xserver

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

xf86RandR.c (13447B)


      1 /*
      2  *
      3  * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc.
      4  *
      5  * Permission to use, copy, modify, distribute, and sell this software and its
      6  * documentation for any purpose is hereby granted without fee, provided that
      7  * the above copyright notice appear in all copies and that both that
      8  * copyright notice and this permission notice appear in supporting
      9  * documentation, and that the name of Keith Packard not be used in
     10  * advertising or publicity pertaining to distribution of the software without
     11  * specific, written prior permission.  Keith Packard makes no
     12  * representations about the suitability of this software for any purpose.  It
     13  * is provided "as is" without express or implied warranty.
     14  *
     15  * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
     16  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
     17  * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
     18  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
     19  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
     20  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
     21  * PERFORMANCE OF THIS SOFTWARE.
     22  */
     23 
     24 #ifdef HAVE_XORG_CONFIG_H
     25 #include <xorg-config.h>
     26 #endif
     27 
     28 #include <X11/X.h>
     29 #include "os.h"
     30 #include "globals.h"
     31 #include "xf86.h"
     32 #include "xf86str.h"
     33 #include "xf86Priv.h"
     34 #include "xf86DDC.h"
     35 #include "mipointer.h"
     36 #include <randrstr.h>
     37 #include "inputstr.h"
     38 
     39 typedef struct _xf86RandRInfo {
     40     CloseScreenProcPtr CloseScreen;
     41     int virtualX;
     42     int virtualY;
     43     int mmWidth;
     44     int mmHeight;
     45     Rotation rotation;
     46 } XF86RandRInfoRec, *XF86RandRInfoPtr;
     47 
     48 static DevPrivateKeyRec xf86RandRKeyRec;
     49 static DevPrivateKey xf86RandRKey;
     50 
     51 #define XF86RANDRINFO(p) ((XF86RandRInfoPtr)dixLookupPrivate(&(p)->devPrivates, xf86RandRKey))
     52 
     53 static int
     54 xf86RandRModeRefresh(DisplayModePtr mode)
     55 {
     56     if (mode->VRefresh)
     57         return (int) (mode->VRefresh + 0.5);
     58     else if (mode->Clock == 0)
     59         return 0;
     60     else
     61         return (int) (mode->Clock * 1000.0 / mode->HTotal / mode->VTotal + 0.5);
     62 }
     63 
     64 static Bool
     65 xf86RandRGetInfo(ScreenPtr pScreen, Rotation * rotations)
     66 {
     67     RRScreenSizePtr pSize;
     68     ScrnInfoPtr scrp = xf86ScreenToScrn(pScreen);
     69     XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
     70     DisplayModePtr mode;
     71     int refresh0 = 60;
     72     xorgRRModeMM RRModeMM;
     73 
     74     *rotations = RR_Rotate_0;
     75 
     76     for (mode = scrp->modes; mode != NULL; mode = mode->next) {
     77         int refresh = xf86RandRModeRefresh(mode);
     78 
     79         if (mode == scrp->modes)
     80             refresh0 = refresh;
     81 
     82         RRModeMM.mode = mode;
     83         RRModeMM.virtX = randrp->virtualX;
     84         RRModeMM.virtY = randrp->virtualY;
     85         RRModeMM.mmWidth = randrp->mmWidth;
     86         RRModeMM.mmHeight = randrp->mmHeight;
     87 
     88         if (scrp->DriverFunc) {
     89             (*scrp->DriverFunc) (scrp, RR_GET_MODE_MM, &RRModeMM);
     90         }
     91 
     92         pSize = RRRegisterSize(pScreen,
     93                                mode->HDisplay, mode->VDisplay,
     94                                RRModeMM.mmWidth, RRModeMM.mmHeight);
     95         if (!pSize)
     96             return FALSE;
     97         RRRegisterRate(pScreen, pSize, refresh);
     98         if (mode == scrp->currentMode &&
     99             mode->HDisplay == scrp->virtualX &&
    100             mode->VDisplay == scrp->virtualY)
    101             RRSetCurrentConfig(pScreen, randrp->rotation, refresh, pSize);
    102         if (mode->next == scrp->modes)
    103             break;
    104     }
    105     if (scrp->currentMode->HDisplay != randrp->virtualX ||
    106         scrp->currentMode->VDisplay != randrp->virtualY) {
    107         mode = scrp->modes;
    108 
    109         RRModeMM.mode = NULL;
    110         RRModeMM.virtX = randrp->virtualX;
    111         RRModeMM.virtY = randrp->virtualY;
    112         RRModeMM.mmWidth = randrp->mmWidth;
    113         RRModeMM.mmHeight = randrp->mmHeight;
    114 
    115         if (scrp->DriverFunc) {
    116             (*scrp->DriverFunc) (scrp, RR_GET_MODE_MM, &RRModeMM);
    117         }
    118 
    119         pSize = RRRegisterSize(pScreen,
    120                                randrp->virtualX, randrp->virtualY,
    121                                RRModeMM.mmWidth, RRModeMM.mmHeight);
    122         if (!pSize)
    123             return FALSE;
    124         RRRegisterRate(pScreen, pSize, refresh0);
    125         if (scrp->virtualX == randrp->virtualX &&
    126             scrp->virtualY == randrp->virtualY) {
    127             RRSetCurrentConfig(pScreen, randrp->rotation, refresh0, pSize);
    128         }
    129     }
    130 
    131     /* If there is driver support for randr, let it set our supported rotations */
    132     if (scrp->DriverFunc) {
    133         xorgRRRotation RRRotation;
    134 
    135         RRRotation.RRRotations = *rotations;
    136         if (!(*scrp->DriverFunc) (scrp, RR_GET_INFO, &RRRotation))
    137             return TRUE;
    138         *rotations = RRRotation.RRRotations;
    139     }
    140 
    141     return TRUE;
    142 }
    143 
    144 static Bool
    145 xf86RandRSetMode(ScreenPtr pScreen,
    146                  DisplayModePtr mode,
    147                  Bool useVirtual, int mmWidth, int mmHeight)
    148 {
    149     ScrnInfoPtr scrp = xf86ScreenToScrn(pScreen);
    150     XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
    151     int oldWidth = pScreen->width;
    152     int oldHeight = pScreen->height;
    153     int oldmmWidth = pScreen->mmWidth;
    154     int oldmmHeight = pScreen->mmHeight;
    155     int oldVirtualX = scrp->virtualX;
    156     int oldVirtualY = scrp->virtualY;
    157     WindowPtr pRoot = pScreen->root;
    158     Bool ret = TRUE;
    159 
    160     if (pRoot && scrp->vtSema)
    161         (*scrp->EnableDisableFBAccess) (scrp, FALSE);
    162     if (useVirtual) {
    163         scrp->virtualX = randrp->virtualX;
    164         scrp->virtualY = randrp->virtualY;
    165     }
    166     else {
    167         scrp->virtualX = mode->HDisplay;
    168         scrp->virtualY = mode->VDisplay;
    169     }
    170 
    171     /*
    172      * The DIX forgets the physical dimensions we passed into RRRegisterSize, so
    173      * reconstruct them if possible.
    174      */
    175     if (scrp->DriverFunc) {
    176         xorgRRModeMM RRModeMM;
    177 
    178         RRModeMM.mode = mode;
    179         RRModeMM.virtX = scrp->virtualX;
    180         RRModeMM.virtY = scrp->virtualY;
    181         RRModeMM.mmWidth = mmWidth;
    182         RRModeMM.mmHeight = mmHeight;
    183 
    184         (*scrp->DriverFunc) (scrp, RR_GET_MODE_MM, &RRModeMM);
    185 
    186         mmWidth = RRModeMM.mmWidth;
    187         mmHeight = RRModeMM.mmHeight;
    188     }
    189     if (randrp->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
    190         /* If the screen is rotated 90 or 270 degrees, swap the sizes. */
    191         pScreen->width = scrp->virtualY;
    192         pScreen->height = scrp->virtualX;
    193         pScreen->mmWidth = mmHeight;
    194         pScreen->mmHeight = mmWidth;
    195     }
    196     else {
    197         pScreen->width = scrp->virtualX;
    198         pScreen->height = scrp->virtualY;
    199         pScreen->mmWidth = mmWidth;
    200         pScreen->mmHeight = mmHeight;
    201     }
    202     if (!xf86SwitchMode(pScreen, mode)) {
    203         pScreen->width = oldWidth;
    204         pScreen->height = oldHeight;
    205         pScreen->mmWidth = oldmmWidth;
    206         pScreen->mmHeight = oldmmHeight;
    207         scrp->virtualX = oldVirtualX;
    208         scrp->virtualY = oldVirtualY;
    209         ret = FALSE;
    210     }
    211     /*
    212      * Make sure the layout is correct
    213      */
    214     xf86ReconfigureLayout();
    215 
    216     if (scrp->vtSema) {
    217         /*
    218          * Make sure the whole screen is visible
    219          */
    220         xf86SetViewport (pScreen, pScreen->width, pScreen->height);
    221         xf86SetViewport (pScreen, 0, 0);
    222         if (pRoot)
    223             (*scrp->EnableDisableFBAccess) (scrp, TRUE);
    224     }
    225     return ret;
    226 }
    227 
    228 static Bool
    229 xf86RandRSetConfig(ScreenPtr pScreen,
    230                    Rotation rotation, int rate, RRScreenSizePtr pSize)
    231 {
    232     ScrnInfoPtr scrp = xf86ScreenToScrn(pScreen);
    233     XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
    234     DisplayModePtr mode;
    235     int pos[MAXDEVICES][2];
    236     Bool useVirtual = FALSE;
    237     Rotation oldRotation = randrp->rotation;
    238     DeviceIntPtr dev;
    239     Bool view_adjusted = FALSE;
    240 
    241     for (dev = inputInfo.devices; dev; dev = dev->next) {
    242         if (!IsMaster(dev) && !IsFloating(dev))
    243             continue;
    244 
    245         miPointerGetPosition(dev, &pos[dev->id][0], &pos[dev->id][1]);
    246     }
    247 
    248     for (mode = scrp->modes;; mode = mode->next) {
    249         if (mode->HDisplay == pSize->width &&
    250             mode->VDisplay == pSize->height &&
    251             (rate == 0 || xf86RandRModeRefresh(mode) == rate))
    252             break;
    253         if (mode->next == scrp->modes) {
    254             if (pSize->width == randrp->virtualX &&
    255                 pSize->height == randrp->virtualY) {
    256                 mode = scrp->modes;
    257                 useVirtual = TRUE;
    258                 break;
    259             }
    260             return FALSE;
    261         }
    262     }
    263 
    264     if (randrp->rotation != rotation) {
    265 
    266         /* Have the driver do its thing. */
    267         if (scrp->DriverFunc) {
    268             xorgRRRotation RRRotation;
    269 
    270             RRRotation.RRConfig.rotation = rotation;
    271             RRRotation.RRConfig.rate = rate;
    272             RRRotation.RRConfig.width = pSize->width;
    273             RRRotation.RRConfig.height = pSize->height;
    274 
    275             /*
    276              * Currently we need to rely on HW support for rotation.
    277              */
    278             if (!(*scrp->DriverFunc) (scrp, RR_SET_CONFIG, &RRRotation))
    279                 return FALSE;
    280         }
    281         else
    282             return FALSE;
    283 
    284         randrp->rotation = rotation;
    285     }
    286 
    287     if (!xf86RandRSetMode
    288         (pScreen, mode, useVirtual, pSize->mmWidth, pSize->mmHeight)) {
    289         if (randrp->rotation != oldRotation) {
    290             /* Have the driver undo its thing. */
    291             if (scrp->DriverFunc) {
    292                 xorgRRRotation RRRotation;
    293 
    294                 RRRotation.RRConfig.rotation = oldRotation;
    295                 RRRotation.RRConfig.rate =
    296                     xf86RandRModeRefresh(scrp->currentMode);
    297                 RRRotation.RRConfig.width = scrp->virtualX;
    298                 RRRotation.RRConfig.height = scrp->virtualY;
    299                 (*scrp->DriverFunc) (scrp, RR_SET_CONFIG, &RRRotation);
    300             }
    301 
    302             randrp->rotation = oldRotation;
    303         }
    304         return FALSE;
    305     }
    306 
    307     update_desktop_dimensions();
    308 
    309     /*
    310      * Move the cursor back where it belongs; SwitchMode repositions it
    311      * FIXME: duplicated code, see modes/xf86RandR12.c
    312      */
    313     for (dev = inputInfo.devices; dev; dev = dev->next) {
    314         if (!IsMaster(dev) && !IsFloating(dev))
    315             continue;
    316 
    317         if (pScreen == miPointerGetScreen(dev)) {
    318             int px = pos[dev->id][0];
    319             int py = pos[dev->id][1];
    320 
    321             px = (px >= pScreen->width ? (pScreen->width - 1) : px);
    322             py = (py >= pScreen->height ? (pScreen->height - 1) : py);
    323 
    324             /* Setting the viewpoint makes only sense on one device */
    325             if (!view_adjusted && IsMaster(dev)) {
    326                 xf86SetViewport(pScreen, px, py);
    327                 view_adjusted = TRUE;
    328             }
    329 
    330             (*pScreen->SetCursorPosition) (dev, pScreen, px, py, FALSE);
    331         }
    332     }
    333 
    334     return TRUE;
    335 }
    336 
    337 /*
    338  * Reset size back to original
    339  */
    340 static Bool
    341 xf86RandRCloseScreen(ScreenPtr pScreen)
    342 {
    343     ScrnInfoPtr scrp = xf86ScreenToScrn(pScreen);
    344     XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
    345 
    346     scrp->virtualX = pScreen->width = randrp->virtualX;
    347     scrp->virtualY = pScreen->height = randrp->virtualY;
    348     scrp->currentMode = scrp->modes;
    349     pScreen->CloseScreen = randrp->CloseScreen;
    350     free(randrp);
    351     dixSetPrivate(&pScreen->devPrivates, xf86RandRKey, NULL);
    352     return (*pScreen->CloseScreen) (pScreen);
    353 }
    354 
    355 Rotation
    356 xf86GetRotation(ScreenPtr pScreen)
    357 {
    358     if (xf86RandRKey == NULL)
    359         return RR_Rotate_0;
    360 
    361     return XF86RANDRINFO(pScreen)->rotation;
    362 }
    363 
    364 /* Function to change RandR's idea of the virtual screen size */
    365 Bool
    366 xf86RandRSetNewVirtualAndDimensions(ScreenPtr pScreen,
    367                                     int newvirtX, int newvirtY, int newmmWidth,
    368                                     int newmmHeight, Bool resetMode)
    369 {
    370     XF86RandRInfoPtr randrp;
    371 
    372     if (xf86RandRKey == NULL)
    373         return FALSE;
    374 
    375     randrp = XF86RANDRINFO(pScreen);
    376     if (randrp == NULL)
    377         return FALSE;
    378 
    379     if (newvirtX > 0)
    380         randrp->virtualX = newvirtX;
    381 
    382     if (newvirtY > 0)
    383         randrp->virtualY = newvirtY;
    384 
    385     if (newmmWidth > 0)
    386         randrp->mmWidth = newmmWidth;
    387 
    388     if (newmmHeight > 0)
    389         randrp->mmHeight = newmmHeight;
    390 
    391     /* This is only for during server start */
    392     if (resetMode) {
    393 	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
    394         return (xf86RandRSetMode(pScreen,
    395                                  pScrn->currentMode,
    396                                  TRUE, pScreen->mmWidth, pScreen->mmHeight));
    397     }
    398 
    399     return TRUE;
    400 }
    401 
    402 Bool
    403 xf86RandRInit(ScreenPtr pScreen)
    404 {
    405     rrScrPrivPtr rp;
    406     XF86RandRInfoPtr randrp;
    407     ScrnInfoPtr scrp = xf86ScreenToScrn(pScreen);
    408 
    409 #ifdef PANORAMIX
    410     /* XXX disable RandR when using Xinerama */
    411     if (!noPanoramiXExtension)
    412         return TRUE;
    413 #endif
    414 
    415     xf86RandRKey = &xf86RandRKeyRec;
    416 
    417     if (!dixRegisterPrivateKey(&xf86RandRKeyRec, PRIVATE_SCREEN, 0))
    418         return FALSE;
    419 
    420     randrp = malloc(sizeof(XF86RandRInfoRec));
    421     if (!randrp)
    422         return FALSE;
    423 
    424     if (!RRScreenInit(pScreen)) {
    425         free(randrp);
    426         return FALSE;
    427     }
    428     rp = rrGetScrPriv(pScreen);
    429     rp->rrGetInfo = xf86RandRGetInfo;
    430     rp->rrSetConfig = xf86RandRSetConfig;
    431 
    432     randrp->virtualX = scrp->virtualX;
    433     randrp->virtualY = scrp->virtualY;
    434     randrp->mmWidth = pScreen->mmWidth;
    435     randrp->mmHeight = pScreen->mmHeight;
    436 
    437     randrp->CloseScreen = pScreen->CloseScreen;
    438     pScreen->CloseScreen = xf86RandRCloseScreen;
    439 
    440     randrp->rotation = RR_Rotate_0;
    441 
    442     dixSetPrivate(&pScreen->devPrivates, xf86RandRKey, randrp);
    443     return TRUE;
    444 }