xserver

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

pseudoramiX.c (13798B)


      1 /*
      2  * Minimal implementation of PanoramiX/Xinerama
      3  *
      4  * This is used in rootless mode where the underlying window server
      5  * already provides an abstracted view of multiple screens as one
      6  * large screen area.
      7  *
      8  * This code is largely based on panoramiX.c, which contains the
      9  * following copyright notice:
     10  */
     11 /*****************************************************************
     12    Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
     13    Permission is hereby granted, free of charge, to any person obtaining a copy
     14    of this software and associated documentation files (the "Software"), to deal
     15    in the Software without restriction, including without limitation the rights
     16    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     17    copies of the Software.
     18 
     19    The above copyright notice and this permission notice shall be included in
     20    all copies or substantial portions of the Software.
     21 
     22    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     23    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     24    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     25    DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
     26    BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
     27    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
     28    IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     29 
     30    Except as contained in this notice, the name of Digital Equipment Corporation
     31    shall not be used in advertising or otherwise to promote the sale, use or other
     32    dealings in this Software without prior written authorization from Digital
     33    Equipment Corporation.
     34  ******************************************************************/
     35 
     36 #ifdef HAVE_DIX_CONFIG_H
     37 #include <dix-config.h>
     38 #endif
     39 
     40 #include "pseudoramiX.h"
     41 #include "extnsionst.h"
     42 #include "nonsdk_extinit.h"
     43 #include "dixstruct.h"
     44 #include "window.h"
     45 #include <X11/extensions/panoramiXproto.h>
     46 #include "globals.h"
     47 
     48 #define TRACE PseudoramiXTrace("TRACE " __FILE__ ":%s",__FUNCTION__)
     49 #define DEBUG_LOG PseudoramiXDebug
     50 
     51 Bool noPseudoramiXExtension = FALSE;
     52 extern Bool noRRXineramaExtension;
     53 
     54 extern int
     55 ProcPanoramiXQueryVersion(ClientPtr client);
     56 
     57 static void
     58 PseudoramiXResetProc(ExtensionEntry *extEntry);
     59 
     60 static int
     61 ProcPseudoramiXQueryVersion(ClientPtr client);
     62 static int
     63 ProcPseudoramiXGetState(ClientPtr client);
     64 static int
     65 ProcPseudoramiXGetScreenCount(ClientPtr client);
     66 static int
     67 ProcPseudoramiXGetScreenSize(ClientPtr client);
     68 static int
     69 ProcPseudoramiXIsActive(ClientPtr client);
     70 static int
     71 ProcPseudoramiXQueryScreens(ClientPtr client);
     72 static int
     73 ProcPseudoramiXDispatch(ClientPtr client);
     74 
     75 static int
     76 SProcPseudoramiXQueryVersion(ClientPtr client);
     77 static int
     78 SProcPseudoramiXGetState(ClientPtr client);
     79 static int
     80 SProcPseudoramiXGetScreenCount(ClientPtr client);
     81 static int
     82 SProcPseudoramiXGetScreenSize(ClientPtr client);
     83 static int
     84 SProcPseudoramiXIsActive(ClientPtr client);
     85 static int
     86 SProcPseudoramiXQueryScreens(ClientPtr client);
     87 static int
     88 SProcPseudoramiXDispatch(ClientPtr client);
     89 
     90 typedef struct {
     91     int x;
     92     int y;
     93     int w;
     94     int h;
     95 } PseudoramiXScreenRec;
     96 
     97 static PseudoramiXScreenRec *pseudoramiXScreens = NULL;
     98 static int pseudoramiXScreensAllocated = 0;
     99 static int pseudoramiXNumScreens = 0;
    100 static unsigned long pseudoramiXGeneration = 0;
    101 
    102 static void
    103 PseudoramiXTrace(const char *format, ...)
    104     _X_ATTRIBUTE_PRINTF(1, 2);
    105 
    106 static void
    107 PseudoramiXTrace(const char *format, ...)
    108 {
    109     va_list ap;
    110 
    111     va_start(ap, format);
    112     LogVMessageVerb(X_NONE, 10, format, ap);
    113     va_end(ap);
    114 }
    115 
    116 static void
    117 PseudoramiXDebug(const char *format, ...)
    118     _X_ATTRIBUTE_PRINTF(1, 2);
    119 
    120 static void
    121 PseudoramiXDebug(const char *format, ...)
    122 {
    123     va_list ap;
    124 
    125     va_start(ap, format);
    126     LogVMessageVerb(X_NONE, 3, format, ap);
    127     va_end(ap);
    128 }
    129 
    130 // Add a PseudoramiX screen.
    131 // The rest of the X server will know nothing about this screen.
    132 // Can be called before or after extension init.
    133 // Screens must be re-added once per generation.
    134 void
    135 PseudoramiXAddScreen(int x, int y, int w, int h)
    136 {
    137     PseudoramiXScreenRec *s;
    138 
    139     if (noPseudoramiXExtension) return;
    140 
    141     if (pseudoramiXNumScreens == pseudoramiXScreensAllocated) {
    142         pseudoramiXScreensAllocated += pseudoramiXScreensAllocated + 1;
    143         pseudoramiXScreens = reallocarray(pseudoramiXScreens,
    144                                           pseudoramiXScreensAllocated,
    145                                           sizeof(PseudoramiXScreenRec));
    146     }
    147 
    148     DEBUG_LOG("x: %d, y: %d, w: %d, h: %d\n", x, y, w, h);
    149 
    150     s = &pseudoramiXScreens[pseudoramiXNumScreens++];
    151     s->x = x;
    152     s->y = y;
    153     s->w = w;
    154     s->h = h;
    155 }
    156 
    157 // Initialize PseudoramiX.
    158 // Copied from PanoramiXExtensionInit
    159 void
    160 PseudoramiXExtensionInit(void)
    161 {
    162     Bool success = FALSE;
    163     ExtensionEntry      *extEntry;
    164 
    165     if (noPseudoramiXExtension) return;
    166 
    167     TRACE;
    168 
    169     /* Even with only one screen we need to enable PseudoramiX to allow
    170        dynamic screen configuration changes. */
    171 #if 0
    172     if (pseudoramiXNumScreens == 1) {
    173         // Only one screen - disable Xinerama extension.
    174         noPseudoramiXExtension = TRUE;
    175         return;
    176     }
    177 #endif
    178 
    179     if (pseudoramiXGeneration != serverGeneration) {
    180         extEntry = AddExtension(PANORAMIX_PROTOCOL_NAME, 0, 0,
    181                                 ProcPseudoramiXDispatch,
    182                                 SProcPseudoramiXDispatch,
    183                                 PseudoramiXResetProc,
    184                                 StandardMinorOpcode);
    185         if (!extEntry) {
    186             ErrorF("PseudoramiXExtensionInit(): AddExtension failed\n");
    187         }
    188         else {
    189             pseudoramiXGeneration = serverGeneration;
    190             success = TRUE;
    191         }
    192     }
    193 
    194     /* Do not allow RRXinerama to initialize if we did */
    195     noRRXineramaExtension = success;
    196 
    197     if (!success) {
    198         ErrorF("%s Extension (PseudoramiX) failed to initialize\n",
    199                PANORAMIX_PROTOCOL_NAME);
    200         return;
    201     }
    202 }
    203 
    204 void
    205 PseudoramiXResetScreens(void)
    206 {
    207     TRACE;
    208 
    209     pseudoramiXNumScreens = 0;
    210 }
    211 
    212 static void
    213 PseudoramiXResetProc(ExtensionEntry *extEntry)
    214 {
    215     TRACE;
    216 
    217     PseudoramiXResetScreens();
    218 }
    219 
    220 // was PanoramiX
    221 static int
    222 ProcPseudoramiXQueryVersion(ClientPtr client)
    223 {
    224     TRACE;
    225 
    226     return ProcPanoramiXQueryVersion(client);
    227 }
    228 
    229 // was PanoramiX
    230 static int
    231 ProcPseudoramiXGetState(ClientPtr client)
    232 {
    233     REQUEST(xPanoramiXGetStateReq);
    234     WindowPtr pWin;
    235     xPanoramiXGetStateReply rep;
    236     register int rc;
    237 
    238     TRACE;
    239 
    240     REQUEST_SIZE_MATCH(xPanoramiXGetStateReq);
    241     rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
    242     if (rc != Success)
    243         return rc;
    244 
    245     rep.type = X_Reply;
    246     rep.length = 0;
    247     rep.sequenceNumber = client->sequence;
    248     rep.state = !noPseudoramiXExtension;
    249     rep.window = stuff->window;
    250     if (client->swapped) {
    251         swaps(&rep.sequenceNumber);
    252         swapl(&rep.length);
    253         swapl(&rep.window);
    254     }
    255     WriteToClient(client, sizeof(xPanoramiXGetStateReply),&rep);
    256     return Success;
    257 }
    258 
    259 // was PanoramiX
    260 static int
    261 ProcPseudoramiXGetScreenCount(ClientPtr client)
    262 {
    263     REQUEST(xPanoramiXGetScreenCountReq);
    264     WindowPtr pWin;
    265     xPanoramiXGetScreenCountReply rep;
    266     register int rc;
    267 
    268     TRACE;
    269 
    270     REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq);
    271     rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
    272     if (rc != Success)
    273         return rc;
    274 
    275     rep.type = X_Reply;
    276     rep.length = 0;
    277     rep.sequenceNumber = client->sequence;
    278     rep.ScreenCount = pseudoramiXNumScreens;
    279     rep.window = stuff->window;
    280     if (client->swapped) {
    281         swaps(&rep.sequenceNumber);
    282         swapl(&rep.length);
    283         swapl(&rep.window);
    284     }
    285     WriteToClient(client, sizeof(xPanoramiXGetScreenCountReply),&rep);
    286     return Success;
    287 }
    288 
    289 // was PanoramiX
    290 static int
    291 ProcPseudoramiXGetScreenSize(ClientPtr client)
    292 {
    293     REQUEST(xPanoramiXGetScreenSizeReq);
    294     WindowPtr pWin;
    295     xPanoramiXGetScreenSizeReply rep;
    296     register int rc;
    297 
    298     TRACE;
    299 
    300     REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq);
    301 
    302     if (stuff->screen >= pseudoramiXNumScreens)
    303       return BadMatch;
    304 
    305     rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
    306     if (rc != Success)
    307         return rc;
    308 
    309     rep.type = X_Reply;
    310     rep.length = 0;
    311     rep.sequenceNumber = client->sequence;
    312     /* screen dimensions */
    313     rep.width = pseudoramiXScreens[stuff->screen].w;
    314     // was screenInfo.screens[stuff->screen]->width;
    315     rep.height = pseudoramiXScreens[stuff->screen].h;
    316     // was screenInfo.screens[stuff->screen]->height;
    317     rep.window = stuff->window;
    318     rep.screen = stuff->screen;
    319     if (client->swapped) {
    320         swaps(&rep.sequenceNumber);
    321         swapl(&rep.length);
    322         swapl(&rep.width);
    323         swapl(&rep.height);
    324         swapl(&rep.window);
    325         swapl(&rep.screen);
    326     }
    327     WriteToClient(client, sizeof(xPanoramiXGetScreenSizeReply),&rep);
    328     return Success;
    329 }
    330 
    331 // was Xinerama
    332 static int
    333 ProcPseudoramiXIsActive(ClientPtr client)
    334 {
    335     /* REQUEST(xXineramaIsActiveReq); */
    336     xXineramaIsActiveReply rep;
    337 
    338     TRACE;
    339 
    340     REQUEST_SIZE_MATCH(xXineramaIsActiveReq);
    341 
    342     rep.type = X_Reply;
    343     rep.length = 0;
    344     rep.sequenceNumber = client->sequence;
    345     rep.state = !noPseudoramiXExtension;
    346     if (client->swapped) {
    347         swaps(&rep.sequenceNumber);
    348         swapl(&rep.length);
    349         swapl(&rep.state);
    350     }
    351     WriteToClient(client, sizeof(xXineramaIsActiveReply),&rep);
    352     return Success;
    353 }
    354 
    355 // was Xinerama
    356 static int
    357 ProcPseudoramiXQueryScreens(ClientPtr client)
    358 {
    359     /* REQUEST(xXineramaQueryScreensReq); */
    360     xXineramaQueryScreensReply rep;
    361 
    362     DEBUG_LOG("noPseudoramiXExtension=%d, pseudoramiXNumScreens=%d\n",
    363               noPseudoramiXExtension,
    364               pseudoramiXNumScreens);
    365 
    366     REQUEST_SIZE_MATCH(xXineramaQueryScreensReq);
    367 
    368     rep.type = X_Reply;
    369     rep.sequenceNumber = client->sequence;
    370     rep.number = noPseudoramiXExtension ? 0 : pseudoramiXNumScreens;
    371     rep.length = bytes_to_int32(rep.number * sz_XineramaScreenInfo);
    372     if (client->swapped) {
    373         swaps(&rep.sequenceNumber);
    374         swapl(&rep.length);
    375         swapl(&rep.number);
    376     }
    377     WriteToClient(client, sizeof(xXineramaQueryScreensReply),&rep);
    378 
    379     if (!noPseudoramiXExtension) {
    380         xXineramaScreenInfo scratch;
    381         int i;
    382 
    383         for (i = 0; i < pseudoramiXNumScreens; i++) {
    384             scratch.x_org = pseudoramiXScreens[i].x;
    385             scratch.y_org = pseudoramiXScreens[i].y;
    386             scratch.width = pseudoramiXScreens[i].w;
    387             scratch.height = pseudoramiXScreens[i].h;
    388 
    389             if (client->swapped) {
    390                 swaps(&scratch.x_org);
    391                 swaps(&scratch.y_org);
    392                 swaps(&scratch.width);
    393                 swaps(&scratch.height);
    394             }
    395             WriteToClient(client, sz_XineramaScreenInfo,&scratch);
    396         }
    397     }
    398 
    399     return Success;
    400 }
    401 
    402 // was PanoramiX
    403 static int
    404 ProcPseudoramiXDispatch(ClientPtr client)
    405 {
    406     REQUEST(xReq);
    407     TRACE;
    408     switch (stuff->data) {
    409     case X_PanoramiXQueryVersion:
    410         return ProcPseudoramiXQueryVersion(client);
    411 
    412     case X_PanoramiXGetState:
    413         return ProcPseudoramiXGetState(client);
    414 
    415     case X_PanoramiXGetScreenCount:
    416         return ProcPseudoramiXGetScreenCount(client);
    417 
    418     case X_PanoramiXGetScreenSize:
    419         return ProcPseudoramiXGetScreenSize(client);
    420 
    421     case X_XineramaIsActive:
    422         return ProcPseudoramiXIsActive(client);
    423 
    424     case X_XineramaQueryScreens:
    425         return ProcPseudoramiXQueryScreens(client);
    426     }
    427     return BadRequest;
    428 }
    429 
    430 static int
    431 SProcPseudoramiXQueryVersion(ClientPtr client)
    432 {
    433     REQUEST(xPanoramiXQueryVersionReq);
    434 
    435     TRACE;
    436 
    437     swaps(&stuff->length);
    438     REQUEST_SIZE_MATCH(xPanoramiXQueryVersionReq);
    439     return ProcPseudoramiXQueryVersion(client);
    440 }
    441 
    442 static int
    443 SProcPseudoramiXGetState(ClientPtr client)
    444 {
    445     REQUEST(xPanoramiXGetStateReq);
    446 
    447     TRACE;
    448 
    449     swaps(&stuff->length);
    450     REQUEST_SIZE_MATCH(xPanoramiXGetStateReq);
    451     return ProcPseudoramiXGetState(client);
    452 }
    453 
    454 static int
    455 SProcPseudoramiXGetScreenCount(ClientPtr client)
    456 {
    457     REQUEST(xPanoramiXGetScreenCountReq);
    458 
    459     TRACE;
    460 
    461     swaps(&stuff->length);
    462     REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq);
    463     return ProcPseudoramiXGetScreenCount(client);
    464 }
    465 
    466 static int
    467 SProcPseudoramiXGetScreenSize(ClientPtr client)
    468 {
    469     REQUEST(xPanoramiXGetScreenSizeReq);
    470 
    471     TRACE;
    472 
    473     swaps(&stuff->length);
    474     REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq);
    475     return ProcPseudoramiXGetScreenSize(client);
    476 }
    477 
    478 static int
    479 SProcPseudoramiXIsActive(ClientPtr client)
    480 {
    481     REQUEST(xXineramaIsActiveReq);
    482 
    483     TRACE;
    484 
    485     swaps(&stuff->length);
    486     REQUEST_SIZE_MATCH(xXineramaIsActiveReq);
    487     return ProcPseudoramiXIsActive(client);
    488 }
    489 
    490 static int
    491 SProcPseudoramiXQueryScreens(ClientPtr client)
    492 {
    493     REQUEST(xXineramaQueryScreensReq);
    494 
    495     TRACE;
    496 
    497     swaps(&stuff->length);
    498     REQUEST_SIZE_MATCH(xXineramaQueryScreensReq);
    499     return ProcPseudoramiXQueryScreens(client);
    500 }
    501 
    502 static int
    503 SProcPseudoramiXDispatch(ClientPtr client)
    504 {
    505     REQUEST(xReq);
    506 
    507     TRACE;
    508 
    509     switch (stuff->data) {
    510     case X_PanoramiXQueryVersion:
    511         return SProcPseudoramiXQueryVersion(client);
    512 
    513     case X_PanoramiXGetState:
    514         return SProcPseudoramiXGetState(client);
    515 
    516     case X_PanoramiXGetScreenCount:
    517         return SProcPseudoramiXGetScreenCount(client);
    518 
    519     case X_PanoramiXGetScreenSize:
    520         return SProcPseudoramiXGetScreenSize(client);
    521 
    522     case X_XineramaIsActive:
    523         return SProcPseudoramiXIsActive(client);
    524 
    525     case X_XineramaQueryScreens:
    526         return SProcPseudoramiXQueryScreens(client);
    527     }
    528     return BadRequest;
    529 }