xserver

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

xf86Cursor.c (25813B)


      1 /*
      2  * Copyright (c) 1994-2003 by The XFree86 Project, Inc.
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a
      5  * copy of this software and associated documentation files (the "Software"),
      6  * to deal in the Software without restriction, including without limitation
      7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8  * and/or sell copies of the Software, and to permit persons to whom the
      9  * Software is furnished to do so, subject to the following conditions:
     10  *
     11  * The above copyright notice and this permission notice shall be included in
     12  * all copies or substantial portions of the Software.
     13  *
     14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
     18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     20  * OTHER DEALINGS IN THE SOFTWARE.
     21  *
     22  * Except as contained in this notice, the name of the copyright holder(s)
     23  * and author(s) shall not be used in advertising or otherwise to promote
     24  * the sale, use or other dealings in this Software without prior written
     25  * authorization from the copyright holder(s) and author(s).
     26  */
     27 
     28 #ifdef HAVE_XORG_CONFIG_H
     29 #include <xorg-config.h>
     30 #endif
     31 
     32 #include <X11/X.h>
     33 #include <X11/Xmd.h>
     34 #include "input.h"
     35 #include "cursor.h"
     36 #include "mipointer.h"
     37 #include "scrnintstr.h"
     38 #include "globals.h"
     39 
     40 #include "xf86.h"
     41 #include "xf86Priv.h"
     42 #include "xf86_OSproc.h"
     43 
     44 #include <X11/extensions/XIproto.h>
     45 #include "xf86Xinput.h"
     46 
     47 #ifdef XFreeXDGA
     48 #include "dgaproc.h"
     49 #endif
     50 
     51 typedef struct _xf86EdgeRec {
     52     short screen;
     53     short start;
     54     short end;
     55     DDXPointRec offset;
     56     struct _xf86EdgeRec *next;
     57 } xf86EdgeRec, *xf86EdgePtr;
     58 
     59 typedef struct {
     60     xf86EdgePtr left, right, up, down;
     61 } xf86ScreenLayoutRec, *xf86ScreenLayoutPtr;
     62 
     63 static Bool xf86CursorOffScreen(ScreenPtr *pScreen, int *x, int *y);
     64 static void xf86CrossScreen(ScreenPtr pScreen, Bool entering);
     65 static void xf86WarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y);
     66 
     67 static void xf86PointerMoved(ScrnInfoPtr pScrn, int x, int y);
     68 
     69 static miPointerScreenFuncRec xf86PointerScreenFuncs = {
     70     xf86CursorOffScreen,
     71     xf86CrossScreen,
     72     xf86WarpCursor,
     73 };
     74 
     75 static xf86ScreenLayoutRec xf86ScreenLayout[MAXSCREENS];
     76 
     77 /*
     78  * xf86InitViewport --
     79  *      Initialize paning & zooming parameters, so that a driver must only
     80  *      check what resolutions are possible and whether the virtual area
     81  *      is valid if specified.
     82  */
     83 
     84 void
     85 xf86InitViewport(ScrnInfoPtr pScr)
     86 {
     87 
     88     pScr->PointerMoved = xf86PointerMoved;
     89 
     90     /*
     91      * Compute the initial Viewport if necessary
     92      */
     93     if (pScr->display) {
     94         if (pScr->display->frameX0 < 0) {
     95             pScr->frameX0 = (pScr->virtualX - pScr->modes->HDisplay) / 2;
     96             pScr->frameY0 = (pScr->virtualY - pScr->modes->VDisplay) / 2;
     97         }
     98         else {
     99             pScr->frameX0 = pScr->display->frameX0;
    100             pScr->frameY0 = pScr->display->frameY0;
    101         }
    102     }
    103 
    104     pScr->frameX1 = pScr->frameX0 + pScr->modes->HDisplay - 1;
    105     pScr->frameY1 = pScr->frameY0 + pScr->modes->VDisplay - 1;
    106 
    107     /*
    108      * Now adjust the initial Viewport, so it lies within the virtual area
    109      */
    110     if (pScr->frameX1 >= pScr->virtualX) {
    111         pScr->frameX0 = pScr->virtualX - pScr->modes->HDisplay;
    112         pScr->frameX1 = pScr->frameX0 + pScr->modes->HDisplay - 1;
    113     }
    114 
    115     if (pScr->frameY1 >= pScr->virtualY) {
    116         pScr->frameY0 = pScr->virtualY - pScr->modes->VDisplay;
    117         pScr->frameY1 = pScr->frameY0 + pScr->modes->VDisplay - 1;
    118     }
    119 }
    120 
    121 /*
    122  * xf86SetViewport --
    123  *      Scroll the visual part of the screen so the pointer is visible.
    124  */
    125 
    126 void
    127 xf86SetViewport(ScreenPtr pScreen, int x, int y)
    128 {
    129     ScrnInfoPtr pScr = xf86ScreenToScrn(pScreen);
    130 
    131     (*pScr->PointerMoved) (pScr, x, y);
    132 }
    133 
    134 static void
    135 xf86PointerMoved(ScrnInfoPtr pScr, int x, int y)
    136 {
    137     Bool frameChanged = FALSE;
    138 
    139     /*
    140      * check whether (x,y) belongs to the visual part of the screen
    141      * if not, change the base of the displayed frame occurring
    142      */
    143     if (pScr->frameX0 > x) {
    144         pScr->frameX0 = x;
    145         pScr->frameX1 = x + pScr->currentMode->HDisplay - 1;
    146         frameChanged = TRUE;
    147     }
    148 
    149     if (pScr->frameX1 < x) {
    150         pScr->frameX1 = x + 1;
    151         pScr->frameX0 = x - pScr->currentMode->HDisplay + 1;
    152         frameChanged = TRUE;
    153     }
    154 
    155     if (pScr->frameY0 > y) {
    156         pScr->frameY0 = y;
    157         pScr->frameY1 = y + pScr->currentMode->VDisplay - 1;
    158         frameChanged = TRUE;
    159     }
    160 
    161     if (pScr->frameY1 < y) {
    162         pScr->frameY1 = y;
    163         pScr->frameY0 = y - pScr->currentMode->VDisplay + 1;
    164         frameChanged = TRUE;
    165     }
    166 
    167     if (frameChanged && pScr->AdjustFrame != NULL)
    168         pScr->AdjustFrame(pScr, pScr->frameX0, pScr->frameY0);
    169 }
    170 
    171 /*
    172  * xf86LockZoom --
    173  *	Enable/disable ZoomViewport
    174  */
    175 
    176 void
    177 xf86LockZoom(ScreenPtr pScreen, Bool lock)
    178 {
    179     ScrnInfoPtr pScr = xf86ScreenToScrn(pScreen);
    180     pScr->zoomLocked = lock;
    181 }
    182 
    183 /*
    184  * xf86SwitchMode --
    185  *	This is called by both keyboard processing and the VidMode extension to
    186  *	set a new mode.
    187  */
    188 
    189 Bool
    190 xf86SwitchMode(ScreenPtr pScreen, DisplayModePtr mode)
    191 {
    192     ScrnInfoPtr pScr = xf86ScreenToScrn(pScreen);
    193     ScreenPtr pCursorScreen;
    194     Bool Switched;
    195     int px, py;
    196     DeviceIntPtr dev, it;
    197 
    198     if (!pScr->vtSema || !mode || !pScr->SwitchMode)
    199         return FALSE;
    200 
    201 #ifdef XFreeXDGA
    202     if (DGAActive(pScr->scrnIndex))
    203         return FALSE;
    204 #endif
    205 
    206     if (mode == pScr->currentMode)
    207         return TRUE;
    208 
    209     if (mode->HDisplay > pScr->virtualX || mode->VDisplay > pScr->virtualY)
    210         return FALSE;
    211 
    212     /* Let's take an educated guess for which pointer to take here. And about as
    213        educated as it gets is to take the first pointer we find.
    214      */
    215     for (dev = inputInfo.devices; dev; dev = dev->next) {
    216         if (IsPointerDevice(dev) && dev->spriteInfo->spriteOwner)
    217             break;
    218     }
    219 
    220     pCursorScreen = miPointerGetScreen(dev);
    221     if (pScreen == pCursorScreen)
    222         miPointerGetPosition(dev, &px, &py);
    223 
    224     input_lock();
    225     Switched = (*pScr->SwitchMode) (pScr, mode);
    226     if (Switched) {
    227         pScr->currentMode = mode;
    228 
    229         /*
    230          * Adjust frame for new display size.
    231          * Frame is centered around cursor position if cursor is on same screen.
    232          */
    233         if (pScreen == pCursorScreen)
    234             pScr->frameX0 = px - (mode->HDisplay / 2) + 1;
    235         else
    236             pScr->frameX0 =
    237                 (pScr->frameX0 + pScr->frameX1 + 1 - mode->HDisplay) / 2;
    238 
    239         if (pScr->frameX0 < 0)
    240             pScr->frameX0 = 0;
    241 
    242         pScr->frameX1 = pScr->frameX0 + mode->HDisplay - 1;
    243         if (pScr->frameX1 >= pScr->virtualX) {
    244             pScr->frameX0 = pScr->virtualX - mode->HDisplay;
    245             pScr->frameX1 = pScr->virtualX - 1;
    246         }
    247 
    248         if (pScreen == pCursorScreen)
    249             pScr->frameY0 = py - (mode->VDisplay / 2) + 1;
    250         else
    251             pScr->frameY0 =
    252                 (pScr->frameY0 + pScr->frameY1 + 1 - mode->VDisplay) / 2;
    253 
    254         if (pScr->frameY0 < 0)
    255             pScr->frameY0 = 0;
    256 
    257         pScr->frameY1 = pScr->frameY0 + mode->VDisplay - 1;
    258         if (pScr->frameY1 >= pScr->virtualY) {
    259             pScr->frameY0 = pScr->virtualY - mode->VDisplay;
    260             pScr->frameY1 = pScr->virtualY - 1;
    261         }
    262     }
    263     input_unlock();
    264 
    265     if (pScr->AdjustFrame)
    266         (*pScr->AdjustFrame) (pScr, pScr->frameX0, pScr->frameY0);
    267 
    268     /* The original code centered the frame around the cursor if possible.
    269      * Since this is hard to achieve with multiple cursors, we do the following:
    270      *   - center around the first pointer
    271      *   - move all other pointers to the nearest edge on the screen (or leave
    272      *   them unmodified if they are within the boundaries).
    273      */
    274     if (pScreen == pCursorScreen) {
    275         xf86WarpCursor(dev, pScreen, px, py);
    276     }
    277 
    278     for (it = inputInfo.devices; it; it = it->next) {
    279         if (it == dev)
    280             continue;
    281 
    282         if (IsPointerDevice(it) && it->spriteInfo->spriteOwner) {
    283             pCursorScreen = miPointerGetScreen(it);
    284             if (pScreen == pCursorScreen) {
    285                 miPointerGetPosition(it, &px, &py);
    286                 if (px < pScr->frameX0)
    287                     px = pScr->frameX0;
    288                 else if (px > pScr->frameX1)
    289                     px = pScr->frameX1;
    290 
    291                 if (py < pScr->frameY0)
    292                     py = pScr->frameY0;
    293                 else if (py > pScr->frameY1)
    294                     py = pScr->frameY1;
    295 
    296                 xf86WarpCursor(it, pScreen, px, py);
    297             }
    298         }
    299     }
    300 
    301     return Switched;
    302 }
    303 
    304 /*
    305  * xf86ZoomViewport --
    306  *      Reinitialize the visual part of the screen for another mode.
    307  */
    308 
    309 void
    310 xf86ZoomViewport(ScreenPtr pScreen, int zoom)
    311 {
    312     ScrnInfoPtr pScr = xf86ScreenToScrn(pScreen);
    313     DisplayModePtr mode;
    314 
    315     if (pScr->zoomLocked || !(mode = pScr->currentMode))
    316         return;
    317 
    318     do {
    319         if (zoom > 0)
    320             mode = mode->next;
    321         else
    322             mode = mode->prev;
    323     } while (mode != pScr->currentMode && !(mode->type & M_T_USERDEF));
    324 
    325     (void) xf86SwitchMode(pScreen, mode);
    326 }
    327 
    328 static xf86EdgePtr
    329 FindEdge(xf86EdgePtr edge, int val)
    330 {
    331     while (edge && (edge->end <= val))
    332         edge = edge->next;
    333 
    334     if (edge && (edge->start <= val))
    335         return edge;
    336 
    337     return NULL;
    338 }
    339 
    340 /*
    341  * xf86CursorOffScreen --
    342  *      Check whether it is necessary to switch to another screen
    343  */
    344 
    345 static Bool
    346 xf86CursorOffScreen(ScreenPtr *pScreen, int *x, int *y)
    347 {
    348     xf86EdgePtr edge;
    349     int tmp;
    350 
    351     if (screenInfo.numScreens == 1)
    352         return FALSE;
    353 
    354     if (*x < 0) {
    355         tmp = *y;
    356         if (tmp < 0)
    357             tmp = 0;
    358         if (tmp >= (*pScreen)->height)
    359             tmp = (*pScreen)->height - 1;
    360 
    361         if ((edge = xf86ScreenLayout[(*pScreen)->myNum].left))
    362             edge = FindEdge(edge, tmp);
    363 
    364         if (!edge)
    365             *x = 0;
    366         else {
    367             *x += edge->offset.x;
    368             *y += edge->offset.y;
    369             *pScreen = xf86Screens[edge->screen]->pScreen;
    370         }
    371     }
    372 
    373     if (*x >= (*pScreen)->width) {
    374         tmp = *y;
    375         if (tmp < 0)
    376             tmp = 0;
    377         if (tmp >= (*pScreen)->height)
    378             tmp = (*pScreen)->height - 1;
    379 
    380         if ((edge = xf86ScreenLayout[(*pScreen)->myNum].right))
    381             edge = FindEdge(edge, tmp);
    382 
    383         if (!edge)
    384             *x = (*pScreen)->width - 1;
    385         else {
    386             *x += edge->offset.x;
    387             *y += edge->offset.y;
    388             *pScreen = xf86Screens[edge->screen]->pScreen;
    389         }
    390     }
    391 
    392     if (*y < 0) {
    393         tmp = *x;
    394         if (tmp < 0)
    395             tmp = 0;
    396         if (tmp >= (*pScreen)->width)
    397             tmp = (*pScreen)->width - 1;
    398 
    399         if ((edge = xf86ScreenLayout[(*pScreen)->myNum].up))
    400             edge = FindEdge(edge, tmp);
    401 
    402         if (!edge)
    403             *y = 0;
    404         else {
    405             *x += edge->offset.x;
    406             *y += edge->offset.y;
    407             *pScreen = xf86Screens[edge->screen]->pScreen;
    408         }
    409     }
    410 
    411     if (*y >= (*pScreen)->height) {
    412         tmp = *x;
    413         if (tmp < 0)
    414             tmp = 0;
    415         if (tmp >= (*pScreen)->width)
    416             tmp = (*pScreen)->width - 1;
    417 
    418         if ((edge = xf86ScreenLayout[(*pScreen)->myNum].down))
    419             edge = FindEdge(edge, tmp);
    420 
    421         if (!edge)
    422             *y = (*pScreen)->height - 1;
    423         else {
    424             *x += edge->offset.x;
    425             *y += edge->offset.y;
    426             (*pScreen) = xf86Screens[edge->screen]->pScreen;
    427         }
    428     }
    429 
    430     return TRUE;
    431 }
    432 
    433 /*
    434  * xf86CrossScreen --
    435  *      Switch to another screen
    436  *
    437  *	Currently nothing special happens, but mi assumes the CrossScreen
    438  *	method exists.
    439  */
    440 
    441 static void
    442 xf86CrossScreen(ScreenPtr pScreen, Bool entering)
    443 {
    444 }
    445 
    446 /*
    447  * xf86WarpCursor --
    448  *      Warp possible to another screen
    449  */
    450 
    451 /* ARGSUSED */
    452 static void
    453 xf86WarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
    454 {
    455     input_lock();
    456     miPointerWarpCursor(pDev, pScreen, x, y);
    457 
    458     xf86Info.currentScreen = pScreen;
    459     input_unlock();
    460 }
    461 
    462 void *
    463 xf86GetPointerScreenFuncs(void)
    464 {
    465     return (void *) &xf86PointerScreenFuncs;
    466 }
    467 
    468 static xf86EdgePtr
    469 AddEdge(xf86EdgePtr edge,
    470         short min, short max, short dx, short dy, short screen)
    471 {
    472     xf86EdgePtr pEdge = edge, pPrev = NULL, pNew;
    473 
    474     while (1) {
    475         while (pEdge && (min >= pEdge->end)) {
    476             pPrev = pEdge;
    477             pEdge = pEdge->next;
    478         }
    479 
    480         if (!pEdge) {
    481             if (!(pNew = malloc(sizeof(xf86EdgeRec))))
    482                 break;
    483 
    484             pNew->screen = screen;
    485             pNew->start = min;
    486             pNew->end = max;
    487             pNew->offset.x = dx;
    488             pNew->offset.y = dy;
    489             pNew->next = NULL;
    490 
    491             if (pPrev)
    492                 pPrev->next = pNew;
    493             else
    494                 edge = pNew;
    495 
    496             break;
    497         }
    498         else if (min < pEdge->start) {
    499             if (!(pNew = malloc(sizeof(xf86EdgeRec))))
    500                 break;
    501 
    502             pNew->screen = screen;
    503             pNew->start = min;
    504             pNew->offset.x = dx;
    505             pNew->offset.y = dy;
    506             pNew->next = pEdge;
    507 
    508             if (pPrev)
    509                 pPrev->next = pNew;
    510             else
    511                 edge = pNew;
    512 
    513             if (max <= pEdge->start) {
    514                 pNew->end = max;
    515                 break;
    516             }
    517             else {
    518                 pNew->end = pEdge->start;
    519                 min = pEdge->end;
    520             }
    521         }
    522         else
    523             min = pEdge->end;
    524 
    525         pPrev = pEdge;
    526         pEdge = pEdge->next;
    527 
    528         if (max <= min)
    529             break;
    530     }
    531 
    532     return edge;
    533 }
    534 
    535 static void
    536 FillOutEdge(xf86EdgePtr pEdge, int limit)
    537 {
    538     xf86EdgePtr pNext;
    539     int diff;
    540 
    541     if (pEdge->start > 0)
    542         pEdge->start = 0;
    543 
    544     while ((pNext = pEdge->next)) {
    545         diff = pNext->start - pEdge->end;
    546         if (diff > 0) {
    547             pEdge->end += diff >> 1;
    548             pNext->start -= diff - (diff >> 1);
    549         }
    550         pEdge = pNext;
    551     }
    552 
    553     if (pEdge->end < limit)
    554         pEdge->end = limit;
    555 }
    556 
    557 /*
    558  * xf86InitOrigins() can deal with a maximum of 32 screens
    559  * on 32 bit architectures, 64 on 64 bit architectures.
    560  */
    561 
    562 void
    563 xf86InitOrigins(void)
    564 {
    565     unsigned long screensLeft, prevScreensLeft, mask;
    566     screenLayoutPtr screen;
    567     ScreenPtr pScreen, refScreen;
    568     int x1, x2, y1, y2, left, right, top, bottom;
    569     int i, j, ref, minX, minY, min, max;
    570     xf86ScreenLayoutPtr pLayout;
    571     Bool OldStyleConfig = FALSE;
    572 
    573     memset(xf86ScreenLayout, 0, MAXSCREENS * sizeof(xf86ScreenLayoutRec));
    574 
    575     screensLeft = prevScreensLeft = (1 << xf86NumScreens) - 1;
    576 
    577     while (1) {
    578         for (mask = screensLeft, i = 0; mask; mask >>= 1, i++) {
    579             if (!(mask & 1L))
    580                 continue;
    581 
    582             screen = &xf86ConfigLayout.screens[i];
    583 
    584             if (screen->refscreen != NULL &&
    585                 screen->refscreen->screennum >= xf86NumScreens) {
    586                 screensLeft &= ~(1 << i);
    587                 xf86Msg(X_WARNING,
    588                         "Not including screen \"%s\" in origins calculation.\n",
    589                         screen->screen->id);
    590                 continue;
    591             }
    592 
    593             pScreen = xf86Screens[i]->pScreen;
    594             switch (screen->where) {
    595             case PosObsolete:
    596                 OldStyleConfig = TRUE;
    597                 pLayout = &xf86ScreenLayout[i];
    598                 /* force edge lists */
    599                 if (screen->left) {
    600                     ref = screen->left->screennum;
    601                     if (!xf86Screens[ref] || !xf86Screens[ref]->pScreen) {
    602                         ErrorF("Referenced uninitialized screen in Layout!\n");
    603                         break;
    604                     }
    605                     pLayout->left = AddEdge(pLayout->left,
    606                                             0, pScreen->height,
    607                                             xf86Screens[ref]->pScreen->width, 0,
    608                                             ref);
    609                 }
    610                 if (screen->right) {
    611                     ref = screen->right->screennum;
    612                     if (!xf86Screens[ref] || !xf86Screens[ref]->pScreen) {
    613                         ErrorF("Referenced uninitialized screen in Layout!\n");
    614                         break;
    615                     }
    616                     pLayout->right = AddEdge(pLayout->right,
    617                                              0, pScreen->height,
    618                                              -pScreen->width, 0, ref);
    619                 }
    620                 if (screen->top) {
    621                     ref = screen->top->screennum;
    622                     if (!xf86Screens[ref] || !xf86Screens[ref]->pScreen) {
    623                         ErrorF("Referenced uninitialized screen in Layout!\n");
    624                         break;
    625                     }
    626                     pLayout->up = AddEdge(pLayout->up,
    627                                           0, pScreen->width,
    628                                           0, xf86Screens[ref]->pScreen->height,
    629                                           ref);
    630                 }
    631                 if (screen->bottom) {
    632                     ref = screen->bottom->screennum;
    633                     if (!xf86Screens[ref] || !xf86Screens[ref]->pScreen) {
    634                         ErrorF("Referenced uninitialized screen in Layout!\n");
    635                         break;
    636                     }
    637                     pLayout->down = AddEdge(pLayout->down,
    638                                             0, pScreen->width, 0,
    639                                             -pScreen->height, ref);
    640                 }
    641                 /* we could also try to place it based on those
    642                    relative locations if we wanted to */
    643                 screen->x = screen->y = 0;
    644                 /* FALLTHROUGH */
    645             case PosAbsolute:
    646                 pScreen->x = screen->x;
    647                 pScreen->y = screen->y;
    648                 screensLeft &= ~(1 << i);
    649                 break;
    650             case PosRelative:
    651                 ref = screen->refscreen->screennum;
    652                 if (!xf86Screens[ref] || !xf86Screens[ref]->pScreen) {
    653                     ErrorF("Referenced uninitialized screen in Layout!\n");
    654                     break;
    655                 }
    656                 if (screensLeft & (1 << ref))
    657                     break;
    658                 refScreen = xf86Screens[ref]->pScreen;
    659                 pScreen->x = refScreen->x + screen->x;
    660                 pScreen->y = refScreen->y + screen->y;
    661                 screensLeft &= ~(1 << i);
    662                 break;
    663             case PosRightOf:
    664                 ref = screen->refscreen->screennum;
    665                 if (!xf86Screens[ref] || !xf86Screens[ref]->pScreen) {
    666                     ErrorF("Referenced uninitialized screen in Layout!\n");
    667                     break;
    668                 }
    669                 if (screensLeft & (1 << ref))
    670                     break;
    671                 refScreen = xf86Screens[ref]->pScreen;
    672                 pScreen->x = refScreen->x + refScreen->width;
    673                 pScreen->y = refScreen->y;
    674                 screensLeft &= ~(1 << i);
    675                 break;
    676             case PosLeftOf:
    677                 ref = screen->refscreen->screennum;
    678                 if (!xf86Screens[ref] || !xf86Screens[ref]->pScreen) {
    679                     ErrorF("Referenced uninitialized screen in Layout!\n");
    680                     break;
    681                 }
    682                 if (screensLeft & (1 << ref))
    683                     break;
    684                 refScreen = xf86Screens[ref]->pScreen;
    685                 pScreen->x = refScreen->x - pScreen->width;
    686                 pScreen->y = refScreen->y;
    687                 screensLeft &= ~(1 << i);
    688                 break;
    689             case PosBelow:
    690                 ref = screen->refscreen->screennum;
    691                 if (!xf86Screens[ref] || !xf86Screens[ref]->pScreen) {
    692                     ErrorF("Referenced uninitialized screen in Layout!\n");
    693                     break;
    694                 }
    695                 if (screensLeft & (1 << ref))
    696                     break;
    697                 refScreen = xf86Screens[ref]->pScreen;
    698                 pScreen->x = refScreen->x;
    699                 pScreen->y = refScreen->y + refScreen->height;
    700                 screensLeft &= ~(1 << i);
    701                 break;
    702             case PosAbove:
    703                 ref = screen->refscreen->screennum;
    704                 if (!xf86Screens[ref] || !xf86Screens[ref]->pScreen) {
    705                     ErrorF("Referenced uninitialized screen in Layout!\n");
    706                     break;
    707                 }
    708                 if (screensLeft & (1 << ref))
    709                     break;
    710                 refScreen = xf86Screens[ref]->pScreen;
    711                 pScreen->x = refScreen->x;
    712                 pScreen->y = refScreen->y - pScreen->height;
    713                 screensLeft &= ~(1 << i);
    714                 break;
    715             default:
    716                 ErrorF("Illegal placement keyword in Layout!\n");
    717                 break;
    718             }
    719 
    720         }
    721 
    722         if (!screensLeft)
    723             break;
    724 
    725         if (screensLeft == prevScreensLeft) {
    726             /* All the remaining screens are referencing each other.
    727                Assign a value to one of them and go through again */
    728             i = 0;
    729             while (!((1 << i) & screensLeft)) {
    730                 i++;
    731             }
    732 
    733             ref = xf86ConfigLayout.screens[i].refscreen->screennum;
    734             xf86Screens[ref]->pScreen->x = xf86Screens[ref]->pScreen->y = 0;
    735             screensLeft &= ~(1 << ref);
    736         }
    737 
    738         prevScreensLeft = screensLeft;
    739     }
    740 
    741     /* justify the topmost and leftmost to (0,0) */
    742     minX = xf86Screens[0]->pScreen->x;
    743     minY = xf86Screens[0]->pScreen->y;
    744 
    745     for (i = 1; i < xf86NumScreens; i++) {
    746         if (xf86Screens[i]->pScreen->x < minX)
    747             minX = xf86Screens[i]->pScreen->x;
    748         if (xf86Screens[i]->pScreen->y < minY)
    749             minY = xf86Screens[i]->pScreen->y;
    750     }
    751 
    752     if (minX || minY) {
    753         for (i = 0; i < xf86NumScreens; i++) {
    754             xf86Screens[i]->pScreen->x -= minX;
    755             xf86Screens[i]->pScreen->y -= minY;
    756         }
    757     }
    758 
    759     /* Create the edge lists */
    760 
    761     if (!OldStyleConfig) {
    762         for (i = 0; i < xf86NumScreens; i++) {
    763             pLayout = &xf86ScreenLayout[i];
    764 
    765             pScreen = xf86Screens[i]->pScreen;
    766 
    767             left = pScreen->x;
    768             right = left + pScreen->width;
    769             top = pScreen->y;
    770             bottom = top + pScreen->height;
    771 
    772             for (j = 0; j < xf86NumScreens; j++) {
    773                 if (i == j)
    774                     continue;
    775 
    776                 refScreen = xf86Screens[j]->pScreen;
    777 
    778                 x1 = refScreen->x;
    779                 x2 = x1 + refScreen->width;
    780                 y1 = refScreen->y;
    781                 y2 = y1 + refScreen->height;
    782 
    783                 if ((bottom > y1) && (top < y2)) {
    784                     min = y1 - top;
    785                     if (min < 0)
    786                         min = 0;
    787                     max = pScreen->height - (bottom - y2);
    788                     if (max > pScreen->height)
    789                         max = pScreen->height;
    790 
    791                     if (((left - 1) >= x1) && ((left - 1) < x2))
    792                         pLayout->left = AddEdge(pLayout->left, min, max,
    793                                                 pScreen->x - refScreen->x,
    794                                                 pScreen->y - refScreen->y, j);
    795 
    796                     if ((right >= x1) && (right < x2))
    797                         pLayout->right = AddEdge(pLayout->right, min, max,
    798                                                  pScreen->x - refScreen->x,
    799                                                  pScreen->y - refScreen->y, j);
    800                 }
    801 
    802                 if ((left < x2) && (right > x1)) {
    803                     min = x1 - left;
    804                     if (min < 0)
    805                         min = 0;
    806                     max = pScreen->width - (right - x2);
    807                     if (max > pScreen->width)
    808                         max = pScreen->width;
    809 
    810                     if (((top - 1) >= y1) && ((top - 1) < y2))
    811                         pLayout->up = AddEdge(pLayout->up, min, max,
    812                                               pScreen->x - refScreen->x,
    813                                               pScreen->y - refScreen->y, j);
    814 
    815                     if ((bottom >= y1) && (bottom < y2))
    816                         pLayout->down = AddEdge(pLayout->down, min, max,
    817                                                 pScreen->x - refScreen->x,
    818                                                 pScreen->y - refScreen->y, j);
    819                 }
    820             }
    821         }
    822     }
    823 
    824     if (!OldStyleConfig) {
    825         for (i = 0; i < xf86NumScreens; i++) {
    826             pLayout = &xf86ScreenLayout[i];
    827             pScreen = xf86Screens[i]->pScreen;
    828             if (pLayout->left)
    829                 FillOutEdge(pLayout->left, pScreen->height);
    830             if (pLayout->right)
    831                 FillOutEdge(pLayout->right, pScreen->height);
    832             if (pLayout->up)
    833                 FillOutEdge(pLayout->up, pScreen->width);
    834             if (pLayout->down)
    835                 FillOutEdge(pLayout->down, pScreen->width);
    836         }
    837     }
    838 
    839     update_desktop_dimensions();
    840 }
    841 
    842 void
    843 xf86ReconfigureLayout(void)
    844 {
    845     int i;
    846 
    847     for (i = 0; i < MAXSCREENS; i++) {
    848         xf86ScreenLayoutPtr sl = &xf86ScreenLayout[i];
    849 
    850         /* we don't have to zero these, xf86InitOrigins() takes care of that */
    851         free(sl->left);
    852         free(sl->right);
    853         free(sl->up);
    854         free(sl->down);
    855     }
    856 
    857     xf86InitOrigins();
    858 }