xserver

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

cursor.c (15533B)


      1 /***********************************************************
      2 
      3 Copyright 1987, 1998  The Open Group
      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.
     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 THE
     17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
     18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     20 
     21 Except as contained in this notice, the name of The Open Group shall not be
     22 used in advertising or otherwise to promote the sale, use or other dealings
     23 in this Software without prior written authorization from The Open Group.
     24 
     25 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
     26 
     27                         All Rights Reserved
     28 
     29 Permission to use, copy, modify, and distribute this software and its
     30 documentation for any purpose and without fee is hereby granted,
     31 provided that the above copyright notice appear in all copies and that
     32 both that copyright notice and this permission notice appear in
     33 supporting documentation, and that the name of Digital not be
     34 used in advertising or publicity pertaining to distribution of the
     35 software without specific, written prior permission.
     36 
     37 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
     38 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
     39 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
     40 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
     41 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
     42 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
     43 SOFTWARE.
     44 
     45 ******************************************************************/
     46 
     47 #ifdef HAVE_DIX_CONFIG_H
     48 #include <dix-config.h>
     49 #endif
     50 
     51 #include <X11/X.h>
     52 #include <X11/Xmd.h>
     53 #include "servermd.h"
     54 #include "scrnintstr.h"
     55 #include "dixstruct.h"
     56 #include "cursorstr.h"
     57 #include "dixfontstr.h"
     58 #include "opaque.h"
     59 #include "inputstr.h"
     60 #include "xace.h"
     61 
     62 typedef struct _GlyphShare {
     63     FontPtr font;
     64     unsigned short sourceChar;
     65     unsigned short maskChar;
     66     CursorBitsPtr bits;
     67     struct _GlyphShare *next;
     68 } GlyphShare, *GlyphSharePtr;
     69 
     70 static GlyphSharePtr sharedGlyphs = (GlyphSharePtr) NULL;
     71 
     72 DevScreenPrivateKeyRec cursorScreenDevPriv;
     73 
     74 static CARD32 cursorSerial;
     75 
     76 static void
     77 FreeCursorBits(CursorBitsPtr bits)
     78 {
     79     if (--bits->refcnt > 0)
     80         return;
     81     free(bits->source);
     82     free(bits->mask);
     83     free(bits->argb);
     84     dixFiniPrivates(bits, PRIVATE_CURSOR_BITS);
     85     if (bits->refcnt == 0) {
     86         GlyphSharePtr *prev, this;
     87 
     88         for (prev = &sharedGlyphs;
     89              (this = *prev) && (this->bits != bits); prev = &this->next);
     90         if (this) {
     91             *prev = this->next;
     92             CloseFont(this->font, (Font) 0);
     93             free(this);
     94         }
     95         free(bits);
     96     }
     97 }
     98 
     99 /**
    100  * To be called indirectly by DeleteResource; must use exactly two args.
    101  *
    102  *  \param value must conform to DeleteType
    103  */
    104 int
    105 FreeCursor(void *value, XID cid)
    106 {
    107     int nscr;
    108     CursorPtr pCurs = (CursorPtr) value;
    109 
    110     ScreenPtr pscr;
    111     DeviceIntPtr pDev = NULL;   /* unused anyway */
    112 
    113 
    114     UnrefCursor(pCurs);
    115     if (CursorRefCount(pCurs) != 0)
    116         return Success;
    117 
    118     BUG_WARN(CursorRefCount(pCurs) < 0);
    119 
    120     for (nscr = 0; nscr < screenInfo.numScreens; nscr++) {
    121         pscr = screenInfo.screens[nscr];
    122         (void) (*pscr->UnrealizeCursor) (pDev, pscr, pCurs);
    123     }
    124     FreeCursorBits(pCurs->bits);
    125     dixFiniPrivates(pCurs, PRIVATE_CURSOR);
    126     free(pCurs);
    127     return Success;
    128 }
    129 
    130 CursorPtr
    131 RefCursor(CursorPtr cursor)
    132 {
    133     if (cursor)
    134         cursor->refcnt++;
    135     return cursor;
    136 }
    137 
    138 CursorPtr
    139 UnrefCursor(CursorPtr cursor)
    140 {
    141     if (cursor)
    142         cursor->refcnt--;
    143     return cursor;
    144 }
    145 
    146 int
    147 CursorRefCount(const CursorPtr cursor)
    148 {
    149     return cursor ? cursor->refcnt : 0;
    150 }
    151 
    152 
    153 /*
    154  * We check for empty cursors so that we won't have to display them
    155  */
    156 static void
    157 CheckForEmptyMask(CursorBitsPtr bits)
    158 {
    159     unsigned char *msk = bits->mask;
    160     int n = BitmapBytePad(bits->width) * bits->height;
    161 
    162     bits->emptyMask = FALSE;
    163     while (n--)
    164         if (*(msk++) != 0)
    165             return;
    166     if (bits->argb) {
    167         CARD32 *argb = bits->argb;
    168 
    169         n = bits->width * bits->height;
    170         while (n--)
    171             if (*argb++ & 0xff000000)
    172                 return;
    173     }
    174     bits->emptyMask = TRUE;
    175 }
    176 
    177 /**
    178  * realize the cursor for every screen. Do not change the refcnt, this will be
    179  * changed when ChangeToCursor actually changes the sprite.
    180  *
    181  * @return Success if all cursors realize on all screens, BadAlloc if realize
    182  * failed for a device on a given screen.
    183  */
    184 static int
    185 RealizeCursorAllScreens(CursorPtr pCurs)
    186 {
    187     DeviceIntPtr pDev;
    188     ScreenPtr pscr;
    189     int nscr;
    190 
    191     for (nscr = 0; nscr < screenInfo.numScreens; nscr++) {
    192         pscr = screenInfo.screens[nscr];
    193         for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
    194             if (DevHasCursor(pDev)) {
    195                 if (!(*pscr->RealizeCursor) (pDev, pscr, pCurs)) {
    196                     /* Realize failed for device pDev on screen pscr.
    197                      * We have to assume that for all devices before, realize
    198                      * worked. We need to rollback all devices so far on the
    199                      * current screen and then all devices on previous
    200                      * screens.
    201                      */
    202                     DeviceIntPtr pDevIt = inputInfo.devices;    /*dev iterator */
    203 
    204                     while (pDevIt && pDevIt != pDev) {
    205                         if (DevHasCursor(pDevIt))
    206                             (*pscr->UnrealizeCursor) (pDevIt, pscr, pCurs);
    207                         pDevIt = pDevIt->next;
    208                     }
    209                     while (--nscr >= 0) {
    210                         pscr = screenInfo.screens[nscr];
    211                         /* now unrealize all devices on previous screens */
    212                         pDevIt = inputInfo.devices;
    213                         while (pDevIt) {
    214                             if (DevHasCursor(pDevIt))
    215                                 (*pscr->UnrealizeCursor) (pDevIt, pscr, pCurs);
    216                             pDevIt = pDevIt->next;
    217                         }
    218                         (*pscr->UnrealizeCursor) (pDev, pscr, pCurs);
    219                     }
    220                     return BadAlloc;
    221                 }
    222             }
    223         }
    224     }
    225 
    226     return Success;
    227 }
    228 
    229 /**
    230  * does nothing about the resource table, just creates the data structure.
    231  * does not copy the src and mask bits
    232  *
    233  *  \param psrcbits  server-defined padding
    234  *  \param pmaskbits server-defined padding
    235  *  \param argb      no padding
    236  */
    237 int
    238 AllocARGBCursor(unsigned char *psrcbits, unsigned char *pmaskbits,
    239                 CARD32 *argb, CursorMetricPtr cm,
    240                 unsigned foreRed, unsigned foreGreen, unsigned foreBlue,
    241                 unsigned backRed, unsigned backGreen, unsigned backBlue,
    242                 CursorPtr *ppCurs, ClientPtr client, XID cid)
    243 {
    244     CursorBitsPtr bits;
    245     CursorPtr pCurs;
    246     int rc;
    247 
    248     *ppCurs = NULL;
    249     pCurs = (CursorPtr) calloc(CURSOR_REC_SIZE + CURSOR_BITS_SIZE, 1);
    250     if (!pCurs)
    251         return BadAlloc;
    252 
    253     bits = (CursorBitsPtr) ((char *) pCurs + CURSOR_REC_SIZE);
    254     dixInitPrivates(pCurs, pCurs + 1, PRIVATE_CURSOR);
    255     dixInitPrivates(bits, bits + 1, PRIVATE_CURSOR_BITS)
    256         bits->source = psrcbits;
    257     bits->mask = pmaskbits;
    258     bits->argb = argb;
    259     bits->width = cm->width;
    260     bits->height = cm->height;
    261     bits->xhot = cm->xhot;
    262     bits->yhot = cm->yhot;
    263     pCurs->refcnt = 1;
    264     bits->refcnt = -1;
    265     CheckForEmptyMask(bits);
    266     pCurs->bits = bits;
    267     pCurs->serialNumber = ++cursorSerial;
    268     pCurs->name = None;
    269 
    270     pCurs->foreRed = foreRed;
    271     pCurs->foreGreen = foreGreen;
    272     pCurs->foreBlue = foreBlue;
    273 
    274     pCurs->backRed = backRed;
    275     pCurs->backGreen = backGreen;
    276     pCurs->backBlue = backBlue;
    277 
    278     pCurs->id = cid;
    279 
    280     /* security creation/labeling check */
    281     rc = XaceHook(XACE_RESOURCE_ACCESS, client, cid, RT_CURSOR,
    282                   pCurs, RT_NONE, NULL, DixCreateAccess);
    283     if (rc != Success)
    284         goto error;
    285 
    286     rc = RealizeCursorAllScreens(pCurs);
    287     if (rc != Success)
    288         goto error;
    289 
    290     *ppCurs = pCurs;
    291 
    292     if (argb) {
    293         size_t i, size = bits->width * bits->height;
    294 
    295         for (i = 0; i < size; i++) {
    296             if ((argb[i] & 0xff000000) == 0 && (argb[i] & 0xffffff) != 0) {
    297                 /* ARGB data doesn't seem pre-multiplied, fix it */
    298                 for (i = 0; i < size; i++) {
    299                     CARD32 a, ar, ag, ab;
    300 
    301                     a = argb[i] >> 24;
    302                     ar = a * ((argb[i] >> 16) & 0xff) / 0xff;
    303                     ag = a * ((argb[i] >> 8) & 0xff) / 0xff;
    304                     ab = a * (argb[i] & 0xff) / 0xff;
    305 
    306                     argb[i] = a << 24 | ar << 16 | ag << 8 | ab;
    307                 }
    308 
    309                 break;
    310             }
    311         }
    312     }
    313 
    314     return Success;
    315 
    316  error:
    317     FreeCursorBits(bits);
    318     dixFiniPrivates(pCurs, PRIVATE_CURSOR);
    319     free(pCurs);
    320 
    321     return rc;
    322 }
    323 
    324 int
    325 AllocGlyphCursor(Font source, unsigned sourceChar, Font mask, unsigned maskChar,
    326                  unsigned foreRed, unsigned foreGreen, unsigned foreBlue,
    327                  unsigned backRed, unsigned backGreen, unsigned backBlue,
    328                  CursorPtr *ppCurs, ClientPtr client, XID cid)
    329 {
    330     FontPtr sourcefont, maskfont;
    331     unsigned char *srcbits;
    332     unsigned char *mskbits;
    333     CursorMetricRec cm;
    334     int rc;
    335     CursorBitsPtr bits;
    336     CursorPtr pCurs;
    337     GlyphSharePtr pShare;
    338 
    339     rc = dixLookupResourceByType((void **) &sourcefont, source, RT_FONT,
    340                                  client, DixUseAccess);
    341     if (rc != Success) {
    342         client->errorValue = source;
    343         return rc;
    344     }
    345     rc = dixLookupResourceByType((void **) &maskfont, mask, RT_FONT, client,
    346                                  DixUseAccess);
    347     if (rc != Success && mask != None) {
    348         client->errorValue = mask;
    349         return rc;
    350     }
    351     if (sourcefont != maskfont)
    352         pShare = (GlyphSharePtr) NULL;
    353     else {
    354         for (pShare = sharedGlyphs;
    355              pShare &&
    356              ((pShare->font != sourcefont) ||
    357               (pShare->sourceChar != sourceChar) ||
    358               (pShare->maskChar != maskChar)); pShare = pShare->next);
    359     }
    360     if (pShare) {
    361         pCurs = (CursorPtr) calloc(CURSOR_REC_SIZE, 1);
    362         if (!pCurs)
    363             return BadAlloc;
    364         dixInitPrivates(pCurs, pCurs + 1, PRIVATE_CURSOR);
    365         bits = pShare->bits;
    366         bits->refcnt++;
    367     }
    368     else {
    369         if (!CursorMetricsFromGlyph(sourcefont, sourceChar, &cm)) {
    370             client->errorValue = sourceChar;
    371             return BadValue;
    372         }
    373         if (!maskfont) {
    374             long n;
    375             unsigned char *mskptr;
    376 
    377             n = BitmapBytePad(cm.width) * (long) cm.height;
    378             mskptr = mskbits = malloc(n);
    379             if (!mskptr)
    380                 return BadAlloc;
    381             while (--n >= 0)
    382                 *mskptr++ = ~0;
    383         }
    384         else {
    385             if (!CursorMetricsFromGlyph(maskfont, maskChar, &cm)) {
    386                 client->errorValue = maskChar;
    387                 return BadValue;
    388             }
    389             if ((rc = ServerBitsFromGlyph(maskfont, maskChar, &cm, &mskbits)))
    390                 return rc;
    391         }
    392         if ((rc = ServerBitsFromGlyph(sourcefont, sourceChar, &cm, &srcbits))) {
    393             free(mskbits);
    394             return rc;
    395         }
    396         if (sourcefont != maskfont) {
    397             pCurs = (CursorPtr) calloc(CURSOR_REC_SIZE + CURSOR_BITS_SIZE, 1);
    398             if (pCurs)
    399                 bits = (CursorBitsPtr) ((char *) pCurs + CURSOR_REC_SIZE);
    400             else
    401                 bits = (CursorBitsPtr) NULL;
    402         }
    403         else {
    404             pCurs = (CursorPtr) calloc(CURSOR_REC_SIZE, 1);
    405             if (pCurs)
    406                 bits = (CursorBitsPtr) calloc(CURSOR_BITS_SIZE, 1);
    407             else
    408                 bits = (CursorBitsPtr) NULL;
    409         }
    410         if (!bits) {
    411             free(pCurs);
    412             free(mskbits);
    413             free(srcbits);
    414             return BadAlloc;
    415         }
    416         dixInitPrivates(pCurs, pCurs + 1, PRIVATE_CURSOR);
    417         dixInitPrivates(bits, bits + 1, PRIVATE_CURSOR_BITS);
    418         bits->source = srcbits;
    419         bits->mask = mskbits;
    420         bits->argb = 0;
    421         bits->width = cm.width;
    422         bits->height = cm.height;
    423         bits->xhot = cm.xhot;
    424         bits->yhot = cm.yhot;
    425         if (sourcefont != maskfont)
    426             bits->refcnt = -1;
    427         else {
    428             bits->refcnt = 1;
    429             pShare = malloc(sizeof(GlyphShare));
    430             if (!pShare) {
    431                 FreeCursorBits(bits);
    432                 return BadAlloc;
    433             }
    434             pShare->font = sourcefont;
    435             sourcefont->refcnt++;
    436             pShare->sourceChar = sourceChar;
    437             pShare->maskChar = maskChar;
    438             pShare->bits = bits;
    439             pShare->next = sharedGlyphs;
    440             sharedGlyphs = pShare;
    441         }
    442     }
    443 
    444     CheckForEmptyMask(bits);
    445     pCurs->bits = bits;
    446     pCurs->refcnt = 1;
    447     pCurs->serialNumber = ++cursorSerial;
    448     pCurs->name = None;
    449 
    450     pCurs->foreRed = foreRed;
    451     pCurs->foreGreen = foreGreen;
    452     pCurs->foreBlue = foreBlue;
    453 
    454     pCurs->backRed = backRed;
    455     pCurs->backGreen = backGreen;
    456     pCurs->backBlue = backBlue;
    457 
    458     pCurs->id = cid;
    459 
    460     /* security creation/labeling check */
    461     rc = XaceHook(XACE_RESOURCE_ACCESS, client, cid, RT_CURSOR,
    462                   pCurs, RT_NONE, NULL, DixCreateAccess);
    463     if (rc != Success)
    464         goto error;
    465 
    466     rc = RealizeCursorAllScreens(pCurs);
    467     if (rc != Success)
    468         goto error;
    469 
    470     *ppCurs = pCurs;
    471     return Success;
    472 
    473  error:
    474     FreeCursorBits(bits);
    475     dixFiniPrivates(pCurs, PRIVATE_CURSOR);
    476     free(pCurs);
    477 
    478     return rc;
    479 }
    480 
    481 /** CreateRootCursor
    482  *
    483  * look up the name of a font
    484  * open the font
    485  * add the font to the resource table
    486  * make a cursor from the glyphs
    487  * add the cursor to the resource table
    488  *************************************************************/
    489 
    490 CursorPtr
    491 CreateRootCursor(char *unused1, unsigned int unused2)
    492 {
    493     CursorPtr curs;
    494     FontPtr cursorfont;
    495     int err;
    496     XID fontID;
    497     const char defaultCursorFont[] = "cursor";
    498 
    499     fontID = FakeClientID(0);
    500     err = OpenFont(serverClient, fontID, FontLoadAll | FontOpenSync,
    501                    (unsigned) strlen(defaultCursorFont), defaultCursorFont);
    502     if (err != Success)
    503         return NullCursor;
    504 
    505     err = dixLookupResourceByType((void **) &cursorfont, fontID, RT_FONT,
    506                                   serverClient, DixReadAccess);
    507     if (err != Success)
    508         return NullCursor;
    509     if (AllocGlyphCursor(fontID, 0, fontID, 1, 0, 0, 0, ~0, ~0, ~0,
    510                          &curs, serverClient, (XID) 0) != Success)
    511         return NullCursor;
    512 
    513     if (!AddResource(FakeClientID(0), RT_CURSOR, (void *) curs))
    514         return NullCursor;
    515 
    516     return curs;
    517 }