1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright © 2014 Keith Packard
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Permission to use, copy, modify, distribute, and sell this software and its
5*4882a593Smuzhiyun * documentation for any purpose is hereby granted without fee, provided that
6*4882a593Smuzhiyun * the above copyright notice appear in all copies and that both that copyright
7*4882a593Smuzhiyun * notice and this permission notice appear in supporting documentation, and
8*4882a593Smuzhiyun * that the name of the copyright holders not be used in advertising or
9*4882a593Smuzhiyun * publicity pertaining to distribution of the software without specific,
10*4882a593Smuzhiyun * written prior permission. The copyright holders make no representations
11*4882a593Smuzhiyun * about the suitability of this software for any purpose. It is provided "as
12*4882a593Smuzhiyun * is" without express or implied warranty.
13*4882a593Smuzhiyun *
14*4882a593Smuzhiyun * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15*4882a593Smuzhiyun * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16*4882a593Smuzhiyun * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17*4882a593Smuzhiyun * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18*4882a593Smuzhiyun * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19*4882a593Smuzhiyun * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20*4882a593Smuzhiyun * OF THIS SOFTWARE.
21*4882a593Smuzhiyun */
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun #include "randrstr.h"
24*4882a593Smuzhiyun #include "swaprep.h"
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun static Atom
RRMonitorCrtcName(RRCrtcPtr crtc)27*4882a593Smuzhiyun RRMonitorCrtcName(RRCrtcPtr crtc)
28*4882a593Smuzhiyun {
29*4882a593Smuzhiyun char name[20];
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun if (crtc->numOutputs) {
32*4882a593Smuzhiyun RROutputPtr output = crtc->outputs[0];
33*4882a593Smuzhiyun return MakeAtom(output->name, output->nameLength, TRUE);
34*4882a593Smuzhiyun }
35*4882a593Smuzhiyun sprintf(name, "Monitor-%08lx", (unsigned long int)crtc->id);
36*4882a593Smuzhiyun return MakeAtom(name, strlen(name), TRUE);
37*4882a593Smuzhiyun }
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun static Bool
RRMonitorCrtcPrimary(RRCrtcPtr crtc)40*4882a593Smuzhiyun RRMonitorCrtcPrimary(RRCrtcPtr crtc)
41*4882a593Smuzhiyun {
42*4882a593Smuzhiyun ScreenPtr screen = crtc->pScreen;
43*4882a593Smuzhiyun rrScrPrivPtr pScrPriv = rrGetScrPriv(screen);
44*4882a593Smuzhiyun int o;
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun for (o = 0; o < crtc->numOutputs; o++)
47*4882a593Smuzhiyun if (crtc->outputs[o] == pScrPriv->primaryOutput)
48*4882a593Smuzhiyun return TRUE;
49*4882a593Smuzhiyun return FALSE;
50*4882a593Smuzhiyun }
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun #define DEFAULT_PIXELS_PER_MM (96.0 / 25.4)
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun static void
RRMonitorGetCrtcGeometry(RRCrtcPtr crtc,RRMonitorGeometryPtr geometry)55*4882a593Smuzhiyun RRMonitorGetCrtcGeometry(RRCrtcPtr crtc, RRMonitorGeometryPtr geometry)
56*4882a593Smuzhiyun {
57*4882a593Smuzhiyun ScreenPtr screen = crtc->pScreen;
58*4882a593Smuzhiyun rrScrPrivPtr pScrPriv = rrGetScrPriv(screen);
59*4882a593Smuzhiyun BoxRec panned_area;
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun /* Check to see if crtc is panned and return the full area when applicable. */
62*4882a593Smuzhiyun if (pScrPriv && pScrPriv->rrGetPanning &&
63*4882a593Smuzhiyun pScrPriv->rrGetPanning(screen, crtc, &panned_area, NULL, NULL) &&
64*4882a593Smuzhiyun (panned_area.x2 > panned_area.x1) &&
65*4882a593Smuzhiyun (panned_area.y2 > panned_area.y1)) {
66*4882a593Smuzhiyun geometry->box = panned_area;
67*4882a593Smuzhiyun }
68*4882a593Smuzhiyun else {
69*4882a593Smuzhiyun int width, height;
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun RRCrtcGetScanoutSize(crtc, &width, &height);
72*4882a593Smuzhiyun geometry->box.x1 = crtc->x;
73*4882a593Smuzhiyun geometry->box.y1 = crtc->y;
74*4882a593Smuzhiyun geometry->box.x2 = geometry->box.x1 + width;
75*4882a593Smuzhiyun geometry->box.y2 = geometry->box.y1 + height;
76*4882a593Smuzhiyun }
77*4882a593Smuzhiyun if (crtc->numOutputs && crtc->outputs[0]->mmWidth && crtc->outputs[0]->mmHeight) {
78*4882a593Smuzhiyun RROutputPtr output = crtc->outputs[0];
79*4882a593Smuzhiyun geometry->mmWidth = output->mmWidth;
80*4882a593Smuzhiyun geometry->mmHeight = output->mmHeight;
81*4882a593Smuzhiyun } else {
82*4882a593Smuzhiyun geometry->mmWidth = floor ((geometry->box.x2 - geometry->box.x1) / DEFAULT_PIXELS_PER_MM + 0.5);
83*4882a593Smuzhiyun geometry->mmHeight = floor ((geometry->box.y2 - geometry->box.y1) / DEFAULT_PIXELS_PER_MM + 0.5);
84*4882a593Smuzhiyun }
85*4882a593Smuzhiyun }
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun static Bool
RRMonitorSetFromServer(RRCrtcPtr crtc,RRMonitorPtr monitor)88*4882a593Smuzhiyun RRMonitorSetFromServer(RRCrtcPtr crtc, RRMonitorPtr monitor)
89*4882a593Smuzhiyun {
90*4882a593Smuzhiyun int o;
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun monitor->name = RRMonitorCrtcName(crtc);
93*4882a593Smuzhiyun monitor->pScreen = crtc->pScreen;
94*4882a593Smuzhiyun monitor->numOutputs = crtc->numOutputs;
95*4882a593Smuzhiyun monitor->outputs = calloc(crtc->numOutputs, sizeof(RROutput));
96*4882a593Smuzhiyun if (!monitor->outputs)
97*4882a593Smuzhiyun return FALSE;
98*4882a593Smuzhiyun for (o = 0; o < crtc->numOutputs; o++)
99*4882a593Smuzhiyun monitor->outputs[o] = crtc->outputs[o]->id;
100*4882a593Smuzhiyun monitor->primary = RRMonitorCrtcPrimary(crtc);
101*4882a593Smuzhiyun monitor->automatic = TRUE;
102*4882a593Smuzhiyun RRMonitorGetCrtcGeometry(crtc, &monitor->geometry);
103*4882a593Smuzhiyun return TRUE;
104*4882a593Smuzhiyun }
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun static Bool
RRMonitorAutomaticGeometry(RRMonitorPtr monitor)107*4882a593Smuzhiyun RRMonitorAutomaticGeometry(RRMonitorPtr monitor)
108*4882a593Smuzhiyun {
109*4882a593Smuzhiyun return (monitor->geometry.box.x1 == 0 &&
110*4882a593Smuzhiyun monitor->geometry.box.y1 == 0 &&
111*4882a593Smuzhiyun monitor->geometry.box.x2 == 0 &&
112*4882a593Smuzhiyun monitor->geometry.box.y2 == 0);
113*4882a593Smuzhiyun }
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun static void
RRMonitorGetGeometry(RRMonitorPtr monitor,RRMonitorGeometryPtr geometry)116*4882a593Smuzhiyun RRMonitorGetGeometry(RRMonitorPtr monitor, RRMonitorGeometryPtr geometry)
117*4882a593Smuzhiyun {
118*4882a593Smuzhiyun if (RRMonitorAutomaticGeometry(monitor) && monitor->numOutputs > 0) {
119*4882a593Smuzhiyun ScreenPtr screen = monitor->pScreen;
120*4882a593Smuzhiyun rrScrPrivPtr pScrPriv = rrGetScrPriv(screen);
121*4882a593Smuzhiyun RRMonitorGeometryRec first = { .box = { 0, 0, 0, 0 }, .mmWidth = 0, .mmHeight = 0 };
122*4882a593Smuzhiyun RRMonitorGeometryRec this;
123*4882a593Smuzhiyun int c, o, co;
124*4882a593Smuzhiyun int active_crtcs = 0;
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun *geometry = first;
127*4882a593Smuzhiyun for (o = 0; o < monitor->numOutputs; o++) {
128*4882a593Smuzhiyun RRCrtcPtr crtc = NULL;
129*4882a593Smuzhiyun Bool in_use = FALSE;
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun for (c = 0; !in_use && c < pScrPriv->numCrtcs; c++) {
132*4882a593Smuzhiyun crtc = pScrPriv->crtcs[c];
133*4882a593Smuzhiyun if (!crtc->mode)
134*4882a593Smuzhiyun continue;
135*4882a593Smuzhiyun for (co = 0; !in_use && co < crtc->numOutputs; co++)
136*4882a593Smuzhiyun if (monitor->outputs[o] == crtc->outputs[co]->id)
137*4882a593Smuzhiyun in_use = TRUE;
138*4882a593Smuzhiyun }
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun if (!in_use)
141*4882a593Smuzhiyun continue;
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun RRMonitorGetCrtcGeometry(crtc, &this);
144*4882a593Smuzhiyun
145*4882a593Smuzhiyun if (active_crtcs == 0) {
146*4882a593Smuzhiyun first = this;
147*4882a593Smuzhiyun *geometry = this;
148*4882a593Smuzhiyun } else {
149*4882a593Smuzhiyun geometry->box.x1 = min(this.box.x1, geometry->box.x1);
150*4882a593Smuzhiyun geometry->box.x2 = max(this.box.x2, geometry->box.x2);
151*4882a593Smuzhiyun geometry->box.y1 = min(this.box.y1, geometry->box.y1);
152*4882a593Smuzhiyun geometry->box.y2 = max(this.box.y2, geometry->box.y2);
153*4882a593Smuzhiyun }
154*4882a593Smuzhiyun active_crtcs++;
155*4882a593Smuzhiyun }
156*4882a593Smuzhiyun
157*4882a593Smuzhiyun /* Adjust physical sizes to account for total area */
158*4882a593Smuzhiyun if (active_crtcs > 1 && first.box.x2 != first.box.x1 && first.box.y2 != first.box.y1) {
159*4882a593Smuzhiyun geometry->mmWidth = (this.box.x2 - this.box.x1) / (first.box.x2 - first.box.x1) * first.mmWidth;
160*4882a593Smuzhiyun geometry->mmHeight = (this.box.y2 - this.box.y1) / (first.box.y2 - first.box.y1) * first.mmHeight;
161*4882a593Smuzhiyun }
162*4882a593Smuzhiyun } else {
163*4882a593Smuzhiyun *geometry = monitor->geometry;
164*4882a593Smuzhiyun }
165*4882a593Smuzhiyun }
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun static Bool
RRMonitorSetFromClient(RRMonitorPtr client_monitor,RRMonitorPtr monitor)168*4882a593Smuzhiyun RRMonitorSetFromClient(RRMonitorPtr client_monitor, RRMonitorPtr monitor)
169*4882a593Smuzhiyun {
170*4882a593Smuzhiyun monitor->name = client_monitor->name;
171*4882a593Smuzhiyun monitor->pScreen = client_monitor->pScreen;
172*4882a593Smuzhiyun monitor->numOutputs = client_monitor->numOutputs;
173*4882a593Smuzhiyun monitor->outputs = calloc(client_monitor->numOutputs, sizeof (RROutput));
174*4882a593Smuzhiyun if (!monitor->outputs && client_monitor->numOutputs)
175*4882a593Smuzhiyun return FALSE;
176*4882a593Smuzhiyun memcpy(monitor->outputs, client_monitor->outputs, client_monitor->numOutputs * sizeof (RROutput));
177*4882a593Smuzhiyun monitor->primary = client_monitor->primary;
178*4882a593Smuzhiyun monitor->automatic = client_monitor->automatic;
179*4882a593Smuzhiyun RRMonitorGetGeometry(client_monitor, &monitor->geometry);
180*4882a593Smuzhiyun return TRUE;
181*4882a593Smuzhiyun }
182*4882a593Smuzhiyun
183*4882a593Smuzhiyun typedef struct _rrMonitorList {
184*4882a593Smuzhiyun int num_client;
185*4882a593Smuzhiyun int num_server;
186*4882a593Smuzhiyun RRCrtcPtr *server_crtc;
187*4882a593Smuzhiyun int num_crtcs;
188*4882a593Smuzhiyun int client_primary;
189*4882a593Smuzhiyun int server_primary;
190*4882a593Smuzhiyun } RRMonitorListRec, *RRMonitorListPtr;
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun static Bool
RRMonitorInitList(ScreenPtr screen,RRMonitorListPtr mon_list,Bool get_active)193*4882a593Smuzhiyun RRMonitorInitList(ScreenPtr screen, RRMonitorListPtr mon_list, Bool get_active)
194*4882a593Smuzhiyun {
195*4882a593Smuzhiyun rrScrPrivPtr pScrPriv = rrGetScrPriv(screen);
196*4882a593Smuzhiyun int m, o, c, sc;
197*4882a593Smuzhiyun int numCrtcs;
198*4882a593Smuzhiyun ScreenPtr slave;
199*4882a593Smuzhiyun
200*4882a593Smuzhiyun if (!RRGetInfo(screen, FALSE))
201*4882a593Smuzhiyun return FALSE;
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun /* Count the number of crtcs in this and any slave screens */
204*4882a593Smuzhiyun numCrtcs = pScrPriv->numCrtcs;
205*4882a593Smuzhiyun xorg_list_for_each_entry(slave, &screen->slave_list, slave_head) {
206*4882a593Smuzhiyun rrScrPrivPtr pSlavePriv;
207*4882a593Smuzhiyun
208*4882a593Smuzhiyun if (!slave->is_output_slave)
209*4882a593Smuzhiyun continue;
210*4882a593Smuzhiyun
211*4882a593Smuzhiyun pSlavePriv = rrGetScrPriv(slave);
212*4882a593Smuzhiyun numCrtcs += pSlavePriv->numCrtcs;
213*4882a593Smuzhiyun }
214*4882a593Smuzhiyun mon_list->num_crtcs = numCrtcs;
215*4882a593Smuzhiyun
216*4882a593Smuzhiyun mon_list->server_crtc = calloc(numCrtcs * 2, sizeof (RRCrtcPtr));
217*4882a593Smuzhiyun if (!mon_list->server_crtc)
218*4882a593Smuzhiyun return FALSE;
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun /* Collect pointers to all of the active crtcs */
221*4882a593Smuzhiyun c = 0;
222*4882a593Smuzhiyun for (sc = 0; sc < pScrPriv->numCrtcs; sc++, c++) {
223*4882a593Smuzhiyun if (pScrPriv->crtcs[sc]->mode != NULL)
224*4882a593Smuzhiyun mon_list->server_crtc[c] = pScrPriv->crtcs[sc];
225*4882a593Smuzhiyun }
226*4882a593Smuzhiyun
227*4882a593Smuzhiyun xorg_list_for_each_entry(slave, &screen->slave_list, slave_head) {
228*4882a593Smuzhiyun rrScrPrivPtr pSlavePriv;
229*4882a593Smuzhiyun
230*4882a593Smuzhiyun if (!slave->is_output_slave)
231*4882a593Smuzhiyun continue;
232*4882a593Smuzhiyun
233*4882a593Smuzhiyun pSlavePriv = rrGetScrPriv(slave);
234*4882a593Smuzhiyun for (sc = 0; sc < pSlavePriv->numCrtcs; sc++, c++) {
235*4882a593Smuzhiyun if (pSlavePriv->crtcs[sc]->mode != NULL)
236*4882a593Smuzhiyun mon_list->server_crtc[c] = pSlavePriv->crtcs[sc];
237*4882a593Smuzhiyun }
238*4882a593Smuzhiyun }
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun /* Walk the list of client-defined monitors, clearing the covered
241*4882a593Smuzhiyun * CRTCs from the full list and finding whether one of the
242*4882a593Smuzhiyun * monitors is primary
243*4882a593Smuzhiyun */
244*4882a593Smuzhiyun mon_list->num_client = pScrPriv->numMonitors;
245*4882a593Smuzhiyun mon_list->client_primary = -1;
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun for (m = 0; m < pScrPriv->numMonitors; m++) {
248*4882a593Smuzhiyun RRMonitorPtr monitor = pScrPriv->monitors[m];
249*4882a593Smuzhiyun if (get_active) {
250*4882a593Smuzhiyun RRMonitorGeometryRec geom;
251*4882a593Smuzhiyun
252*4882a593Smuzhiyun RRMonitorGetGeometry(monitor, &geom);
253*4882a593Smuzhiyun if (geom.box.x2 - geom.box.x1 == 0 ||
254*4882a593Smuzhiyun geom.box.y2 - geom.box.y1 == 0) {
255*4882a593Smuzhiyun mon_list->num_client--;
256*4882a593Smuzhiyun continue;
257*4882a593Smuzhiyun }
258*4882a593Smuzhiyun }
259*4882a593Smuzhiyun if (monitor->primary && mon_list->client_primary == -1)
260*4882a593Smuzhiyun mon_list->client_primary = m;
261*4882a593Smuzhiyun for (o = 0; o < monitor->numOutputs; o++) {
262*4882a593Smuzhiyun for (c = 0; c < numCrtcs; c++) {
263*4882a593Smuzhiyun RRCrtcPtr crtc = mon_list->server_crtc[c];
264*4882a593Smuzhiyun if (crtc) {
265*4882a593Smuzhiyun int co;
266*4882a593Smuzhiyun for (co = 0; co < crtc->numOutputs; co++)
267*4882a593Smuzhiyun if (crtc->outputs[co]->id == monitor->outputs[o]) {
268*4882a593Smuzhiyun mon_list->server_crtc[c] = NULL;
269*4882a593Smuzhiyun break;
270*4882a593Smuzhiyun }
271*4882a593Smuzhiyun }
272*4882a593Smuzhiyun }
273*4882a593Smuzhiyun }
274*4882a593Smuzhiyun }
275*4882a593Smuzhiyun
276*4882a593Smuzhiyun /* Now look at the active CRTCs, and count
277*4882a593Smuzhiyun * those not covered by a client monitor, as well
278*4882a593Smuzhiyun * as finding whether one of them is marked primary
279*4882a593Smuzhiyun */
280*4882a593Smuzhiyun mon_list->num_server = 0;
281*4882a593Smuzhiyun mon_list->server_primary = -1;
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun for (c = 0; c < mon_list->num_crtcs; c++) {
284*4882a593Smuzhiyun RRCrtcPtr crtc = mon_list->server_crtc[c];
285*4882a593Smuzhiyun
286*4882a593Smuzhiyun if (!crtc)
287*4882a593Smuzhiyun continue;
288*4882a593Smuzhiyun
289*4882a593Smuzhiyun mon_list->num_server++;
290*4882a593Smuzhiyun
291*4882a593Smuzhiyun if (RRMonitorCrtcPrimary(crtc) && mon_list->server_primary == -1)
292*4882a593Smuzhiyun mon_list->server_primary = c;
293*4882a593Smuzhiyun }
294*4882a593Smuzhiyun return TRUE;
295*4882a593Smuzhiyun }
296*4882a593Smuzhiyun
297*4882a593Smuzhiyun static void
RRMonitorFiniList(RRMonitorListPtr list)298*4882a593Smuzhiyun RRMonitorFiniList(RRMonitorListPtr list)
299*4882a593Smuzhiyun {
300*4882a593Smuzhiyun free(list->server_crtc);
301*4882a593Smuzhiyun }
302*4882a593Smuzhiyun
303*4882a593Smuzhiyun /* Construct a complete list of protocol-visible monitors, including
304*4882a593Smuzhiyun * the manually generated ones as well as those generated
305*4882a593Smuzhiyun * automatically from the remaining CRCTs
306*4882a593Smuzhiyun */
307*4882a593Smuzhiyun
308*4882a593Smuzhiyun Bool
RRMonitorMakeList(ScreenPtr screen,Bool get_active,RRMonitorPtr * monitors_ret,int * nmon_ret)309*4882a593Smuzhiyun RRMonitorMakeList(ScreenPtr screen, Bool get_active, RRMonitorPtr *monitors_ret, int *nmon_ret)
310*4882a593Smuzhiyun {
311*4882a593Smuzhiyun rrScrPrivPtr pScrPriv = rrGetScrPriv(screen);
312*4882a593Smuzhiyun RRMonitorListRec list;
313*4882a593Smuzhiyun int m, c;
314*4882a593Smuzhiyun RRMonitorPtr mon, monitors;
315*4882a593Smuzhiyun Bool has_primary = FALSE;
316*4882a593Smuzhiyun
317*4882a593Smuzhiyun if (!pScrPriv)
318*4882a593Smuzhiyun return FALSE;
319*4882a593Smuzhiyun
320*4882a593Smuzhiyun if (!RRMonitorInitList(screen, &list, get_active))
321*4882a593Smuzhiyun return FALSE;
322*4882a593Smuzhiyun
323*4882a593Smuzhiyun monitors = calloc(list.num_client + list.num_server, sizeof (RRMonitorRec));
324*4882a593Smuzhiyun if (!monitors) {
325*4882a593Smuzhiyun RRMonitorFiniList(&list);
326*4882a593Smuzhiyun return FALSE;
327*4882a593Smuzhiyun }
328*4882a593Smuzhiyun
329*4882a593Smuzhiyun mon = monitors;
330*4882a593Smuzhiyun
331*4882a593Smuzhiyun /* Fill in the primary monitor data first
332*4882a593Smuzhiyun */
333*4882a593Smuzhiyun if (list.client_primary >= 0) {
334*4882a593Smuzhiyun RRMonitorSetFromClient(pScrPriv->monitors[list.client_primary], mon);
335*4882a593Smuzhiyun mon++;
336*4882a593Smuzhiyun } else if (list.server_primary >= 0) {
337*4882a593Smuzhiyun RRMonitorSetFromServer(list.server_crtc[list.server_primary], mon);
338*4882a593Smuzhiyun mon++;
339*4882a593Smuzhiyun }
340*4882a593Smuzhiyun
341*4882a593Smuzhiyun /* Fill in the client-defined monitors next
342*4882a593Smuzhiyun */
343*4882a593Smuzhiyun for (m = 0; m < pScrPriv->numMonitors; m++) {
344*4882a593Smuzhiyun if (m == list.client_primary)
345*4882a593Smuzhiyun continue;
346*4882a593Smuzhiyun if (get_active) {
347*4882a593Smuzhiyun RRMonitorGeometryRec geom;
348*4882a593Smuzhiyun
349*4882a593Smuzhiyun RRMonitorGetGeometry(pScrPriv->monitors[m], &geom);
350*4882a593Smuzhiyun if (geom.box.x2 - geom.box.x1 == 0 ||
351*4882a593Smuzhiyun geom.box.y2 - geom.box.y1 == 0) {
352*4882a593Smuzhiyun continue;
353*4882a593Smuzhiyun }
354*4882a593Smuzhiyun }
355*4882a593Smuzhiyun RRMonitorSetFromClient(pScrPriv->monitors[m], mon);
356*4882a593Smuzhiyun if (has_primary)
357*4882a593Smuzhiyun mon->primary = FALSE;
358*4882a593Smuzhiyun else if (mon->primary)
359*4882a593Smuzhiyun has_primary = TRUE;
360*4882a593Smuzhiyun mon++;
361*4882a593Smuzhiyun }
362*4882a593Smuzhiyun
363*4882a593Smuzhiyun /* And finish with the list of crtc-inspired monitors
364*4882a593Smuzhiyun */
365*4882a593Smuzhiyun for (c = 0; c < list.num_crtcs; c++) {
366*4882a593Smuzhiyun RRCrtcPtr crtc = list.server_crtc[c];
367*4882a593Smuzhiyun if (c == list.server_primary && list.client_primary < 0)
368*4882a593Smuzhiyun continue;
369*4882a593Smuzhiyun
370*4882a593Smuzhiyun if (!list.server_crtc[c])
371*4882a593Smuzhiyun continue;
372*4882a593Smuzhiyun
373*4882a593Smuzhiyun RRMonitorSetFromServer(crtc, mon);
374*4882a593Smuzhiyun if (has_primary)
375*4882a593Smuzhiyun mon->primary = FALSE;
376*4882a593Smuzhiyun else if (mon->primary)
377*4882a593Smuzhiyun has_primary = TRUE;
378*4882a593Smuzhiyun mon++;
379*4882a593Smuzhiyun }
380*4882a593Smuzhiyun
381*4882a593Smuzhiyun RRMonitorFiniList(&list);
382*4882a593Smuzhiyun *nmon_ret = list.num_client + list.num_server;
383*4882a593Smuzhiyun *monitors_ret = monitors;
384*4882a593Smuzhiyun return TRUE;
385*4882a593Smuzhiyun }
386*4882a593Smuzhiyun
387*4882a593Smuzhiyun int
RRMonitorCountList(ScreenPtr screen)388*4882a593Smuzhiyun RRMonitorCountList(ScreenPtr screen)
389*4882a593Smuzhiyun {
390*4882a593Smuzhiyun RRMonitorListRec list;
391*4882a593Smuzhiyun int nmon;
392*4882a593Smuzhiyun
393*4882a593Smuzhiyun if (!RRMonitorInitList(screen, &list, FALSE))
394*4882a593Smuzhiyun return -1;
395*4882a593Smuzhiyun nmon = list.num_client + list.num_server;
396*4882a593Smuzhiyun RRMonitorFiniList(&list);
397*4882a593Smuzhiyun return nmon;
398*4882a593Smuzhiyun }
399*4882a593Smuzhiyun
400*4882a593Smuzhiyun void
RRMonitorFree(RRMonitorPtr monitor)401*4882a593Smuzhiyun RRMonitorFree(RRMonitorPtr monitor)
402*4882a593Smuzhiyun {
403*4882a593Smuzhiyun free(monitor);
404*4882a593Smuzhiyun }
405*4882a593Smuzhiyun
406*4882a593Smuzhiyun RRMonitorPtr
RRMonitorAlloc(int noutput)407*4882a593Smuzhiyun RRMonitorAlloc(int noutput)
408*4882a593Smuzhiyun {
409*4882a593Smuzhiyun RRMonitorPtr monitor;
410*4882a593Smuzhiyun
411*4882a593Smuzhiyun monitor = calloc(1, sizeof (RRMonitorRec) + noutput * sizeof (RROutput));
412*4882a593Smuzhiyun if (!monitor)
413*4882a593Smuzhiyun return NULL;
414*4882a593Smuzhiyun monitor->numOutputs = noutput;
415*4882a593Smuzhiyun monitor->outputs = (RROutput *) (monitor + 1);
416*4882a593Smuzhiyun return monitor;
417*4882a593Smuzhiyun }
418*4882a593Smuzhiyun
419*4882a593Smuzhiyun static int
RRMonitorDelete(ClientPtr client,ScreenPtr screen,Atom name)420*4882a593Smuzhiyun RRMonitorDelete(ClientPtr client, ScreenPtr screen, Atom name)
421*4882a593Smuzhiyun {
422*4882a593Smuzhiyun rrScrPrivPtr pScrPriv = rrGetScrPriv(screen);
423*4882a593Smuzhiyun int m;
424*4882a593Smuzhiyun
425*4882a593Smuzhiyun if (!pScrPriv) {
426*4882a593Smuzhiyun client->errorValue = name;
427*4882a593Smuzhiyun return BadAtom;
428*4882a593Smuzhiyun }
429*4882a593Smuzhiyun
430*4882a593Smuzhiyun for (m = 0; m < pScrPriv->numMonitors; m++) {
431*4882a593Smuzhiyun RRMonitorPtr monitor = pScrPriv->monitors[m];
432*4882a593Smuzhiyun if (monitor->name == name) {
433*4882a593Smuzhiyun memmove(pScrPriv->monitors + m, pScrPriv->monitors + m + 1,
434*4882a593Smuzhiyun (pScrPriv->numMonitors - (m + 1)) * sizeof (RRMonitorPtr));
435*4882a593Smuzhiyun --pScrPriv->numMonitors;
436*4882a593Smuzhiyun RRMonitorFree(monitor);
437*4882a593Smuzhiyun return Success;
438*4882a593Smuzhiyun }
439*4882a593Smuzhiyun }
440*4882a593Smuzhiyun
441*4882a593Smuzhiyun client->errorValue = name;
442*4882a593Smuzhiyun return BadValue;
443*4882a593Smuzhiyun }
444*4882a593Smuzhiyun
445*4882a593Smuzhiyun static Bool
RRMonitorMatchesOutputName(ScreenPtr screen,Atom name)446*4882a593Smuzhiyun RRMonitorMatchesOutputName(ScreenPtr screen, Atom name)
447*4882a593Smuzhiyun {
448*4882a593Smuzhiyun rrScrPrivPtr pScrPriv = rrGetScrPriv(screen);
449*4882a593Smuzhiyun int o;
450*4882a593Smuzhiyun const char *str = NameForAtom(name);
451*4882a593Smuzhiyun int len = strlen(str);
452*4882a593Smuzhiyun
453*4882a593Smuzhiyun for (o = 0; o < pScrPriv->numOutputs; o++) {
454*4882a593Smuzhiyun RROutputPtr output = pScrPriv->outputs[o];
455*4882a593Smuzhiyun
456*4882a593Smuzhiyun if (output->nameLength == len && !memcmp(output->name, str, len))
457*4882a593Smuzhiyun return TRUE;
458*4882a593Smuzhiyun }
459*4882a593Smuzhiyun return FALSE;
460*4882a593Smuzhiyun }
461*4882a593Smuzhiyun
462*4882a593Smuzhiyun int
RRMonitorAdd(ClientPtr client,ScreenPtr screen,RRMonitorPtr monitor)463*4882a593Smuzhiyun RRMonitorAdd(ClientPtr client, ScreenPtr screen, RRMonitorPtr monitor)
464*4882a593Smuzhiyun {
465*4882a593Smuzhiyun rrScrPrivPtr pScrPriv = rrGetScrPriv(screen);
466*4882a593Smuzhiyun int m;
467*4882a593Smuzhiyun ScreenPtr slave;
468*4882a593Smuzhiyun RRMonitorPtr *monitors;
469*4882a593Smuzhiyun
470*4882a593Smuzhiyun if (!pScrPriv)
471*4882a593Smuzhiyun return BadAlloc;
472*4882a593Smuzhiyun
473*4882a593Smuzhiyun /* 'name' must not match the name of any Output on the screen, or
474*4882a593Smuzhiyun * a Value error results.
475*4882a593Smuzhiyun */
476*4882a593Smuzhiyun
477*4882a593Smuzhiyun if (RRMonitorMatchesOutputName(screen, monitor->name)) {
478*4882a593Smuzhiyun client->errorValue = monitor->name;
479*4882a593Smuzhiyun return BadValue;
480*4882a593Smuzhiyun }
481*4882a593Smuzhiyun
482*4882a593Smuzhiyun xorg_list_for_each_entry(slave, &screen->slave_list, slave_head) {
483*4882a593Smuzhiyun if (!slave->is_output_slave)
484*4882a593Smuzhiyun continue;
485*4882a593Smuzhiyun
486*4882a593Smuzhiyun if (RRMonitorMatchesOutputName(slave, monitor->name)) {
487*4882a593Smuzhiyun client->errorValue = monitor->name;
488*4882a593Smuzhiyun return BadValue;
489*4882a593Smuzhiyun }
490*4882a593Smuzhiyun }
491*4882a593Smuzhiyun
492*4882a593Smuzhiyun /* 'name' must not match the name of any Monitor on the screen, or
493*4882a593Smuzhiyun * a Value error results.
494*4882a593Smuzhiyun */
495*4882a593Smuzhiyun
496*4882a593Smuzhiyun for (m = 0; m < pScrPriv->numMonitors; m++) {
497*4882a593Smuzhiyun if (pScrPriv->monitors[m]->name == monitor->name) {
498*4882a593Smuzhiyun client->errorValue = monitor->name;
499*4882a593Smuzhiyun return BadValue;
500*4882a593Smuzhiyun }
501*4882a593Smuzhiyun }
502*4882a593Smuzhiyun
503*4882a593Smuzhiyun /* Allocate space for the new pointer. This is done before
504*4882a593Smuzhiyun * removing matching monitors as it may fail, and the request
505*4882a593Smuzhiyun * needs to not have any side-effects on failure
506*4882a593Smuzhiyun */
507*4882a593Smuzhiyun if (pScrPriv->numMonitors)
508*4882a593Smuzhiyun monitors = reallocarray(pScrPriv->monitors,
509*4882a593Smuzhiyun pScrPriv->numMonitors + 1,
510*4882a593Smuzhiyun sizeof (RRMonitorPtr));
511*4882a593Smuzhiyun else
512*4882a593Smuzhiyun monitors = malloc(sizeof (RRMonitorPtr));
513*4882a593Smuzhiyun
514*4882a593Smuzhiyun if (!monitors)
515*4882a593Smuzhiyun return BadAlloc;
516*4882a593Smuzhiyun
517*4882a593Smuzhiyun pScrPriv->monitors = monitors;
518*4882a593Smuzhiyun
519*4882a593Smuzhiyun for (m = 0; m < pScrPriv->numMonitors; m++) {
520*4882a593Smuzhiyun RRMonitorPtr existing = pScrPriv->monitors[m];
521*4882a593Smuzhiyun int o, eo;
522*4882a593Smuzhiyun
523*4882a593Smuzhiyun /* If 'name' matches an existing Monitor on the screen, the
524*4882a593Smuzhiyun * existing one will be deleted as if RRDeleteMonitor were called.
525*4882a593Smuzhiyun */
526*4882a593Smuzhiyun if (existing->name == monitor->name) {
527*4882a593Smuzhiyun (void) RRMonitorDelete(client, screen, existing->name);
528*4882a593Smuzhiyun continue;
529*4882a593Smuzhiyun }
530*4882a593Smuzhiyun
531*4882a593Smuzhiyun /* For each output in 'info.outputs', each one is removed from all
532*4882a593Smuzhiyun * pre-existing Monitors. If removing the output causes the list
533*4882a593Smuzhiyun * of outputs for that Monitor to become empty, then that
534*4882a593Smuzhiyun * Monitor will be deleted as if RRDeleteMonitor were called.
535*4882a593Smuzhiyun */
536*4882a593Smuzhiyun
537*4882a593Smuzhiyun for (eo = 0; eo < existing->numOutputs; eo++) {
538*4882a593Smuzhiyun for (o = 0; o < monitor->numOutputs; o++) {
539*4882a593Smuzhiyun if (monitor->outputs[o] == existing->outputs[eo]) {
540*4882a593Smuzhiyun memmove(existing->outputs + eo, existing->outputs + eo + 1,
541*4882a593Smuzhiyun (existing->numOutputs - (eo + 1)) * sizeof (RROutput));
542*4882a593Smuzhiyun --existing->numOutputs;
543*4882a593Smuzhiyun --eo;
544*4882a593Smuzhiyun break;
545*4882a593Smuzhiyun }
546*4882a593Smuzhiyun }
547*4882a593Smuzhiyun if (existing->numOutputs == 0) {
548*4882a593Smuzhiyun (void) RRMonitorDelete(client, screen, existing->name);
549*4882a593Smuzhiyun break;
550*4882a593Smuzhiyun }
551*4882a593Smuzhiyun }
552*4882a593Smuzhiyun if (monitor->primary)
553*4882a593Smuzhiyun existing->primary = FALSE;
554*4882a593Smuzhiyun }
555*4882a593Smuzhiyun
556*4882a593Smuzhiyun /* Add the new one to the list
557*4882a593Smuzhiyun */
558*4882a593Smuzhiyun pScrPriv->monitors[pScrPriv->numMonitors++] = monitor;
559*4882a593Smuzhiyun
560*4882a593Smuzhiyun return Success;
561*4882a593Smuzhiyun }
562*4882a593Smuzhiyun
563*4882a593Smuzhiyun void
RRMonitorFreeList(RRMonitorPtr monitors,int nmon)564*4882a593Smuzhiyun RRMonitorFreeList(RRMonitorPtr monitors, int nmon)
565*4882a593Smuzhiyun {
566*4882a593Smuzhiyun int m;
567*4882a593Smuzhiyun
568*4882a593Smuzhiyun for (m = 0; m < nmon; m++)
569*4882a593Smuzhiyun free(monitors[m].outputs);
570*4882a593Smuzhiyun free(monitors);
571*4882a593Smuzhiyun }
572*4882a593Smuzhiyun
573*4882a593Smuzhiyun void
RRMonitorInit(ScreenPtr screen)574*4882a593Smuzhiyun RRMonitorInit(ScreenPtr screen)
575*4882a593Smuzhiyun {
576*4882a593Smuzhiyun rrScrPrivPtr pScrPriv = rrGetScrPriv(screen);
577*4882a593Smuzhiyun
578*4882a593Smuzhiyun if (!pScrPriv)
579*4882a593Smuzhiyun return;
580*4882a593Smuzhiyun
581*4882a593Smuzhiyun pScrPriv->numMonitors = 0;
582*4882a593Smuzhiyun pScrPriv->monitors = NULL;
583*4882a593Smuzhiyun }
584*4882a593Smuzhiyun
585*4882a593Smuzhiyun void
RRMonitorClose(ScreenPtr screen)586*4882a593Smuzhiyun RRMonitorClose(ScreenPtr screen)
587*4882a593Smuzhiyun {
588*4882a593Smuzhiyun rrScrPrivPtr pScrPriv = rrGetScrPriv(screen);
589*4882a593Smuzhiyun int m;
590*4882a593Smuzhiyun
591*4882a593Smuzhiyun if (!pScrPriv)
592*4882a593Smuzhiyun return;
593*4882a593Smuzhiyun
594*4882a593Smuzhiyun for (m = 0; m < pScrPriv->numMonitors; m++)
595*4882a593Smuzhiyun RRMonitorFree(pScrPriv->monitors[m]);
596*4882a593Smuzhiyun free(pScrPriv->monitors);
597*4882a593Smuzhiyun pScrPriv->monitors = NULL;
598*4882a593Smuzhiyun pScrPriv->numMonitors = 0;
599*4882a593Smuzhiyun }
600*4882a593Smuzhiyun
601*4882a593Smuzhiyun static CARD32
RRMonitorTimestamp(ScreenPtr screen)602*4882a593Smuzhiyun RRMonitorTimestamp(ScreenPtr screen)
603*4882a593Smuzhiyun {
604*4882a593Smuzhiyun rrScrPrivPtr pScrPriv = rrGetScrPriv(screen);
605*4882a593Smuzhiyun
606*4882a593Smuzhiyun /* XXX should take client monitor changes into account */
607*4882a593Smuzhiyun return pScrPriv->lastConfigTime.milliseconds;
608*4882a593Smuzhiyun }
609*4882a593Smuzhiyun
610*4882a593Smuzhiyun int
ProcRRGetMonitors(ClientPtr client)611*4882a593Smuzhiyun ProcRRGetMonitors(ClientPtr client)
612*4882a593Smuzhiyun {
613*4882a593Smuzhiyun REQUEST(xRRGetMonitorsReq);
614*4882a593Smuzhiyun xRRGetMonitorsReply rep = {
615*4882a593Smuzhiyun .type = X_Reply,
616*4882a593Smuzhiyun .sequenceNumber = client->sequence,
617*4882a593Smuzhiyun .length = 0,
618*4882a593Smuzhiyun };
619*4882a593Smuzhiyun WindowPtr window;
620*4882a593Smuzhiyun ScreenPtr screen;
621*4882a593Smuzhiyun int r;
622*4882a593Smuzhiyun RRMonitorPtr monitors;
623*4882a593Smuzhiyun int nmonitors;
624*4882a593Smuzhiyun int noutputs;
625*4882a593Smuzhiyun int m;
626*4882a593Smuzhiyun Bool get_active;
627*4882a593Smuzhiyun REQUEST_SIZE_MATCH(xRRGetMonitorsReq);
628*4882a593Smuzhiyun r = dixLookupWindow(&window, stuff->window, client, DixGetAttrAccess);
629*4882a593Smuzhiyun if (r != Success)
630*4882a593Smuzhiyun return r;
631*4882a593Smuzhiyun screen = window->drawable.pScreen;
632*4882a593Smuzhiyun
633*4882a593Smuzhiyun get_active = stuff->get_active;
634*4882a593Smuzhiyun if (!RRMonitorMakeList(screen, get_active, &monitors, &nmonitors))
635*4882a593Smuzhiyun return BadAlloc;
636*4882a593Smuzhiyun
637*4882a593Smuzhiyun rep.timestamp = RRMonitorTimestamp(screen);
638*4882a593Smuzhiyun
639*4882a593Smuzhiyun noutputs = 0;
640*4882a593Smuzhiyun for (m = 0; m < nmonitors; m++) {
641*4882a593Smuzhiyun rep.length += SIZEOF(xRRMonitorInfo) >> 2;
642*4882a593Smuzhiyun rep.length += monitors[m].numOutputs;
643*4882a593Smuzhiyun noutputs += monitors[m].numOutputs;
644*4882a593Smuzhiyun }
645*4882a593Smuzhiyun
646*4882a593Smuzhiyun rep.nmonitors = nmonitors;
647*4882a593Smuzhiyun rep.noutputs = noutputs;
648*4882a593Smuzhiyun
649*4882a593Smuzhiyun if (client->swapped) {
650*4882a593Smuzhiyun swaps(&rep.sequenceNumber);
651*4882a593Smuzhiyun swapl(&rep.length);
652*4882a593Smuzhiyun swapl(&rep.timestamp);
653*4882a593Smuzhiyun swapl(&rep.nmonitors);
654*4882a593Smuzhiyun swapl(&rep.noutputs);
655*4882a593Smuzhiyun }
656*4882a593Smuzhiyun WriteToClient(client, sizeof(xRRGetMonitorsReply), &rep);
657*4882a593Smuzhiyun
658*4882a593Smuzhiyun client->pSwapReplyFunc = (ReplySwapPtr) CopySwap32Write;
659*4882a593Smuzhiyun
660*4882a593Smuzhiyun for (m = 0; m < nmonitors; m++) {
661*4882a593Smuzhiyun RRMonitorPtr monitor = &monitors[m];
662*4882a593Smuzhiyun xRRMonitorInfo info = {
663*4882a593Smuzhiyun .name = monitor->name,
664*4882a593Smuzhiyun .primary = monitor->primary,
665*4882a593Smuzhiyun .automatic = monitor->automatic,
666*4882a593Smuzhiyun .noutput = monitor->numOutputs,
667*4882a593Smuzhiyun .x = monitor->geometry.box.x1,
668*4882a593Smuzhiyun .y = monitor->geometry.box.y1,
669*4882a593Smuzhiyun .width = monitor->geometry.box.x2 - monitor->geometry.box.x1,
670*4882a593Smuzhiyun .height = monitor->geometry.box.y2 - monitor->geometry.box.y1,
671*4882a593Smuzhiyun .widthInMillimeters = monitor->geometry.mmWidth,
672*4882a593Smuzhiyun .heightInMillimeters = monitor->geometry.mmHeight,
673*4882a593Smuzhiyun };
674*4882a593Smuzhiyun if (client->swapped) {
675*4882a593Smuzhiyun swapl(&info.name);
676*4882a593Smuzhiyun swaps(&info.noutput);
677*4882a593Smuzhiyun swaps(&info.x);
678*4882a593Smuzhiyun swaps(&info.y);
679*4882a593Smuzhiyun swaps(&info.width);
680*4882a593Smuzhiyun swaps(&info.height);
681*4882a593Smuzhiyun swapl(&info.widthInMillimeters);
682*4882a593Smuzhiyun swapl(&info.heightInMillimeters);
683*4882a593Smuzhiyun }
684*4882a593Smuzhiyun
685*4882a593Smuzhiyun WriteToClient(client, sizeof(xRRMonitorInfo), &info);
686*4882a593Smuzhiyun WriteSwappedDataToClient(client, monitor->numOutputs * sizeof (RROutput), monitor->outputs);
687*4882a593Smuzhiyun }
688*4882a593Smuzhiyun
689*4882a593Smuzhiyun RRMonitorFreeList(monitors, nmonitors);
690*4882a593Smuzhiyun
691*4882a593Smuzhiyun return Success;
692*4882a593Smuzhiyun }
693*4882a593Smuzhiyun
694*4882a593Smuzhiyun int
ProcRRSetMonitor(ClientPtr client)695*4882a593Smuzhiyun ProcRRSetMonitor(ClientPtr client)
696*4882a593Smuzhiyun {
697*4882a593Smuzhiyun REQUEST(xRRSetMonitorReq);
698*4882a593Smuzhiyun WindowPtr window;
699*4882a593Smuzhiyun ScreenPtr screen;
700*4882a593Smuzhiyun RRMonitorPtr monitor;
701*4882a593Smuzhiyun int r;
702*4882a593Smuzhiyun
703*4882a593Smuzhiyun REQUEST_AT_LEAST_SIZE(xRRSetMonitorReq);
704*4882a593Smuzhiyun
705*4882a593Smuzhiyun if (stuff->monitor.noutput != stuff->length - (SIZEOF(xRRSetMonitorReq) >> 2))
706*4882a593Smuzhiyun return BadLength;
707*4882a593Smuzhiyun
708*4882a593Smuzhiyun r = dixLookupWindow(&window, stuff->window, client, DixGetAttrAccess);
709*4882a593Smuzhiyun if (r != Success)
710*4882a593Smuzhiyun return r;
711*4882a593Smuzhiyun screen = window->drawable.pScreen;
712*4882a593Smuzhiyun
713*4882a593Smuzhiyun if (!ValidAtom(stuff->monitor.name))
714*4882a593Smuzhiyun return BadAtom;
715*4882a593Smuzhiyun
716*4882a593Smuzhiyun /* Allocate the new monitor */
717*4882a593Smuzhiyun monitor = RRMonitorAlloc(stuff->monitor.noutput);
718*4882a593Smuzhiyun if (!monitor)
719*4882a593Smuzhiyun return BadAlloc;
720*4882a593Smuzhiyun
721*4882a593Smuzhiyun /* Fill in the bits from the request */
722*4882a593Smuzhiyun monitor->pScreen = screen;
723*4882a593Smuzhiyun monitor->name = stuff->monitor.name;
724*4882a593Smuzhiyun monitor->primary = stuff->monitor.primary;
725*4882a593Smuzhiyun monitor->automatic = FALSE;
726*4882a593Smuzhiyun memcpy(monitor->outputs, stuff + 1, stuff->monitor.noutput * sizeof (RROutput));
727*4882a593Smuzhiyun monitor->geometry.box.x1 = stuff->monitor.x;
728*4882a593Smuzhiyun monitor->geometry.box.y1 = stuff->monitor.y;
729*4882a593Smuzhiyun monitor->geometry.box.x2 = stuff->monitor.x + stuff->monitor.width;
730*4882a593Smuzhiyun monitor->geometry.box.y2 = stuff->monitor.y + stuff->monitor.height;
731*4882a593Smuzhiyun monitor->geometry.mmWidth = stuff->monitor.widthInMillimeters;
732*4882a593Smuzhiyun monitor->geometry.mmHeight = stuff->monitor.heightInMillimeters;
733*4882a593Smuzhiyun
734*4882a593Smuzhiyun r = RRMonitorAdd(client, screen, monitor);
735*4882a593Smuzhiyun if (r == Success)
736*4882a593Smuzhiyun RRSendConfigNotify(screen);
737*4882a593Smuzhiyun else
738*4882a593Smuzhiyun RRMonitorFree(monitor);
739*4882a593Smuzhiyun return r;
740*4882a593Smuzhiyun }
741*4882a593Smuzhiyun
742*4882a593Smuzhiyun int
ProcRRDeleteMonitor(ClientPtr client)743*4882a593Smuzhiyun ProcRRDeleteMonitor(ClientPtr client)
744*4882a593Smuzhiyun {
745*4882a593Smuzhiyun REQUEST(xRRDeleteMonitorReq);
746*4882a593Smuzhiyun WindowPtr window;
747*4882a593Smuzhiyun ScreenPtr screen;
748*4882a593Smuzhiyun int r;
749*4882a593Smuzhiyun
750*4882a593Smuzhiyun REQUEST_SIZE_MATCH(xRRDeleteMonitorReq);
751*4882a593Smuzhiyun r = dixLookupWindow(&window, stuff->window, client, DixGetAttrAccess);
752*4882a593Smuzhiyun if (r != Success)
753*4882a593Smuzhiyun return r;
754*4882a593Smuzhiyun screen = window->drawable.pScreen;
755*4882a593Smuzhiyun
756*4882a593Smuzhiyun if (!ValidAtom(stuff->name)) {
757*4882a593Smuzhiyun client->errorValue = stuff->name;
758*4882a593Smuzhiyun return BadAtom;
759*4882a593Smuzhiyun }
760*4882a593Smuzhiyun
761*4882a593Smuzhiyun r = RRMonitorDelete(client, screen, stuff->name);
762*4882a593Smuzhiyun if (r == Success)
763*4882a593Smuzhiyun RRSendConfigNotify(screen);
764*4882a593Smuzhiyun return r;
765*4882a593Smuzhiyun }
766