xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

rrmonitor.c (23653B)


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