xserver

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

dixutils.c (25454B)


      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 /*
     48 
     49 (c)Copyright 1988,1991 Adobe Systems Incorporated. All rights reserved.
     50 
     51 Permission to use, copy, modify, distribute, and sublicense this software and its
     52 documentation for any purpose and without fee is hereby granted, provided that
     53 the above copyright notices appear in all copies and that both those copyright
     54 notices and this permission notice appear in supporting documentation and that
     55 the name of Adobe Systems Incorporated not be used in advertising or publicity
     56 pertaining to distribution of the software without specific, written prior
     57 permission.  No trademark license to use the Adobe trademarks is hereby
     58 granted.  If the Adobe trademark "Display PostScript"(tm) is used to describe
     59 this software, its functionality or for any other purpose, such use shall be
     60 limited to a statement that this software works in conjunction with the Display
     61 PostScript system.  Proper trademark attribution to reflect Adobe's ownership
     62 of the trademark shall be given whenever any such reference to the Display
     63 PostScript system is made.
     64 
     65 ADOBE MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THE SOFTWARE FOR ANY
     66 PURPOSE.  IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.  ADOBE
     67 DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
     68 WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-
     69 INFRINGEMENT OF THIRD PARTY RIGHTS.  IN NO EVENT SHALL ADOBE BE LIABLE TO YOU
     70 OR ANY OTHER PARTY FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
     71 DAMAGES WHATSOEVER WHETHER IN AN ACTION OF CONTRACT,NEGLIGENCE, STRICT
     72 LIABILITY OR ANY OTHER ACTION ARISING OUT OF OR IN CONNECTION WITH THE USE OR
     73 PERFORMANCE OF THIS SOFTWARE.  ADOBE WILL NOT PROVIDE ANY TRAINING OR OTHER
     74 SUPPORT FOR THE SOFTWARE.
     75 
     76 Adobe, PostScript, and Display PostScript are trademarks of Adobe Systems
     77 Incorporated which may be registered in certain jurisdictions.
     78 
     79 Author:  Adobe Systems Incorporated
     80 
     81 */
     82 
     83 #ifdef HAVE_DIX_CONFIG_H
     84 #include <dix-config.h>
     85 #endif
     86 
     87 #include <X11/X.h>
     88 #include <X11/Xmd.h>
     89 #include "misc.h"
     90 #include "windowstr.h"
     91 #include "dixstruct.h"
     92 #include "pixmapstr.h"
     93 #include "gcstruct.h"
     94 #include "scrnintstr.h"
     95 #define  XK_LATIN1
     96 #include <X11/keysymdef.h>
     97 #include "xace.h"
     98 
     99 /*
    100  * CompareTimeStamps returns -1, 0, or +1 depending on if the first
    101  * argument is less than, equal to or greater than the second argument.
    102  */
    103 
    104 int
    105 CompareTimeStamps(TimeStamp a, TimeStamp b)
    106 {
    107     if (a.months < b.months)
    108         return EARLIER;
    109     if (a.months > b.months)
    110         return LATER;
    111     if (a.milliseconds < b.milliseconds)
    112         return EARLIER;
    113     if (a.milliseconds > b.milliseconds)
    114         return LATER;
    115     return SAMETIME;
    116 }
    117 
    118 /*
    119  * convert client times to server TimeStamps
    120  */
    121 
    122 #define HALFMONTH ((unsigned long) 1<<31)
    123 TimeStamp
    124 ClientTimeToServerTime(CARD32 c)
    125 {
    126     TimeStamp ts;
    127 
    128     if (c == CurrentTime)
    129         return currentTime;
    130     ts.months = currentTime.months;
    131     ts.milliseconds = c;
    132     if (c > currentTime.milliseconds) {
    133         if (((unsigned long) c - currentTime.milliseconds) > HALFMONTH)
    134             ts.months -= 1;
    135     }
    136     else if (c < currentTime.milliseconds) {
    137         if (((unsigned long) currentTime.milliseconds - c) > HALFMONTH)
    138             ts.months += 1;
    139     }
    140     return ts;
    141 }
    142 
    143 /*
    144  * ISO Latin-1 case conversion routine
    145  *
    146  * this routine always null-terminates the result, so
    147  * beware of too-small buffers
    148  */
    149 
    150 static unsigned char
    151 ISOLatin1ToLower(unsigned char source)
    152 {
    153     unsigned char dest;
    154 
    155     if ((source >= XK_A) && (source <= XK_Z))
    156         dest = source + (XK_a - XK_A);
    157     else if ((source >= XK_Agrave) && (source <= XK_Odiaeresis))
    158         dest = source + (XK_agrave - XK_Agrave);
    159     else if ((source >= XK_Ooblique) && (source <= XK_Thorn))
    160         dest = source + (XK_oslash - XK_Ooblique);
    161     else
    162         dest = source;
    163     return dest;
    164 }
    165 
    166 int
    167 CompareISOLatin1Lowered(const unsigned char *s1, int s1len,
    168                         const unsigned char *s2, int s2len)
    169 {
    170     unsigned char c1, c2;
    171 
    172     for (;;) {
    173         /* note -- compare against zero so that -1 ignores len */
    174         c1 = s1len-- ? *s1++ : '\0';
    175         c2 = s2len-- ? *s2++ : '\0';
    176         if (!c1 ||
    177             (c1 != c2 &&
    178              (c1 = ISOLatin1ToLower(c1)) != (c2 = ISOLatin1ToLower(c2))))
    179             break;
    180     }
    181     return (int) c1 - (int) c2;
    182 }
    183 
    184 /*
    185  * dixLookupWindow and dixLookupDrawable:
    186  * Look up the window/drawable taking into account the client doing the
    187  * lookup, the type of drawable desired, and the type of access desired.
    188  * Return Success with *pDraw set if the window/drawable exists and the client
    189  * is allowed access, else return an error code with *pDraw set to NULL.  The
    190  * access mask values are defined in resource.h.  The type mask values are
    191  * defined in pixmap.h, with zero equivalent to M_DRAWABLE.
    192  */
    193 int
    194 dixLookupDrawable(DrawablePtr *pDraw, XID id, ClientPtr client,
    195                   Mask type, Mask access)
    196 {
    197     DrawablePtr pTmp;
    198     int rc;
    199 
    200     *pDraw = NULL;
    201 
    202     rc = dixLookupResourceByClass((void **) &pTmp, id, RC_DRAWABLE, client,
    203                                   access);
    204 
    205     if (rc != Success)
    206         client->errorValue = id;
    207 
    208     if (rc == BadValue)
    209         return BadDrawable;
    210     if (rc != Success)
    211         return rc;
    212     if (!((1 << pTmp->type) & (type ? type : M_DRAWABLE)))
    213         return BadMatch;
    214 
    215     *pDraw = pTmp;
    216     return Success;
    217 }
    218 
    219 int
    220 dixLookupWindow(WindowPtr *pWin, XID id, ClientPtr client, Mask access)
    221 {
    222     int rc;
    223 
    224     rc = dixLookupDrawable((DrawablePtr *) pWin, id, client, M_WINDOW, access);
    225     /* dixLookupDrawable returns BadMatch iff id is a valid Drawable
    226        but is not a Window. Users of dixLookupWindow expect a BadWindow
    227        error in this case; they don't care that it's a valid non-Window XID */
    228     if (rc == BadMatch)
    229         rc = BadWindow;
    230     /* Similarly, users of dixLookupWindow don't want BadDrawable. */
    231     if (rc == BadDrawable)
    232         rc = BadWindow;
    233     return rc;
    234 }
    235 
    236 int
    237 dixLookupGC(GCPtr *pGC, XID id, ClientPtr client, Mask access)
    238 {
    239     return dixLookupResourceByType((void **) pGC, id, RT_GC, client, access);
    240 }
    241 
    242 int
    243 dixLookupFontable(FontPtr *pFont, XID id, ClientPtr client, Mask access)
    244 {
    245     int rc;
    246     GC *pGC;
    247 
    248     client->errorValue = id;    /* EITHER font or gc */
    249     rc = dixLookupResourceByType((void **) pFont, id, RT_FONT, client,
    250                                  access);
    251     if (rc != BadFont)
    252         return rc;
    253     rc = dixLookupResourceByType((void **) &pGC, id, RT_GC, client, access);
    254     if (rc == BadGC)
    255         return BadFont;
    256     if (rc == Success)
    257         *pFont = pGC->font;
    258     return rc;
    259 }
    260 
    261 int
    262 dixLookupClient(ClientPtr *pClient, XID rid, ClientPtr client, Mask access)
    263 {
    264     void *pRes;
    265     int rc = BadValue, clientIndex = CLIENT_ID(rid);
    266 
    267     if (!clientIndex || !clients[clientIndex] || (rid & SERVER_BIT))
    268         goto bad;
    269 
    270     rc = dixLookupResourceByClass(&pRes, rid, RC_ANY, client, DixGetAttrAccess);
    271     if (rc != Success)
    272         goto bad;
    273 
    274     rc = XaceHook(XACE_CLIENT_ACCESS, client, clients[clientIndex], access);
    275     if (rc != Success)
    276         goto bad;
    277 
    278     *pClient = clients[clientIndex];
    279     return Success;
    280  bad:
    281     if (client)
    282         client->errorValue = rid;
    283     *pClient = NULL;
    284     return rc;
    285 }
    286 
    287 int
    288 AlterSaveSetForClient(ClientPtr client, WindowPtr pWin, unsigned mode,
    289                       Bool toRoot, Bool map)
    290 {
    291     int numnow;
    292     SaveSetElt *pTmp = NULL;
    293     int j;
    294 
    295     numnow = client->numSaved;
    296     j = 0;
    297     if (numnow) {
    298         pTmp = client->saveSet;
    299         while ((j < numnow) && (SaveSetWindow(pTmp[j]) != (void *) pWin))
    300             j++;
    301     }
    302     if (mode == SetModeInsert) {
    303         if (j < numnow)         /* duplicate */
    304             return Success;
    305         numnow++;
    306         pTmp = (SaveSetElt *) realloc(client->saveSet, sizeof(*pTmp) * numnow);
    307         if (!pTmp)
    308             return BadAlloc;
    309         client->saveSet = pTmp;
    310         client->numSaved = numnow;
    311         SaveSetAssignWindow(client->saveSet[numnow - 1], pWin);
    312         SaveSetAssignToRoot(client->saveSet[numnow - 1], toRoot);
    313         SaveSetAssignMap(client->saveSet[numnow - 1], map);
    314         return Success;
    315     }
    316     else if ((mode == SetModeDelete) && (j < numnow)) {
    317         while (j < numnow - 1) {
    318             pTmp[j] = pTmp[j + 1];
    319             j++;
    320         }
    321         numnow--;
    322         if (numnow) {
    323             pTmp =
    324                 (SaveSetElt *) realloc(client->saveSet, sizeof(*pTmp) * numnow);
    325             if (pTmp)
    326                 client->saveSet = pTmp;
    327         }
    328         else {
    329             free(client->saveSet);
    330             client->saveSet = (SaveSetElt *) NULL;
    331         }
    332         client->numSaved = numnow;
    333         return Success;
    334     }
    335     return Success;
    336 }
    337 
    338 void
    339 DeleteWindowFromAnySaveSet(WindowPtr pWin)
    340 {
    341     int i;
    342     ClientPtr client;
    343 
    344     for (i = 0; i < currentMaxClients; i++) {
    345         client = clients[i];
    346         if (client && client->numSaved)
    347             (void) AlterSaveSetForClient(client, pWin, SetModeDelete, FALSE,
    348                                          TRUE);
    349     }
    350 }
    351 
    352 /* No-op Don't Do Anything : sometimes we need to be able to call a procedure
    353  * that doesn't do anything.  For example, on screen with only static
    354  * colormaps, if someone calls install colormap, it's easier to have a dummy
    355  * procedure to call than to check if there's a procedure
    356  */
    357 void
    358 NoopDDA(void)
    359 {
    360 }
    361 
    362 typedef struct _BlockHandler {
    363     ServerBlockHandlerProcPtr BlockHandler;
    364     ServerWakeupHandlerProcPtr WakeupHandler;
    365     void *blockData;
    366     Bool deleted;
    367 } BlockHandlerRec, *BlockHandlerPtr;
    368 
    369 static BlockHandlerPtr handlers;
    370 static int numHandlers;
    371 static int sizeHandlers;
    372 static Bool inHandler;
    373 static Bool handlerDeleted;
    374 
    375 /**
    376  *
    377  *  \param pTimeout   DIX doesn't want to know how OS represents time
    378  *  \param pReadMask  nor how it represents the det of descriptors
    379  */
    380 void
    381 BlockHandler(void *pTimeout)
    382 {
    383     int i, j;
    384 
    385     ++inHandler;
    386     for (i = 0; i < numHandlers; i++)
    387         if (!handlers[i].deleted)
    388             (*handlers[i].BlockHandler) (handlers[i].blockData, pTimeout);
    389 
    390     for (i = 0; i < screenInfo.numGPUScreens; i++)
    391         (*screenInfo.gpuscreens[i]->BlockHandler) (screenInfo.gpuscreens[i], pTimeout);
    392 
    393     for (i = 0; i < screenInfo.numScreens; i++)
    394         (*screenInfo.screens[i]->BlockHandler) (screenInfo.screens[i], pTimeout);
    395 
    396     if (handlerDeleted) {
    397         for (i = 0; i < numHandlers;)
    398             if (handlers[i].deleted) {
    399                 for (j = i; j < numHandlers - 1; j++)
    400                     handlers[j] = handlers[j + 1];
    401                 numHandlers--;
    402             }
    403             else
    404                 i++;
    405         handlerDeleted = FALSE;
    406     }
    407     --inHandler;
    408 }
    409 
    410 /**
    411  *
    412  *  \param result    32 bits of undefined result from the wait
    413  *  \param pReadmask the resulting descriptor mask
    414  */
    415 void
    416 WakeupHandler(int result)
    417 {
    418     int i, j;
    419 
    420     ++inHandler;
    421     for (i = 0; i < screenInfo.numScreens; i++)
    422         (*screenInfo.screens[i]->WakeupHandler) (screenInfo.screens[i], result);
    423     for (i = 0; i < screenInfo.numGPUScreens; i++)
    424         (*screenInfo.gpuscreens[i]->WakeupHandler) (screenInfo.gpuscreens[i], result);
    425     for (i = numHandlers - 1; i >= 0; i--)
    426         if (!handlers[i].deleted)
    427             (*handlers[i].WakeupHandler) (handlers[i].blockData, result);
    428     if (handlerDeleted) {
    429         for (i = 0; i < numHandlers;)
    430             if (handlers[i].deleted) {
    431                 for (j = i; j < numHandlers - 1; j++)
    432                     handlers[j] = handlers[j + 1];
    433                 numHandlers--;
    434             }
    435             else
    436                 i++;
    437         handlerDeleted = FALSE;
    438     }
    439     --inHandler;
    440 }
    441 
    442 /**
    443  * Reentrant with BlockHandler and WakeupHandler, except wakeup won't
    444  * get called until next time
    445  */
    446 Bool
    447 RegisterBlockAndWakeupHandlers(ServerBlockHandlerProcPtr blockHandler,
    448                                ServerWakeupHandlerProcPtr wakeupHandler,
    449                                void *blockData)
    450 {
    451     BlockHandlerPtr new;
    452 
    453     if (numHandlers >= sizeHandlers) {
    454         new = (BlockHandlerPtr) realloc(handlers, (numHandlers + 1) *
    455                                         sizeof(BlockHandlerRec));
    456         if (!new)
    457             return FALSE;
    458         handlers = new;
    459         sizeHandlers = numHandlers + 1;
    460     }
    461     handlers[numHandlers].BlockHandler = blockHandler;
    462     handlers[numHandlers].WakeupHandler = wakeupHandler;
    463     handlers[numHandlers].blockData = blockData;
    464     handlers[numHandlers].deleted = FALSE;
    465     numHandlers = numHandlers + 1;
    466     return TRUE;
    467 }
    468 
    469 void
    470 RemoveBlockAndWakeupHandlers(ServerBlockHandlerProcPtr blockHandler,
    471                              ServerWakeupHandlerProcPtr wakeupHandler,
    472                              void *blockData)
    473 {
    474     int i;
    475 
    476     for (i = 0; i < numHandlers; i++)
    477         if (handlers[i].BlockHandler == blockHandler &&
    478             handlers[i].WakeupHandler == wakeupHandler &&
    479             handlers[i].blockData == blockData) {
    480             if (inHandler) {
    481                 handlerDeleted = TRUE;
    482                 handlers[i].deleted = TRUE;
    483             }
    484             else {
    485                 for (; i < numHandlers - 1; i++)
    486                     handlers[i] = handlers[i + 1];
    487                 numHandlers--;
    488             }
    489             break;
    490         }
    491 }
    492 
    493 void
    494 InitBlockAndWakeupHandlers(void)
    495 {
    496     free(handlers);
    497     handlers = (BlockHandlerPtr) 0;
    498     numHandlers = 0;
    499     sizeHandlers = 0;
    500 }
    501 
    502 /*
    503  * A general work queue.  Perform some task before the server
    504  * sleeps for input.
    505  */
    506 
    507 WorkQueuePtr workQueue;
    508 static WorkQueuePtr *workQueueLast = &workQueue;
    509 
    510 void
    511 ClearWorkQueue(void)
    512 {
    513     WorkQueuePtr q, *p;
    514 
    515     p = &workQueue;
    516     while ((q = *p)) {
    517         *p = q->next;
    518         free(q);
    519     }
    520     workQueueLast = p;
    521 }
    522 
    523 void
    524 ProcessWorkQueue(void)
    525 {
    526     WorkQueuePtr q, *p;
    527 
    528     p = &workQueue;
    529     /*
    530      * Scan the work queue once, calling each function.  Those
    531      * which return TRUE are removed from the queue, otherwise
    532      * they will be called again.  This must be reentrant with
    533      * QueueWorkProc.
    534      */
    535     while ((q = *p)) {
    536         if ((*q->function) (q->client, q->closure)) {
    537             /* remove q from the list */
    538             *p = q->next;       /* don't fetch until after func called */
    539             free(q);
    540         }
    541         else {
    542             p = &q->next;       /* don't fetch until after func called */
    543         }
    544     }
    545     workQueueLast = p;
    546 }
    547 
    548 void
    549 ProcessWorkQueueZombies(void)
    550 {
    551     WorkQueuePtr q, *p;
    552 
    553     p = &workQueue;
    554     while ((q = *p)) {
    555         if (q->client && q->client->clientGone) {
    556             (void) (*q->function) (q->client, q->closure);
    557             /* remove q from the list */
    558             *p = q->next;       /* don't fetch until after func called */
    559             free(q);
    560         }
    561         else {
    562             p = &q->next;       /* don't fetch until after func called */
    563         }
    564     }
    565     workQueueLast = p;
    566 }
    567 
    568 Bool
    569 QueueWorkProc(Bool (*function) (ClientPtr pClient, void *closure),
    570               ClientPtr client, void *closure)
    571 {
    572     WorkQueuePtr q;
    573 
    574     q = malloc(sizeof *q);
    575     if (!q)
    576         return FALSE;
    577     q->function = function;
    578     q->client = client;
    579     q->closure = closure;
    580     q->next = NULL;
    581     *workQueueLast = q;
    582     workQueueLast = &q->next;
    583     return TRUE;
    584 }
    585 
    586 /*
    587  * Manage a queue of sleeping clients, awakening them
    588  * when requested, by using the OS functions IgnoreClient
    589  * and AttendClient.  Note that this *ignores* the troubles
    590  * with request data interleaving itself with events, but
    591  * we'll leave that until a later time.
    592  */
    593 
    594 typedef struct _SleepQueue {
    595     struct _SleepQueue *next;
    596     ClientPtr client;
    597     ClientSleepProcPtr function;
    598     void *closure;
    599 } SleepQueueRec, *SleepQueuePtr;
    600 
    601 static SleepQueuePtr sleepQueue = NULL;
    602 
    603 Bool
    604 ClientSleep(ClientPtr client, ClientSleepProcPtr function, void *closure)
    605 {
    606     SleepQueuePtr q;
    607 
    608     q = malloc(sizeof *q);
    609     if (!q)
    610         return FALSE;
    611 
    612     IgnoreClient(client);
    613     q->next = sleepQueue;
    614     q->client = client;
    615     q->function = function;
    616     q->closure = closure;
    617     sleepQueue = q;
    618     return TRUE;
    619 }
    620 
    621 Bool
    622 ClientSignal(ClientPtr client)
    623 {
    624     SleepQueuePtr q;
    625 
    626     for (q = sleepQueue; q; q = q->next)
    627         if (q->client == client) {
    628             return QueueWorkProc(q->function, q->client, q->closure);
    629         }
    630     return FALSE;
    631 }
    632 
    633 int
    634 ClientSignalAll(ClientPtr client, ClientSleepProcPtr function, void *closure)
    635 {
    636     SleepQueuePtr q;
    637     int count = 0;
    638 
    639     for (q = sleepQueue; q; q = q->next) {
    640         if (!(client == CLIENT_SIGNAL_ANY || q->client == client))
    641             continue;
    642 
    643         if (!(function == CLIENT_SIGNAL_ANY || q->function == function))
    644             continue;
    645 
    646         if (!(closure == CLIENT_SIGNAL_ANY || q->closure == closure))
    647             continue;
    648 
    649         count += QueueWorkProc(q->function, q->client, q->closure);
    650     }
    651 
    652     return count;
    653 }
    654 
    655 void
    656 ClientWakeup(ClientPtr client)
    657 {
    658     SleepQueuePtr q, *prev;
    659 
    660     prev = &sleepQueue;
    661     while ((q = *prev)) {
    662         if (q->client == client) {
    663             *prev = q->next;
    664             free(q);
    665             AttendClient(client);
    666             break;
    667         }
    668         prev = &q->next;
    669     }
    670 }
    671 
    672 Bool
    673 ClientIsAsleep(ClientPtr client)
    674 {
    675     SleepQueuePtr q;
    676 
    677     for (q = sleepQueue; q; q = q->next)
    678         if (q->client == client)
    679             return TRUE;
    680     return FALSE;
    681 }
    682 
    683 /*
    684  *  Generic Callback Manager
    685  */
    686 
    687 /* ===== Private Procedures ===== */
    688 
    689 static int numCallbackListsToCleanup = 0;
    690 static CallbackListPtr **listsToCleanup = NULL;
    691 
    692 static Bool
    693 _AddCallback(CallbackListPtr *pcbl, CallbackProcPtr callback, void *data)
    694 {
    695     CallbackPtr cbr;
    696 
    697     cbr = malloc(sizeof(CallbackRec));
    698     if (!cbr)
    699         return FALSE;
    700     cbr->proc = callback;
    701     cbr->data = data;
    702     cbr->next = (*pcbl)->list;
    703     cbr->deleted = FALSE;
    704     (*pcbl)->list = cbr;
    705     return TRUE;
    706 }
    707 
    708 static Bool
    709 _DeleteCallback(CallbackListPtr *pcbl, CallbackProcPtr callback, void *data)
    710 {
    711     CallbackListPtr cbl = *pcbl;
    712     CallbackPtr cbr, pcbr;
    713 
    714     for (pcbr = NULL, cbr = cbl->list; cbr != NULL; pcbr = cbr, cbr = cbr->next) {
    715         if ((cbr->proc == callback) && (cbr->data == data))
    716             break;
    717     }
    718     if (cbr != NULL) {
    719         if (cbl->inCallback) {
    720             ++(cbl->numDeleted);
    721             cbr->deleted = TRUE;
    722         }
    723         else {
    724             if (pcbr == NULL)
    725                 cbl->list = cbr->next;
    726             else
    727                 pcbr->next = cbr->next;
    728             free(cbr);
    729         }
    730         return TRUE;
    731     }
    732     return FALSE;
    733 }
    734 
    735 void
    736 _CallCallbacks(CallbackListPtr *pcbl, void *call_data)
    737 {
    738     CallbackListPtr cbl = *pcbl;
    739     CallbackPtr cbr, pcbr;
    740 
    741     ++(cbl->inCallback);
    742     for (cbr = cbl->list; cbr != NULL; cbr = cbr->next) {
    743         (*(cbr->proc)) (pcbl, cbr->data, call_data);
    744     }
    745     --(cbl->inCallback);
    746 
    747     if (cbl->inCallback)
    748         return;
    749 
    750     /* Was the entire list marked for deletion? */
    751 
    752     if (cbl->deleted) {
    753         DeleteCallbackList(pcbl);
    754         return;
    755     }
    756 
    757     /* Were some individual callbacks on the list marked for deletion?
    758      * If so, do the deletions.
    759      */
    760 
    761     if (cbl->numDeleted) {
    762         for (pcbr = NULL, cbr = cbl->list; (cbr != NULL) && cbl->numDeleted;) {
    763             if (cbr->deleted) {
    764                 if (pcbr) {
    765                     cbr = cbr->next;
    766                     free(pcbr->next);
    767                     pcbr->next = cbr;
    768                 }
    769                 else {
    770                     cbr = cbr->next;
    771                     free(cbl->list);
    772                     cbl->list = cbr;
    773                 }
    774                 cbl->numDeleted--;
    775             }
    776             else {              /* this one wasn't deleted */
    777 
    778                 pcbr = cbr;
    779                 cbr = cbr->next;
    780             }
    781         }
    782     }
    783 }
    784 
    785 static void
    786 _DeleteCallbackList(CallbackListPtr *pcbl)
    787 {
    788     CallbackListPtr cbl = *pcbl;
    789     CallbackPtr cbr, nextcbr;
    790     int i;
    791 
    792     if (cbl->inCallback) {
    793         cbl->deleted = TRUE;
    794         return;
    795     }
    796 
    797     for (i = 0; i < numCallbackListsToCleanup; i++) {
    798         if (listsToCleanup[i] == pcbl) {
    799             listsToCleanup[i] = NULL;
    800             break;
    801         }
    802     }
    803 
    804     for (cbr = cbl->list; cbr != NULL; cbr = nextcbr) {
    805         nextcbr = cbr->next;
    806         free(cbr);
    807     }
    808     free(cbl);
    809     *pcbl = NULL;
    810 }
    811 
    812 static Bool
    813 CreateCallbackList(CallbackListPtr *pcbl)
    814 {
    815     CallbackListPtr cbl;
    816     int i;
    817 
    818     if (!pcbl)
    819         return FALSE;
    820     cbl = malloc(sizeof(CallbackListRec));
    821     if (!cbl)
    822         return FALSE;
    823     cbl->inCallback = 0;
    824     cbl->deleted = FALSE;
    825     cbl->numDeleted = 0;
    826     cbl->list = NULL;
    827     *pcbl = cbl;
    828 
    829     for (i = 0; i < numCallbackListsToCleanup; i++) {
    830         if (!listsToCleanup[i]) {
    831             listsToCleanup[i] = pcbl;
    832             return TRUE;
    833         }
    834     }
    835 
    836     listsToCleanup = (CallbackListPtr **) xnfrealloc(listsToCleanup,
    837                                                      sizeof(CallbackListPtr *) *
    838                                                      (numCallbackListsToCleanup
    839                                                       + 1));
    840     listsToCleanup[numCallbackListsToCleanup] = pcbl;
    841     numCallbackListsToCleanup++;
    842     return TRUE;
    843 }
    844 
    845 /* ===== Public Procedures ===== */
    846 
    847 Bool
    848 AddCallback(CallbackListPtr *pcbl, CallbackProcPtr callback, void *data)
    849 {
    850     if (!pcbl)
    851         return FALSE;
    852     if (!*pcbl) {               /* list hasn't been created yet; go create it */
    853         if (!CreateCallbackList(pcbl))
    854             return FALSE;
    855     }
    856     return _AddCallback(pcbl, callback, data);
    857 }
    858 
    859 Bool
    860 DeleteCallback(CallbackListPtr *pcbl, CallbackProcPtr callback, void *data)
    861 {
    862     if (!pcbl || !*pcbl)
    863         return FALSE;
    864     return _DeleteCallback(pcbl, callback, data);
    865 }
    866 
    867 void
    868 DeleteCallbackList(CallbackListPtr *pcbl)
    869 {
    870     if (!pcbl || !*pcbl)
    871         return;
    872     _DeleteCallbackList(pcbl);
    873 }
    874 
    875 void
    876 DeleteCallbackManager(void)
    877 {
    878     int i;
    879 
    880     for (i = 0; i < numCallbackListsToCleanup; i++) {
    881         DeleteCallbackList(listsToCleanup[i]);
    882     }
    883     free(listsToCleanup);
    884 
    885     numCallbackListsToCleanup = 0;
    886     listsToCleanup = NULL;
    887 }
    888 
    889 void
    890 InitCallbackManager(void)
    891 {
    892     DeleteCallbackManager();
    893 }
    894 
    895 /**
    896  * Coordinates the global GL context used by modules in the X Server
    897  * doing rendering with OpenGL.
    898  *
    899  * When setting a GL context (glXMakeCurrent() or eglMakeCurrent()),
    900  * there is an expensive implied glFlush() required by the GLX and EGL
    901  * APIs, so modules don't want to have to do it on every request.  But
    902  * the individual modules using GL also don't know about each other,
    903  * so they have to coordinate who owns the current context.
    904  *
    905  * When you're about to do a MakeCurrent, you should set this variable
    906  * to your context's address, and you can skip MakeCurrent if it's
    907  * already set to yours.
    908  *
    909  * When you're about to do a DestroyContext, you should set this to
    910  * NULL if it's set to your context.
    911  *
    912  * When you're about to do an unbindContext on a DRI driver, you
    913  * should set this to NULL.  Despite the unbindContext interface
    914  * sounding like it only unbinds the passed in context, it actually
    915  * unconditionally clears the dispatch table even if the given
    916  * context wasn't current.
    917  */
    918 void *lastGLContext = NULL;