xserver

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

rrxinerama.c (13399B)


      1 /*
      2  * Copyright © 2006 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  * This Xinerama implementation comes from the SiS driver which has
     24  * the following notice:
     25  */
     26 /*
     27  * SiS driver main code
     28  *
     29  * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria.
     30  *
     31  * Redistribution and use in source and binary forms, with or without
     32  * modification, are permitted provided that the following conditions
     33  * are met:
     34  * 1) Redistributions of source code must retain the above copyright
     35  *    notice, this list of conditions and the following disclaimer.
     36  * 2) Redistributions in binary form must reproduce the above copyright
     37  *    notice, this list of conditions and the following disclaimer in the
     38  *    documentation and/or other materials provided with the distribution.
     39  * 3) The name of the author may not be used to endorse or promote products
     40  *    derived from this software without specific prior written permission.
     41  *
     42  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     43  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     44  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     45  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     46  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     47  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     48  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     49  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     50  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     51  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     52  *
     53  * Author: Thomas Winischhofer <thomas@winischhofer.net>
     54  *	- driver entirely rewritten since 2001, only basic structure taken from
     55  *	  old code (except sis_dri.c, sis_shadow.c, sis_accel.c and parts of
     56  *	  sis_dga.c; these were mostly taken over; sis_dri.c was changed for
     57  *	  new versions of the DRI layer)
     58  *
     59  * This notice covers the entire driver code unless indicated otherwise.
     60  *
     61  * Formerly based on code which was
     62  * 	     Copyright (C) 1998, 1999 by Alan Hourihane, Wigan, England.
     63  * 	     Written by:
     64  *           Alan Hourihane <alanh@fairlite.demon.co.uk>,
     65  *           Mike Chapman <mike@paranoia.com>,
     66  *           Juanjo Santamarta <santamarta@ctv.es>,
     67  *           Mitani Hiroshi <hmitani@drl.mei.co.jp>,
     68  *           David Thomas <davtom@dream.org.uk>.
     69  */
     70 
     71 #include "randrstr.h"
     72 #include "swaprep.h"
     73 #include <X11/extensions/panoramiXproto.h>
     74 #include "protocol-versions.h"
     75 
     76 /* Xinerama is not multi-screen capable; just report about screen 0 */
     77 #define RR_XINERAMA_SCREEN  0
     78 
     79 static int ProcRRXineramaQueryVersion(ClientPtr client);
     80 static int ProcRRXineramaGetState(ClientPtr client);
     81 static int ProcRRXineramaGetScreenCount(ClientPtr client);
     82 static int ProcRRXineramaGetScreenSize(ClientPtr client);
     83 static int ProcRRXineramaIsActive(ClientPtr client);
     84 static int ProcRRXineramaQueryScreens(ClientPtr client);
     85 static int _X_COLD SProcRRXineramaDispatch(ClientPtr client);
     86 
     87 Bool noRRXineramaExtension = FALSE;
     88 
     89 /* Proc */
     90 
     91 int
     92 ProcRRXineramaQueryVersion(ClientPtr client)
     93 {
     94     xPanoramiXQueryVersionReply rep = {
     95         .type = X_Reply,
     96         .sequenceNumber = client->sequence,
     97         .length = 0,
     98         .majorVersion = SERVER_RRXINERAMA_MAJOR_VERSION,
     99         .minorVersion = SERVER_RRXINERAMA_MINOR_VERSION
    100     };
    101 
    102     REQUEST_SIZE_MATCH(xPanoramiXQueryVersionReq);
    103     if (client->swapped) {
    104         swaps(&rep.sequenceNumber);
    105         swapl(&rep.length);
    106         swaps(&rep.majorVersion);
    107         swaps(&rep.minorVersion);
    108     }
    109     WriteToClient(client, sizeof(xPanoramiXQueryVersionReply), &rep);
    110     return Success;
    111 }
    112 
    113 int
    114 ProcRRXineramaGetState(ClientPtr client)
    115 {
    116     REQUEST(xPanoramiXGetStateReq);
    117     WindowPtr pWin;
    118     xPanoramiXGetStateReply rep;
    119     register int rc;
    120     ScreenPtr pScreen;
    121     rrScrPrivPtr pScrPriv;
    122     Bool active = FALSE;
    123 
    124     REQUEST_SIZE_MATCH(xPanoramiXGetStateReq);
    125     rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
    126     if (rc != Success)
    127         return rc;
    128 
    129     pScreen = pWin->drawable.pScreen;
    130     pScrPriv = rrGetScrPriv(pScreen);
    131     if (pScrPriv) {
    132         /* XXX do we need more than this? */
    133         active = TRUE;
    134     }
    135 
    136     rep = (xPanoramiXGetStateReply) {
    137         .type = X_Reply,
    138         .state = active,
    139         .sequenceNumber = client->sequence,
    140         .length = 0,
    141         .window = stuff->window
    142     };
    143     if (client->swapped) {
    144         swaps(&rep.sequenceNumber);
    145         swapl(&rep.length);
    146         swapl(&rep.window);
    147     }
    148     WriteToClient(client, sizeof(xPanoramiXGetStateReply), &rep);
    149     return Success;
    150 }
    151 
    152 static int
    153 RRXineramaScreenCount(ScreenPtr pScreen)
    154 {
    155     return RRMonitorCountList(pScreen);
    156 }
    157 
    158 static Bool
    159 RRXineramaScreenActive(ScreenPtr pScreen)
    160 {
    161     return RRXineramaScreenCount(pScreen) > 0;
    162 }
    163 
    164 int
    165 ProcRRXineramaGetScreenCount(ClientPtr client)
    166 {
    167     REQUEST(xPanoramiXGetScreenCountReq);
    168     WindowPtr pWin;
    169     xPanoramiXGetScreenCountReply rep;
    170     register int rc;
    171 
    172     REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq);
    173     rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
    174     if (rc != Success)
    175         return rc;
    176 
    177     rep = (xPanoramiXGetScreenCountReply)  {
    178         .type = X_Reply,
    179         .ScreenCount = RRXineramaScreenCount(pWin->drawable.pScreen),
    180         .sequenceNumber = client->sequence,
    181         .length = 0,
    182         .window = stuff->window
    183     };
    184     if (client->swapped) {
    185         swaps(&rep.sequenceNumber);
    186         swapl(&rep.length);
    187         swapl(&rep.window);
    188     }
    189     WriteToClient(client, sizeof(xPanoramiXGetScreenCountReply), &rep);
    190     return Success;
    191 }
    192 
    193 int
    194 ProcRRXineramaGetScreenSize(ClientPtr client)
    195 {
    196     REQUEST(xPanoramiXGetScreenSizeReq);
    197     WindowPtr pWin, pRoot;
    198     ScreenPtr pScreen;
    199     xPanoramiXGetScreenSizeReply rep;
    200     register int rc;
    201 
    202     REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq);
    203     rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
    204     if (rc != Success)
    205         return rc;
    206 
    207     pScreen = pWin->drawable.pScreen;
    208     pRoot = pScreen->root;
    209 
    210     rep = (xPanoramiXGetScreenSizeReply) {
    211         .type = X_Reply,
    212         .sequenceNumber = client->sequence,
    213         .length = 0,
    214         .width = pRoot->drawable.width,
    215         .height = pRoot->drawable.height,
    216         .window = stuff->window,
    217         .screen = stuff->screen
    218     };
    219     if (client->swapped) {
    220         swaps(&rep.sequenceNumber);
    221         swapl(&rep.length);
    222         swapl(&rep.width);
    223         swapl(&rep.height);
    224         swapl(&rep.window);
    225         swapl(&rep.screen);
    226     }
    227     WriteToClient(client, sizeof(xPanoramiXGetScreenSizeReply), &rep);
    228     return Success;
    229 }
    230 
    231 int
    232 ProcRRXineramaIsActive(ClientPtr client)
    233 {
    234     xXineramaIsActiveReply rep;
    235 
    236     REQUEST_SIZE_MATCH(xXineramaIsActiveReq);
    237 
    238     rep = (xXineramaIsActiveReply) {
    239         .type = X_Reply,
    240         .length = 0,
    241         .sequenceNumber = client->sequence,
    242         .state = RRXineramaScreenActive(screenInfo.screens[RR_XINERAMA_SCREEN])
    243     };
    244     if (client->swapped) {
    245         swaps(&rep.sequenceNumber);
    246         swapl(&rep.length);
    247         swapl(&rep.state);
    248     }
    249     WriteToClient(client, sizeof(xXineramaIsActiveReply), &rep);
    250     return Success;
    251 }
    252 
    253 static void
    254 RRXineramaWriteMonitor(ClientPtr client, RRMonitorPtr monitor)
    255 {
    256     xXineramaScreenInfo scratch;
    257 
    258     scratch.x_org = monitor->geometry.box.x1;
    259     scratch.y_org = monitor->geometry.box.y1;
    260     scratch.width = monitor->geometry.box.x2 - monitor->geometry.box.x1;
    261     scratch.height = monitor->geometry.box.y2 - monitor->geometry.box.y1;
    262 
    263     if (client->swapped) {
    264         swaps(&scratch.x_org);
    265         swaps(&scratch.y_org);
    266         swaps(&scratch.width);
    267         swaps(&scratch.height);
    268     }
    269 
    270     WriteToClient(client, sz_XineramaScreenInfo, &scratch);
    271 }
    272 
    273 int
    274 ProcRRXineramaQueryScreens(ClientPtr client)
    275 {
    276     xXineramaQueryScreensReply rep;
    277     ScreenPtr pScreen = screenInfo.screens[RR_XINERAMA_SCREEN];
    278     int m;
    279     RRMonitorPtr monitors = NULL;
    280     int nmonitors = 0;
    281 
    282     REQUEST_SIZE_MATCH(xXineramaQueryScreensReq);
    283 
    284     if (RRXineramaScreenActive(pScreen)) {
    285         RRGetInfo(pScreen, FALSE);
    286         if (!RRMonitorMakeList(pScreen, TRUE, &monitors, &nmonitors))
    287             return BadAlloc;
    288     }
    289 
    290     rep = (xXineramaQueryScreensReply) {
    291         .type = X_Reply,
    292         .sequenceNumber = client->sequence,
    293         .length = bytes_to_int32(nmonitors * sz_XineramaScreenInfo),
    294         .number = nmonitors
    295     };
    296     if (client->swapped) {
    297         swaps(&rep.sequenceNumber);
    298         swapl(&rep.length);
    299         swapl(&rep.number);
    300     }
    301     WriteToClient(client, sizeof(xXineramaQueryScreensReply), &rep);
    302 
    303     for (m = 0; m < nmonitors; m++)
    304         RRXineramaWriteMonitor(client, &monitors[m]);
    305 
    306     if (monitors)
    307         RRMonitorFreeList(monitors, nmonitors);
    308 
    309     return Success;
    310 }
    311 
    312 static int
    313 ProcRRXineramaDispatch(ClientPtr client)
    314 {
    315     REQUEST(xReq);
    316     switch (stuff->data) {
    317     case X_PanoramiXQueryVersion:
    318         return ProcRRXineramaQueryVersion(client);
    319     case X_PanoramiXGetState:
    320         return ProcRRXineramaGetState(client);
    321     case X_PanoramiXGetScreenCount:
    322         return ProcRRXineramaGetScreenCount(client);
    323     case X_PanoramiXGetScreenSize:
    324         return ProcRRXineramaGetScreenSize(client);
    325     case X_XineramaIsActive:
    326         return ProcRRXineramaIsActive(client);
    327     case X_XineramaQueryScreens:
    328         return ProcRRXineramaQueryScreens(client);
    329     }
    330     return BadRequest;
    331 }
    332 
    333 /* SProc */
    334 
    335 static int _X_COLD
    336 SProcRRXineramaQueryVersion(ClientPtr client)
    337 {
    338     REQUEST(xPanoramiXQueryVersionReq);
    339     swaps(&stuff->length);
    340     REQUEST_SIZE_MATCH(xPanoramiXQueryVersionReq);
    341     return ProcRRXineramaQueryVersion(client);
    342 }
    343 
    344 static int _X_COLD
    345 SProcRRXineramaGetState(ClientPtr client)
    346 {
    347     REQUEST(xPanoramiXGetStateReq);
    348     swaps(&stuff->length);
    349     REQUEST_SIZE_MATCH(xPanoramiXGetStateReq);
    350     swapl(&stuff->window);
    351     return ProcRRXineramaGetState(client);
    352 }
    353 
    354 static int _X_COLD
    355 SProcRRXineramaGetScreenCount(ClientPtr client)
    356 {
    357     REQUEST(xPanoramiXGetScreenCountReq);
    358     swaps(&stuff->length);
    359     REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq);
    360     swapl(&stuff->window);
    361     return ProcRRXineramaGetScreenCount(client);
    362 }
    363 
    364 static int _X_COLD
    365 SProcRRXineramaGetScreenSize(ClientPtr client)
    366 {
    367     REQUEST(xPanoramiXGetScreenSizeReq);
    368     swaps(&stuff->length);
    369     REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq);
    370     swapl(&stuff->window);
    371     swapl(&stuff->screen);
    372     return ProcRRXineramaGetScreenSize(client);
    373 }
    374 
    375 static int _X_COLD
    376 SProcRRXineramaIsActive(ClientPtr client)
    377 {
    378     REQUEST(xXineramaIsActiveReq);
    379     swaps(&stuff->length);
    380     REQUEST_SIZE_MATCH(xXineramaIsActiveReq);
    381     return ProcRRXineramaIsActive(client);
    382 }
    383 
    384 static int _X_COLD
    385 SProcRRXineramaQueryScreens(ClientPtr client)
    386 {
    387     REQUEST(xXineramaQueryScreensReq);
    388     swaps(&stuff->length);
    389     REQUEST_SIZE_MATCH(xXineramaQueryScreensReq);
    390     return ProcRRXineramaQueryScreens(client);
    391 }
    392 
    393 int
    394 SProcRRXineramaDispatch(ClientPtr client)
    395 {
    396     REQUEST(xReq);
    397     switch (stuff->data) {
    398     case X_PanoramiXQueryVersion:
    399         return SProcRRXineramaQueryVersion(client);
    400     case X_PanoramiXGetState:
    401         return SProcRRXineramaGetState(client);
    402     case X_PanoramiXGetScreenCount:
    403         return SProcRRXineramaGetScreenCount(client);
    404     case X_PanoramiXGetScreenSize:
    405         return SProcRRXineramaGetScreenSize(client);
    406     case X_XineramaIsActive:
    407         return SProcRRXineramaIsActive(client);
    408     case X_XineramaQueryScreens:
    409         return SProcRRXineramaQueryScreens(client);
    410     }
    411     return BadRequest;
    412 }
    413 
    414 void
    415 RRXineramaExtensionInit(void)
    416 {
    417 #ifdef PANORAMIX
    418     if (!noPanoramiXExtension)
    419         return;
    420 #endif
    421 
    422     if (noRRXineramaExtension)
    423       return;
    424 
    425     /*
    426      * Xinerama isn't capable enough to have multiple protocol screens each
    427      * with their own output geometry.  So if there's more than one protocol
    428      * screen, just don't even try.
    429      */
    430     if (screenInfo.numScreens > 1)
    431         return;
    432 
    433     (void) AddExtension(PANORAMIX_PROTOCOL_NAME, 0, 0,
    434                         ProcRRXineramaDispatch,
    435                         SProcRRXineramaDispatch, NULL, StandardMinorOpcode);
    436 }