xserver

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

Window.c (15657B)


      1 /*
      2 
      3 Copyright 1993 by Davor Matic
      4 
      5 Permission to use, copy, modify, distribute, and sell this software
      6 and its documentation for any purpose is hereby granted without fee,
      7 provided that the above copyright notice appear in all copies and that
      8 both that copyright notice and this permission notice appear in
      9 supporting documentation.  Davor Matic makes no representations about
     10 the suitability of this software for any purpose.  It is provided "as
     11 is" without express or implied warranty.
     12 
     13 */
     14 
     15 #ifdef HAVE_XNEST_CONFIG_H
     16 #include <xnest-config.h>
     17 #endif
     18 
     19 #include <X11/X.h>
     20 #include <X11/Xproto.h>
     21 #include "gcstruct.h"
     22 #include "window.h"
     23 #include "windowstr.h"
     24 #include "pixmapstr.h"
     25 #include "colormapst.h"
     26 #include "scrnintstr.h"
     27 #include "region.h"
     28 
     29 #include "mi.h"
     30 
     31 #include "Xnest.h"
     32 
     33 #include "Display.h"
     34 #include "Screen.h"
     35 #include "XNGC.h"
     36 #include "Drawable.h"
     37 #include "Color.h"
     38 #include "Visual.h"
     39 #include "Events.h"
     40 #include "Args.h"
     41 
     42 DevPrivateKeyRec xnestWindowPrivateKeyRec;
     43 
     44 static int
     45 xnestFindWindowMatch(WindowPtr pWin, void *ptr)
     46 {
     47     xnestWindowMatch *wm = (xnestWindowMatch *) ptr;
     48 
     49     if (wm->window == xnestWindow(pWin)) {
     50         wm->pWin = pWin;
     51         return WT_STOPWALKING;
     52     }
     53     else
     54         return WT_WALKCHILDREN;
     55 }
     56 
     57 WindowPtr
     58 xnestWindowPtr(Window window)
     59 {
     60     xnestWindowMatch wm;
     61     int i;
     62 
     63     wm.pWin = NullWindow;
     64     wm.window = window;
     65 
     66     for (i = 0; i < xnestNumScreens; i++) {
     67         WalkTree(screenInfo.screens[i], xnestFindWindowMatch, (void *) &wm);
     68         if (wm.pWin)
     69             break;
     70     }
     71 
     72     return wm.pWin;
     73 }
     74 
     75 Bool
     76 xnestCreateWindow(WindowPtr pWin)
     77 {
     78     unsigned long mask;
     79     XSetWindowAttributes attributes;
     80     Visual *visual;
     81     ColormapPtr pCmap;
     82 
     83     if (pWin->drawable.class == InputOnly) {
     84         mask = 0L;
     85         visual = CopyFromParent;
     86     }
     87     else {
     88         mask = CWEventMask | CWBackingStore;
     89         attributes.event_mask = ExposureMask;
     90         attributes.backing_store = NotUseful;
     91 
     92         if (pWin->parent) {
     93             if (pWin->optional &&
     94                 pWin->optional->visual != wVisual(pWin->parent)) {
     95                 visual =
     96                     xnestVisualFromID(pWin->drawable.pScreen, wVisual(pWin));
     97                 mask |= CWColormap;
     98                 if (pWin->optional->colormap) {
     99                     dixLookupResourceByType((void **) &pCmap, wColormap(pWin),
    100                                             RT_COLORMAP, serverClient,
    101                                             DixUseAccess);
    102                     attributes.colormap = xnestColormap(pCmap);
    103                 }
    104                 else
    105                     attributes.colormap = xnestDefaultVisualColormap(visual);
    106             }
    107             else
    108                 visual = CopyFromParent;
    109         }
    110         else {                  /* root windows have their own colormaps at creation time */
    111             visual = xnestVisualFromID(pWin->drawable.pScreen, wVisual(pWin));
    112             dixLookupResourceByType((void **) &pCmap, wColormap(pWin),
    113                                     RT_COLORMAP, serverClient, DixUseAccess);
    114             mask |= CWColormap;
    115             attributes.colormap = xnestColormap(pCmap);
    116         }
    117     }
    118 
    119     xnestWindowPriv(pWin)->window = XCreateWindow(xnestDisplay,
    120                                                   xnestWindowParent(pWin),
    121                                                   pWin->origin.x -
    122                                                   wBorderWidth(pWin),
    123                                                   pWin->origin.y -
    124                                                   wBorderWidth(pWin),
    125                                                   pWin->drawable.width,
    126                                                   pWin->drawable.height,
    127                                                   pWin->borderWidth,
    128                                                   pWin->drawable.depth,
    129                                                   pWin->drawable.class,
    130                                                   visual, mask, &attributes);
    131     xnestWindowPriv(pWin)->parent = xnestWindowParent(pWin);
    132     xnestWindowPriv(pWin)->x = pWin->origin.x - wBorderWidth(pWin);
    133     xnestWindowPriv(pWin)->y = pWin->origin.y - wBorderWidth(pWin);
    134     xnestWindowPriv(pWin)->width = pWin->drawable.width;
    135     xnestWindowPriv(pWin)->height = pWin->drawable.height;
    136     xnestWindowPriv(pWin)->border_width = pWin->borderWidth;
    137     xnestWindowPriv(pWin)->sibling_above = None;
    138     if (pWin->nextSib)
    139         xnestWindowPriv(pWin->nextSib)->sibling_above = xnestWindow(pWin);
    140     xnestWindowPriv(pWin)->bounding_shape = RegionCreate(NULL, 1);
    141     xnestWindowPriv(pWin)->clip_shape = RegionCreate(NULL, 1);
    142 
    143     if (!pWin->parent)          /* only the root window will have the right colormap */
    144         xnestSetInstalledColormapWindows(pWin->drawable.pScreen);
    145 
    146     return True;
    147 }
    148 
    149 Bool
    150 xnestDestroyWindow(WindowPtr pWin)
    151 {
    152     if (pWin->nextSib)
    153         xnestWindowPriv(pWin->nextSib)->sibling_above =
    154             xnestWindowPriv(pWin)->sibling_above;
    155     RegionDestroy(xnestWindowPriv(pWin)->bounding_shape);
    156     RegionDestroy(xnestWindowPriv(pWin)->clip_shape);
    157     XDestroyWindow(xnestDisplay, xnestWindow(pWin));
    158     xnestWindowPriv(pWin)->window = None;
    159 
    160     if (pWin->optional && pWin->optional->colormap && pWin->parent)
    161         xnestSetInstalledColormapWindows(pWin->drawable.pScreen);
    162 
    163     return True;
    164 }
    165 
    166 Bool
    167 xnestPositionWindow(WindowPtr pWin, int x, int y)
    168 {
    169     xnestConfigureWindow(pWin,
    170                          CWParent |
    171                          CWX | CWY | CWWidth | CWHeight | CWBorderWidth);
    172 
    173     return True;
    174 }
    175 
    176 void
    177 xnestConfigureWindow(WindowPtr pWin, unsigned int mask)
    178 {
    179     unsigned int valuemask;
    180     XWindowChanges values;
    181 
    182     if (mask & CWParent &&
    183         xnestWindowPriv(pWin)->parent != xnestWindowParent(pWin)) {
    184         XReparentWindow(xnestDisplay, xnestWindow(pWin),
    185                         xnestWindowParent(pWin),
    186                         pWin->origin.x - wBorderWidth(pWin),
    187                         pWin->origin.y - wBorderWidth(pWin));
    188         xnestWindowPriv(pWin)->parent = xnestWindowParent(pWin);
    189         xnestWindowPriv(pWin)->x = pWin->origin.x - wBorderWidth(pWin);
    190         xnestWindowPriv(pWin)->y = pWin->origin.y - wBorderWidth(pWin);
    191         xnestWindowPriv(pWin)->sibling_above = None;
    192         if (pWin->nextSib)
    193             xnestWindowPriv(pWin->nextSib)->sibling_above = xnestWindow(pWin);
    194     }
    195 
    196     valuemask = 0;
    197 
    198     if (mask & CWX &&
    199         xnestWindowPriv(pWin)->x != pWin->origin.x - wBorderWidth(pWin)) {
    200         valuemask |= CWX;
    201         values.x =
    202             xnestWindowPriv(pWin)->x = pWin->origin.x - wBorderWidth(pWin);
    203     }
    204 
    205     if (mask & CWY &&
    206         xnestWindowPriv(pWin)->y != pWin->origin.y - wBorderWidth(pWin)) {
    207         valuemask |= CWY;
    208         values.y =
    209             xnestWindowPriv(pWin)->y = pWin->origin.y - wBorderWidth(pWin);
    210     }
    211 
    212     if (mask & CWWidth && xnestWindowPriv(pWin)->width != pWin->drawable.width) {
    213         valuemask |= CWWidth;
    214         values.width = xnestWindowPriv(pWin)->width = pWin->drawable.width;
    215     }
    216 
    217     if (mask & CWHeight &&
    218         xnestWindowPriv(pWin)->height != pWin->drawable.height) {
    219         valuemask |= CWHeight;
    220         values.height = xnestWindowPriv(pWin)->height = pWin->drawable.height;
    221     }
    222 
    223     if (mask & CWBorderWidth &&
    224         xnestWindowPriv(pWin)->border_width != pWin->borderWidth) {
    225         valuemask |= CWBorderWidth;
    226         values.border_width =
    227             xnestWindowPriv(pWin)->border_width = pWin->borderWidth;
    228     }
    229 
    230     if (valuemask)
    231         XConfigureWindow(xnestDisplay, xnestWindow(pWin), valuemask, &values);
    232 
    233     if (mask & CWStackingOrder &&
    234         xnestWindowPriv(pWin)->sibling_above != xnestWindowSiblingAbove(pWin)) {
    235         WindowPtr pSib;
    236 
    237         /* find the top sibling */
    238         for (pSib = pWin; pSib->prevSib != NullWindow; pSib = pSib->prevSib);
    239 
    240         /* the top sibling */
    241         valuemask = CWStackMode;
    242         values.stack_mode = Above;
    243         XConfigureWindow(xnestDisplay, xnestWindow(pSib), valuemask, &values);
    244         xnestWindowPriv(pSib)->sibling_above = None;
    245 
    246         /* the rest of siblings */
    247         for (pSib = pSib->nextSib; pSib != NullWindow; pSib = pSib->nextSib) {
    248             valuemask = CWSibling | CWStackMode;
    249             values.sibling = xnestWindowSiblingAbove(pSib);
    250             values.stack_mode = Below;
    251             XConfigureWindow(xnestDisplay, xnestWindow(pSib), valuemask,
    252                              &values);
    253             xnestWindowPriv(pSib)->sibling_above =
    254                 xnestWindowSiblingAbove(pSib);
    255         }
    256     }
    257 }
    258 
    259 Bool
    260 xnestChangeWindowAttributes(WindowPtr pWin, unsigned long mask)
    261 {
    262     XSetWindowAttributes attributes;
    263 
    264     if (mask & CWBackPixmap)
    265         switch (pWin->backgroundState) {
    266         case None:
    267             attributes.background_pixmap = None;
    268             break;
    269 
    270         case ParentRelative:
    271             attributes.background_pixmap = ParentRelative;
    272             break;
    273 
    274         case BackgroundPixmap:
    275             attributes.background_pixmap = xnestPixmap(pWin->background.pixmap);
    276             break;
    277 
    278         case BackgroundPixel:
    279             mask &= ~CWBackPixmap;
    280             break;
    281         }
    282 
    283     if (mask & CWBackPixel) {
    284         if (pWin->backgroundState == BackgroundPixel)
    285             attributes.background_pixel = xnestPixel(pWin->background.pixel);
    286         else
    287             mask &= ~CWBackPixel;
    288     }
    289 
    290     if (mask & CWBorderPixmap) {
    291         if (pWin->borderIsPixel)
    292             mask &= ~CWBorderPixmap;
    293         else
    294             attributes.border_pixmap = xnestPixmap(pWin->border.pixmap);
    295     }
    296 
    297     if (mask & CWBorderPixel) {
    298         if (pWin->borderIsPixel)
    299             attributes.border_pixel = xnestPixel(pWin->border.pixel);
    300         else
    301             mask &= ~CWBorderPixel;
    302     }
    303 
    304     if (mask & CWBitGravity)
    305         attributes.bit_gravity = pWin->bitGravity;
    306 
    307     if (mask & CWWinGravity)    /* dix does this for us */
    308         mask &= ~CWWinGravity;
    309 
    310     if (mask & CWBackingStore)  /* this is really not useful */
    311         mask &= ~CWBackingStore;
    312 
    313     if (mask & CWBackingPlanes) /* this is really not useful */
    314         mask &= ~CWBackingPlanes;
    315 
    316     if (mask & CWBackingPixel)  /* this is really not useful */
    317         mask &= ~CWBackingPixel;
    318 
    319     if (mask & CWOverrideRedirect)
    320         attributes.override_redirect = pWin->overrideRedirect;
    321 
    322     if (mask & CWSaveUnder)     /* this is really not useful */
    323         mask &= ~CWSaveUnder;
    324 
    325     if (mask & CWEventMask)     /* events are handled elsewhere */
    326         mask &= ~CWEventMask;
    327 
    328     if (mask & CWDontPropagate) /* events are handled elsewhere */
    329         mask &= ~CWDontPropagate;
    330 
    331     if (mask & CWColormap) {
    332         ColormapPtr pCmap;
    333 
    334         dixLookupResourceByType((void **) &pCmap, wColormap(pWin),
    335                                 RT_COLORMAP, serverClient, DixUseAccess);
    336 
    337         attributes.colormap = xnestColormap(pCmap);
    338 
    339         xnestSetInstalledColormapWindows(pWin->drawable.pScreen);
    340     }
    341 
    342     if (mask & CWCursor)        /* this is handled in cursor code */
    343         mask &= ~CWCursor;
    344 
    345     if (mask)
    346         XChangeWindowAttributes(xnestDisplay, xnestWindow(pWin),
    347                                 mask, &attributes);
    348 
    349     return True;
    350 }
    351 
    352 Bool
    353 xnestRealizeWindow(WindowPtr pWin)
    354 {
    355     xnestConfigureWindow(pWin, CWStackingOrder);
    356     xnestShapeWindow(pWin);
    357     XMapWindow(xnestDisplay, xnestWindow(pWin));
    358 
    359     return True;
    360 }
    361 
    362 Bool
    363 xnestUnrealizeWindow(WindowPtr pWin)
    364 {
    365     XUnmapWindow(xnestDisplay, xnestWindow(pWin));
    366 
    367     return True;
    368 }
    369 
    370 void
    371 xnestCopyWindow(WindowPtr pWin, xPoint oldOrigin, RegionPtr oldRegion)
    372 {
    373 }
    374 
    375 void
    376 xnestClipNotify(WindowPtr pWin, int dx, int dy)
    377 {
    378     xnestConfigureWindow(pWin, CWStackingOrder);
    379     xnestShapeWindow(pWin);
    380 }
    381 
    382 static Bool
    383 xnestWindowExposurePredicate(Display * dpy, XEvent * event, XPointer ptr)
    384 {
    385     return (event->type == Expose && event->xexpose.window == *(Window *) ptr);
    386 }
    387 
    388 void
    389 xnestWindowExposures(WindowPtr pWin, RegionPtr pRgn)
    390 {
    391     XEvent event;
    392     Window window;
    393     BoxRec Box;
    394 
    395     XSync(xnestDisplay, False);
    396 
    397     window = xnestWindow(pWin);
    398 
    399     while (XCheckIfEvent(xnestDisplay, &event,
    400                          xnestWindowExposurePredicate, (char *) &window)) {
    401 
    402         Box.x1 = pWin->drawable.x + wBorderWidth(pWin) + event.xexpose.x;
    403         Box.y1 = pWin->drawable.y + wBorderWidth(pWin) + event.xexpose.y;
    404         Box.x2 = Box.x1 + event.xexpose.width;
    405         Box.y2 = Box.y1 + event.xexpose.height;
    406 
    407         event.xexpose.type = ProcessedExpose;
    408 
    409         if (RegionContainsRect(pRgn, &Box) != rgnIN)
    410             XPutBackEvent(xnestDisplay, &event);
    411     }
    412 
    413     miWindowExposures(pWin, pRgn);
    414 }
    415 
    416 void
    417 xnestSetShape(WindowPtr pWin, int kind)
    418 {
    419     xnestShapeWindow(pWin);
    420     miSetShape(pWin, kind);
    421 }
    422 
    423 static Bool
    424 xnestRegionEqual(RegionPtr pReg1, RegionPtr pReg2)
    425 {
    426     BoxPtr pBox1, pBox2;
    427     unsigned int n1, n2;
    428 
    429     if (pReg1 == pReg2)
    430         return True;
    431 
    432     if (pReg1 == NullRegion || pReg2 == NullRegion)
    433         return False;
    434 
    435     pBox1 = RegionRects(pReg1);
    436     n1 = RegionNumRects(pReg1);
    437 
    438     pBox2 = RegionRects(pReg2);
    439     n2 = RegionNumRects(pReg2);
    440 
    441     if (n1 != n2)
    442         return False;
    443 
    444     if (pBox1 == pBox2)
    445         return True;
    446 
    447     if (memcmp(pBox1, pBox2, n1 * sizeof(BoxRec)))
    448         return False;
    449 
    450     return True;
    451 }
    452 
    453 void
    454 xnestShapeWindow(WindowPtr pWin)
    455 {
    456     Region reg;
    457     BoxPtr pBox;
    458     XRectangle rect;
    459     int i;
    460 
    461     if (!xnestRegionEqual(xnestWindowPriv(pWin)->bounding_shape,
    462                           wBoundingShape(pWin))) {
    463 
    464         if (wBoundingShape(pWin)) {
    465             RegionCopy(xnestWindowPriv(pWin)->bounding_shape,
    466                        wBoundingShape(pWin));
    467 
    468             reg = XCreateRegion();
    469             pBox = RegionRects(xnestWindowPriv(pWin)->bounding_shape);
    470             for (i = 0;
    471                  i < RegionNumRects(xnestWindowPriv(pWin)->bounding_shape);
    472                  i++) {
    473                 rect.x = pBox[i].x1;
    474                 rect.y = pBox[i].y1;
    475                 rect.width = pBox[i].x2 - pBox[i].x1;
    476                 rect.height = pBox[i].y2 - pBox[i].y1;
    477                 XUnionRectWithRegion(&rect, reg, reg);
    478             }
    479             XShapeCombineRegion(xnestDisplay, xnestWindow(pWin),
    480                                 ShapeBounding, 0, 0, reg, ShapeSet);
    481             XDestroyRegion(reg);
    482         }
    483         else {
    484             RegionEmpty(xnestWindowPriv(pWin)->bounding_shape);
    485 
    486             XShapeCombineMask(xnestDisplay, xnestWindow(pWin),
    487                               ShapeBounding, 0, 0, None, ShapeSet);
    488         }
    489     }
    490 
    491     if (!xnestRegionEqual(xnestWindowPriv(pWin)->clip_shape, wClipShape(pWin))) {
    492 
    493         if (wClipShape(pWin)) {
    494             RegionCopy(xnestWindowPriv(pWin)->clip_shape, wClipShape(pWin));
    495 
    496             reg = XCreateRegion();
    497             pBox = RegionRects(xnestWindowPriv(pWin)->clip_shape);
    498             for (i = 0;
    499                  i < RegionNumRects(xnestWindowPriv(pWin)->clip_shape); i++) {
    500                 rect.x = pBox[i].x1;
    501                 rect.y = pBox[i].y1;
    502                 rect.width = pBox[i].x2 - pBox[i].x1;
    503                 rect.height = pBox[i].y2 - pBox[i].y1;
    504                 XUnionRectWithRegion(&rect, reg, reg);
    505             }
    506             XShapeCombineRegion(xnestDisplay, xnestWindow(pWin),
    507                                 ShapeClip, 0, 0, reg, ShapeSet);
    508             XDestroyRegion(reg);
    509         }
    510         else {
    511             RegionEmpty(xnestWindowPriv(pWin)->clip_shape);
    512 
    513             XShapeCombineMask(xnestDisplay, xnestWindow(pWin),
    514                               ShapeClip, 0, 0, None, ShapeSet);
    515         }
    516     }
    517 }