xserver

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

midispcur.c (15832B)


      1 /*
      2  * midispcur.c
      3  *
      4  * machine independent cursor display routines
      5  */
      6 
      7 /*
      8 
      9 Copyright 1989, 1998  The Open Group
     10 
     11 Permission to use, copy, modify, distribute, and sell this software and its
     12 documentation for any purpose is hereby granted without fee, provided that
     13 the above copyright notice appear in all copies and that both that
     14 copyright notice and this permission notice appear in supporting
     15 documentation.
     16 
     17 The above copyright notice and this permission notice shall be included in
     18 all copies or substantial portions of the Software.
     19 
     20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     21 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     22 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
     23 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
     24 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     25 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     26 
     27 Except as contained in this notice, the name of The Open Group shall not be
     28 used in advertising or otherwise to promote the sale, use or other dealings
     29 in this Software without prior written authorization from The Open Group.
     30 */
     31 
     32 #ifdef HAVE_DIX_CONFIG_H
     33 #include <dix-config.h>
     34 #endif
     35 
     36 #include   <X11/X.h>
     37 #include   "misc.h"
     38 #include   "input.h"
     39 #include   "cursorstr.h"
     40 #include   "windowstr.h"
     41 #include   "regionstr.h"
     42 #include   "dixstruct.h"
     43 #include   "scrnintstr.h"
     44 #include   "servermd.h"
     45 #include   "mipointer.h"
     46 #include   "misprite.h"
     47 #include   "gcstruct.h"
     48 
     49 #include   "picturestr.h"
     50 
     51 #include "inputstr.h"
     52 
     53 /* per-screen private data */
     54 static DevPrivateKeyRec miDCScreenKeyRec;
     55 
     56 #define miDCScreenKey (&miDCScreenKeyRec)
     57 
     58 static DevScreenPrivateKeyRec miDCDeviceKeyRec;
     59 
     60 #define miDCDeviceKey (&miDCDeviceKeyRec)
     61 
     62 static Bool miDCCloseScreen(ScreenPtr pScreen);
     63 
     64 /* per device private data */
     65 typedef struct {
     66     GCPtr pSourceGC, pMaskGC;
     67     GCPtr pSaveGC, pRestoreGC;
     68     PixmapPtr pSave;
     69     PicturePtr pRootPicture;
     70 } miDCBufferRec, *miDCBufferPtr;
     71 
     72 #define miGetDCDevice(dev, screen) \
     73  ((DevHasCursor(dev)) ? \
     74   (miDCBufferPtr)dixLookupScreenPrivate(&dev->devPrivates, miDCDeviceKey, screen) : \
     75   (miDCBufferPtr)dixLookupScreenPrivate(&GetMaster(dev, MASTER_POINTER)->devPrivates, miDCDeviceKey, screen))
     76 
     77 /*
     78  * The core pointer buffer will point to the index of the virtual pointer
     79  * in the pCursorBuffers array.
     80  */
     81 typedef struct {
     82     CloseScreenProcPtr CloseScreen;
     83     PixmapPtr sourceBits;       /* source bits */
     84     PixmapPtr maskBits;         /* mask bits */
     85     PicturePtr pPicture;
     86     CursorPtr pCursor;
     87 } miDCScreenRec, *miDCScreenPtr;
     88 
     89 #define miGetDCScreen(s)	((miDCScreenPtr)(dixLookupPrivate(&(s)->devPrivates, miDCScreenKey)))
     90 
     91 Bool
     92 miDCInitialize(ScreenPtr pScreen, miPointerScreenFuncPtr screenFuncs)
     93 {
     94     miDCScreenPtr pScreenPriv;
     95 
     96     if (!dixRegisterPrivateKey(&miDCScreenKeyRec, PRIVATE_SCREEN, 0) ||
     97         !dixRegisterScreenPrivateKey(&miDCDeviceKeyRec, pScreen, PRIVATE_DEVICE,
     98                                      0))
     99         return FALSE;
    100 
    101     pScreenPriv = calloc(1, sizeof(miDCScreenRec));
    102     if (!pScreenPriv)
    103         return FALSE;
    104 
    105     pScreenPriv->CloseScreen = pScreen->CloseScreen;
    106     pScreen->CloseScreen = miDCCloseScreen;
    107 
    108     dixSetPrivate(&pScreen->devPrivates, miDCScreenKey, pScreenPriv);
    109 
    110     if (!miSpriteInitialize(pScreen, screenFuncs)) {
    111         free((void *) pScreenPriv);
    112         return FALSE;
    113     }
    114     return TRUE;
    115 }
    116 
    117 static void
    118 miDCSwitchScreenCursor(ScreenPtr pScreen, CursorPtr pCursor, PixmapPtr sourceBits, PixmapPtr maskBits, PicturePtr pPicture)
    119 {
    120     miDCScreenPtr pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miDCScreenKey);
    121 
    122     if (pScreenPriv->sourceBits)
    123         (*pScreen->DestroyPixmap)(pScreenPriv->sourceBits);
    124     pScreenPriv->sourceBits = sourceBits;
    125 
    126     if (pScreenPriv->maskBits)
    127         (*pScreen->DestroyPixmap)(pScreenPriv->maskBits);
    128     pScreenPriv->maskBits = maskBits;
    129 
    130     if (pScreenPriv->pPicture)
    131         FreePicture(pScreenPriv->pPicture, 0);
    132     pScreenPriv->pPicture = pPicture;
    133 
    134     pScreenPriv->pCursor = pCursor;
    135 }
    136 
    137 static Bool
    138 miDCCloseScreen(ScreenPtr pScreen)
    139 {
    140     miDCScreenPtr pScreenPriv;
    141 
    142     pScreenPriv = (miDCScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
    143                                                    miDCScreenKey);
    144     pScreen->CloseScreen = pScreenPriv->CloseScreen;
    145 
    146     miDCSwitchScreenCursor(pScreen, NULL, NULL, NULL, NULL);
    147     free((void *) pScreenPriv);
    148     return (*pScreen->CloseScreen) (pScreen);
    149 }
    150 
    151 Bool
    152 miDCRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor)
    153 {
    154     return TRUE;
    155 }
    156 
    157 #define EnsurePicture(picture,draw,win) (picture || miDCMakePicture(&picture,draw,win))
    158 
    159 static PicturePtr
    160 miDCMakePicture(PicturePtr * ppPicture, DrawablePtr pDraw, WindowPtr pWin)
    161 {
    162     PictFormatPtr pFormat;
    163     XID subwindow_mode = IncludeInferiors;
    164     PicturePtr pPicture;
    165     int error;
    166 
    167     pFormat = PictureWindowFormat(pWin);
    168     if (!pFormat)
    169         return 0;
    170     pPicture = CreatePicture(0, pDraw, pFormat,
    171                              CPSubwindowMode, &subwindow_mode,
    172                              serverClient, &error);
    173     *ppPicture = pPicture;
    174     return pPicture;
    175 }
    176 
    177 static Bool
    178 miDCRealize(ScreenPtr pScreen, CursorPtr pCursor)
    179 {
    180     miDCScreenPtr pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miDCScreenKey);
    181     GCPtr pGC;
    182     ChangeGCVal gcvals;
    183     PixmapPtr   sourceBits, maskBits;
    184 
    185     if (pScreenPriv->pCursor == pCursor)
    186         return TRUE;
    187 
    188     if (pCursor->bits->argb) {
    189         PixmapPtr pPixmap;
    190         PictFormatPtr pFormat;
    191         int error;
    192         PicturePtr  pPicture;
    193 
    194         pFormat = PictureMatchFormat(pScreen, 32, PICT_a8r8g8b8);
    195         if (!pFormat)
    196             return FALSE;
    197 
    198         pPixmap = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width,
    199                                             pCursor->bits->height, 32,
    200                                             CREATE_PIXMAP_USAGE_SCRATCH);
    201         if (!pPixmap)
    202             return FALSE;
    203 
    204         pGC = GetScratchGC(32, pScreen);
    205         if (!pGC) {
    206             (*pScreen->DestroyPixmap) (pPixmap);
    207             return FALSE;
    208         }
    209         ValidateGC(&pPixmap->drawable, pGC);
    210         (*pGC->ops->PutImage) (&pPixmap->drawable, pGC, 32,
    211                                0, 0, pCursor->bits->width,
    212                                pCursor->bits->height,
    213                                0, ZPixmap, (char *) pCursor->bits->argb);
    214         FreeScratchGC(pGC);
    215         pPicture = CreatePicture(0, &pPixmap->drawable,
    216                                  pFormat, 0, 0, serverClient, &error);
    217         (*pScreen->DestroyPixmap) (pPixmap);
    218         if (!pPicture)
    219             return FALSE;
    220 
    221         miDCSwitchScreenCursor(pScreen, pCursor, NULL, NULL, pPicture);
    222         return TRUE;
    223     }
    224 
    225     sourceBits = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width,
    226                                            pCursor->bits->height, 1, 0);
    227     if (!sourceBits)
    228         return FALSE;
    229 
    230     maskBits = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width,
    231                                          pCursor->bits->height, 1, 0);
    232     if (!maskBits) {
    233         (*pScreen->DestroyPixmap) (sourceBits);
    234         return FALSE;
    235     }
    236 
    237     /* create the two sets of bits, clipping as appropriate */
    238 
    239     pGC = GetScratchGC(1, pScreen);
    240     if (!pGC) {
    241         (*pScreen->DestroyPixmap) (sourceBits);
    242         (*pScreen->DestroyPixmap) (maskBits);
    243         return FALSE;
    244     }
    245 
    246     ValidateGC((DrawablePtr) sourceBits, pGC);
    247     (*pGC->ops->PutImage) ((DrawablePtr) sourceBits, pGC, 1,
    248                            0, 0, pCursor->bits->width, pCursor->bits->height,
    249                            0, XYPixmap, (char *) pCursor->bits->source);
    250     gcvals.val = GXand;
    251     ChangeGC(NullClient, pGC, GCFunction, &gcvals);
    252     ValidateGC((DrawablePtr) sourceBits, pGC);
    253     (*pGC->ops->PutImage) ((DrawablePtr) sourceBits, pGC, 1,
    254                            0, 0, pCursor->bits->width, pCursor->bits->height,
    255                            0, XYPixmap, (char *) pCursor->bits->mask);
    256 
    257     /* mask bits -- pCursor->mask & ~pCursor->source */
    258     gcvals.val = GXcopy;
    259     ChangeGC(NullClient, pGC, GCFunction, &gcvals);
    260     ValidateGC((DrawablePtr) maskBits, pGC);
    261     (*pGC->ops->PutImage) ((DrawablePtr) maskBits, pGC, 1,
    262                            0, 0, pCursor->bits->width, pCursor->bits->height,
    263                            0, XYPixmap, (char *) pCursor->bits->mask);
    264     gcvals.val = GXandInverted;
    265     ChangeGC(NullClient, pGC, GCFunction, &gcvals);
    266     ValidateGC((DrawablePtr) maskBits, pGC);
    267     (*pGC->ops->PutImage) ((DrawablePtr) maskBits, pGC, 1,
    268                            0, 0, pCursor->bits->width, pCursor->bits->height,
    269                            0, XYPixmap, (char *) pCursor->bits->source);
    270     FreeScratchGC(pGC);
    271 
    272     miDCSwitchScreenCursor(pScreen, pCursor, sourceBits, maskBits, NULL);
    273     return TRUE;
    274 }
    275 
    276 Bool
    277 miDCUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor)
    278 {
    279     miDCScreenPtr pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miDCScreenKey);
    280 
    281     if (pCursor == pScreenPriv->pCursor)
    282         miDCSwitchScreenCursor(pScreen, NULL, NULL, NULL, NULL);
    283     return TRUE;
    284 }
    285 
    286 static void
    287 miDCPutBits(DrawablePtr pDrawable,
    288             GCPtr sourceGC,
    289             GCPtr maskGC,
    290             int x_org,
    291             int y_org,
    292             unsigned w, unsigned h, unsigned long source, unsigned long mask)
    293 {
    294     miDCScreenPtr pScreenPriv = dixLookupPrivate(&pDrawable->pScreen->devPrivates, miDCScreenKey);
    295     ChangeGCVal gcval;
    296     int x, y;
    297 
    298     if (sourceGC->fgPixel != source) {
    299         gcval.val = source;
    300         ChangeGC(NullClient, sourceGC, GCForeground, &gcval);
    301     }
    302     if (sourceGC->serialNumber != pDrawable->serialNumber)
    303         ValidateGC(pDrawable, sourceGC);
    304 
    305     if (sourceGC->miTranslate) {
    306         x = pDrawable->x + x_org;
    307         y = pDrawable->y + y_org;
    308     }
    309     else {
    310         x = x_org;
    311         y = y_org;
    312     }
    313 
    314     (*sourceGC->ops->PushPixels) (sourceGC, pScreenPriv->sourceBits, pDrawable, w, h,
    315                                   x, y);
    316     if (maskGC->fgPixel != mask) {
    317         gcval.val = mask;
    318         ChangeGC(NullClient, maskGC, GCForeground, &gcval);
    319     }
    320     if (maskGC->serialNumber != pDrawable->serialNumber)
    321         ValidateGC(pDrawable, maskGC);
    322 
    323     if (maskGC->miTranslate) {
    324         x = pDrawable->x + x_org;
    325         y = pDrawable->y + y_org;
    326     }
    327     else {
    328         x = x_org;
    329         y = y_org;
    330     }
    331 
    332     (*maskGC->ops->PushPixels) (maskGC, pScreenPriv->maskBits, pDrawable, w, h, x, y);
    333 }
    334 
    335 static GCPtr
    336 miDCMakeGC(WindowPtr pWin)
    337 {
    338     GCPtr pGC;
    339     int status;
    340     XID gcvals[2];
    341 
    342     gcvals[0] = IncludeInferiors;
    343     gcvals[1] = FALSE;
    344     pGC = CreateGC((DrawablePtr) pWin,
    345                    GCSubwindowMode | GCGraphicsExposures, gcvals, &status,
    346                    (XID) 0, serverClient);
    347     return pGC;
    348 }
    349 
    350 Bool
    351 miDCPutUpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor,
    352                 int x, int y, unsigned long source, unsigned long mask)
    353 {
    354     miDCScreenPtr pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miDCScreenKey);
    355     miDCBufferPtr pBuffer;
    356     WindowPtr pWin;
    357 
    358     if (!miDCRealize(pScreen, pCursor))
    359         return FALSE;
    360 
    361     pWin = pScreen->root;
    362     pBuffer = miGetDCDevice(pDev, pScreen);
    363 
    364     if (pScreenPriv->pPicture) {
    365         if (!EnsurePicture(pBuffer->pRootPicture, &pWin->drawable, pWin))
    366             return FALSE;
    367         CompositePicture(PictOpOver,
    368                          pScreenPriv->pPicture,
    369                          NULL,
    370                          pBuffer->pRootPicture,
    371                          0, 0, 0, 0,
    372                          x, y, pCursor->bits->width, pCursor->bits->height);
    373     }
    374     else
    375     {
    376         miDCPutBits((DrawablePtr) pWin,
    377                     pBuffer->pSourceGC, pBuffer->pMaskGC,
    378                     x, y, pCursor->bits->width, pCursor->bits->height,
    379                     source, mask);
    380     }
    381     return TRUE;
    382 }
    383 
    384 Bool
    385 miDCSaveUnderCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
    386                     int x, int y, int w, int h)
    387 {
    388     miDCBufferPtr pBuffer;
    389     PixmapPtr pSave;
    390     WindowPtr pWin;
    391     GCPtr pGC;
    392 
    393     pBuffer = miGetDCDevice(pDev, pScreen);
    394 
    395     pSave = pBuffer->pSave;
    396     pWin = pScreen->root;
    397     if (!pSave || pSave->drawable.width < w || pSave->drawable.height < h) {
    398         if (pSave)
    399             (*pScreen->DestroyPixmap) (pSave);
    400         pBuffer->pSave = pSave =
    401             (*pScreen->CreatePixmap) (pScreen, w, h, pScreen->rootDepth, 0);
    402         if (!pSave)
    403             return FALSE;
    404     }
    405 
    406     pGC = pBuffer->pSaveGC;
    407     if (pSave->drawable.serialNumber != pGC->serialNumber)
    408         ValidateGC((DrawablePtr) pSave, pGC);
    409     (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC,
    410                            x, y, w, h, 0, 0);
    411     return TRUE;
    412 }
    413 
    414 Bool
    415 miDCRestoreUnderCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
    416                        int x, int y, int w, int h)
    417 {
    418     miDCBufferPtr pBuffer;
    419     PixmapPtr pSave;
    420     WindowPtr pWin;
    421     GCPtr pGC;
    422 
    423     pBuffer = miGetDCDevice(pDev, pScreen);
    424     pSave = pBuffer->pSave;
    425 
    426     pWin = pScreen->root;
    427     if (!pSave)
    428         return FALSE;
    429 
    430     pGC = pBuffer->pRestoreGC;
    431     if (pWin->drawable.serialNumber != pGC->serialNumber)
    432         ValidateGC((DrawablePtr) pWin, pGC);
    433     (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC,
    434                            0, 0, w, h, x, y);
    435     return TRUE;
    436 }
    437 
    438 Bool
    439 miDCDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen)
    440 {
    441     miDCBufferPtr pBuffer;
    442     WindowPtr pWin;
    443     int i;
    444 
    445     if (!DevHasCursor(pDev))
    446         return TRUE;
    447 
    448     for (i = 0; i < screenInfo.numScreens; i++) {
    449         pScreen = screenInfo.screens[i];
    450 
    451         pBuffer = calloc(1, sizeof(miDCBufferRec));
    452         if (!pBuffer)
    453             goto failure;
    454 
    455         dixSetScreenPrivate(&pDev->devPrivates, miDCDeviceKey, pScreen,
    456                             pBuffer);
    457         pWin = pScreen->root;
    458 
    459         pBuffer->pSourceGC = miDCMakeGC(pWin);
    460         if (!pBuffer->pSourceGC)
    461             goto failure;
    462 
    463         pBuffer->pMaskGC = miDCMakeGC(pWin);
    464         if (!pBuffer->pMaskGC)
    465             goto failure;
    466 
    467         pBuffer->pSaveGC = miDCMakeGC(pWin);
    468         if (!pBuffer->pSaveGC)
    469             goto failure;
    470 
    471         pBuffer->pRestoreGC = miDCMakeGC(pWin);
    472         if (!pBuffer->pRestoreGC)
    473             goto failure;
    474 
    475         pBuffer->pRootPicture = NULL;
    476 
    477         /* (re)allocated lazily depending on the cursor size */
    478         pBuffer->pSave = NULL;
    479     }
    480 
    481     return TRUE;
    482 
    483  failure:
    484 
    485     miDCDeviceCleanup(pDev, pScreen);
    486 
    487     return FALSE;
    488 }
    489 
    490 void
    491 miDCDeviceCleanup(DeviceIntPtr pDev, ScreenPtr pScreen)
    492 {
    493     miDCBufferPtr pBuffer;
    494     int i;
    495 
    496     if (DevHasCursor(pDev)) {
    497         for (i = 0; i < screenInfo.numScreens; i++) {
    498             pScreen = screenInfo.screens[i];
    499 
    500             pBuffer = miGetDCDevice(pDev, pScreen);
    501 
    502             if (pBuffer) {
    503                 if (pBuffer->pSourceGC)
    504                     FreeGC(pBuffer->pSourceGC, (GContext) 0);
    505                 if (pBuffer->pMaskGC)
    506                     FreeGC(pBuffer->pMaskGC, (GContext) 0);
    507                 if (pBuffer->pSaveGC)
    508                     FreeGC(pBuffer->pSaveGC, (GContext) 0);
    509                 if (pBuffer->pRestoreGC)
    510                     FreeGC(pBuffer->pRestoreGC, (GContext) 0);
    511 
    512                 /* If a pRootPicture was allocated for a root window, it
    513                  * is freed when that root window is destroyed, so don't
    514                  * free it again here. */
    515 
    516                 if (pBuffer->pSave)
    517                     (*pScreen->DestroyPixmap) (pBuffer->pSave);
    518 
    519                 free(pBuffer);
    520                 dixSetScreenPrivate(&pDev->devPrivates, miDCDeviceKey, pScreen,
    521                                     NULL);
    522             }
    523         }
    524     }
    525 }