xref: /OK3568_Linux_fs/external/xserver/randr/rrmonitor.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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