123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241 |
- /*
- *
- Copyright 1992, 1998 The Open Group
- Permission to use, copy, modify, distribute, and sell this software and its
- documentation for any purpose is hereby granted without fee, provided that
- the above copyright notice appear in all copies and that both that
- copyright notice and this permission notice appear in supporting
- documentation.
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- Except as contained in this notice, the name of The Open Group shall not be
- used in advertising or otherwise to promote the sale, use or other dealings
- in this Software without prior written authorization from The Open Group.
- *
- * Author: Keith Packard, MIT X Consortium
- */
- /* dixsleep.c - implement millisecond timeouts for X clients */
- #ifdef HAVE_DIX_CONFIG_H
- #include <dix-config.h>
- #endif
- #include "sleepuntil.h"
- #include <X11/X.h>
- #include <X11/Xmd.h>
- #include "misc.h"
- #include "windowstr.h"
- #include "dixstruct.h"
- #include "pixmapstr.h"
- #include "scrnintstr.h"
- typedef struct _Sertafied {
- struct _Sertafied *next;
- TimeStamp revive;
- ClientPtr pClient;
- XID id;
- void (*notifyFunc) (ClientPtr /* client */ ,
- pointer /* closure */
- );
- pointer closure;
- } SertafiedRec, *SertafiedPtr;
- static SertafiedPtr pPending;
- static RESTYPE SertafiedResType;
- static Bool BlockHandlerRegistered;
- static int SertafiedGeneration;
- static void ClientAwaken(ClientPtr /* client */ ,
- pointer /* closure */
- );
- static int SertafiedDelete(pointer /* value */ ,
- XID /* id */
- );
- static void SertafiedBlockHandler(pointer /* data */ ,
- OSTimePtr /* wt */ ,
- pointer /* LastSelectMask */
- );
- static void SertafiedWakeupHandler(pointer /* data */ ,
- int /* i */ ,
- pointer /* LastSelectMask */
- );
- _X_EXPORT int
- ClientSleepUntil(client, revive, notifyFunc, closure)
- ClientPtr client;
- TimeStamp *revive;
- void (*notifyFunc) (ClientPtr /* client */ ,
- pointer /* closure */ );
- pointer closure;
- {
- SertafiedPtr pRequest, pReq, pPrev;
- if (SertafiedGeneration != serverGeneration) {
- SertafiedResType = CreateNewResourceType(SertafiedDelete);
- if (!SertafiedResType)
- return FALSE;
- SertafiedGeneration = serverGeneration;
- BlockHandlerRegistered = FALSE;
- }
- pRequest = malloc(sizeof(SertafiedRec));
- if (!pRequest)
- return FALSE;
- pRequest->pClient = client;
- pRequest->revive = *revive;
- pRequest->id = FakeClientID(client->index);
- pRequest->closure = closure;
- if (!BlockHandlerRegistered) {
- if (!RegisterBlockAndWakeupHandlers(SertafiedBlockHandler,
- SertafiedWakeupHandler,
- (pointer) 0)) {
- free(pRequest);
- return FALSE;
- }
- BlockHandlerRegistered = TRUE;
- }
- pRequest->notifyFunc = 0;
- if (!AddResource(pRequest->id, SertafiedResType, (pointer) pRequest))
- return FALSE;
- if (!notifyFunc)
- notifyFunc = ClientAwaken;
- pRequest->notifyFunc = notifyFunc;
- /* Insert into time-ordered queue, with earliest activation time coming first. */
- pPrev = 0;
- for (pReq = pPending; pReq; pReq = pReq->next) {
- if (CompareTimeStamps(pReq->revive, *revive) == LATER)
- break;
- pPrev = pReq;
- }
- if (pPrev)
- pPrev->next = pRequest;
- else
- pPending = pRequest;
- pRequest->next = pReq;
- IgnoreClient(client);
- return TRUE;
- }
- static void
- ClientAwaken(client, closure)
- ClientPtr client;
- pointer closure;
- {
- if (!client->clientGone)
- AttendClient(client);
- }
- static int
- SertafiedDelete(value, id)
- pointer value;
- XID id;
- {
- SertafiedPtr pRequest = (SertafiedPtr) value;
- SertafiedPtr pReq, pPrev;
- pPrev = 0;
- for (pReq = pPending; pReq; pPrev = pReq, pReq = pReq->next)
- if (pReq == pRequest) {
- if (pPrev)
- pPrev->next = pReq->next;
- else
- pPending = pReq->next;
- break;
- }
- if (pRequest->notifyFunc)
- (*pRequest->notifyFunc) (pRequest->pClient, pRequest->closure);
- free(pRequest);
- return TRUE;
- }
- static void
- SertafiedBlockHandler(data, wt, LastSelectMask)
- pointer data; /* unused */
- OSTimePtr wt; /* wait time */
- pointer LastSelectMask;
- {
- SertafiedPtr pReq, pNext;
- unsigned long delay;
- TimeStamp now;
- if (!pPending)
- return;
- now.milliseconds = GetTimeInMillis();
- now.months = currentTime.months;
- if ((int) (now.milliseconds - currentTime.milliseconds) < 0)
- now.months++;
- for (pReq = pPending; pReq; pReq = pNext) {
- pNext = pReq->next;
- if (CompareTimeStamps(pReq->revive, now) == LATER)
- break;
- FreeResource(pReq->id, RT_NONE);
- /* AttendClient() may have been called via the resource delete
- * function so a client may have input to be processed and so
- * set delay to 0 to prevent blocking in WaitForSomething().
- */
- AdjustWaitForDelay(wt, 0);
- }
- pReq = pPending;
- if (!pReq)
- return;
- delay = pReq->revive.milliseconds - now.milliseconds;
- AdjustWaitForDelay(wt, delay);
- }
- static void
- SertafiedWakeupHandler(data, i, LastSelectMask)
- pointer data;
- int i;
- pointer LastSelectMask;
- {
- SertafiedPtr pReq, pNext;
- TimeStamp now;
- now.milliseconds = GetTimeInMillis();
- now.months = currentTime.months;
- if ((int) (now.milliseconds - currentTime.milliseconds) < 0)
- now.months++;
- for (pReq = pPending; pReq; pReq = pNext) {
- pNext = pReq->next;
- if (CompareTimeStamps(pReq->revive, now) == LATER)
- break;
- FreeResource(pReq->id, RT_NONE);
- }
- if (!pPending) {
- RemoveBlockAndWakeupHandlers(SertafiedBlockHandler,
- SertafiedWakeupHandler, (pointer) 0);
- BlockHandlerRegistered = FALSE;
- }
- }
|