105b261ecSmrg/* 205b261ecSmrg * 305b261ecSmrgCopyright 1992, 1998 The Open Group 405b261ecSmrg 505b261ecSmrgPermission to use, copy, modify, distribute, and sell this software and its 605b261ecSmrgdocumentation for any purpose is hereby granted without fee, provided that 705b261ecSmrgthe above copyright notice appear in all copies and that both that 805b261ecSmrgcopyright notice and this permission notice appear in supporting 905b261ecSmrgdocumentation. 1005b261ecSmrg 1105b261ecSmrgThe above copyright notice and this permission notice shall be included in 1205b261ecSmrgall copies or substantial portions of the Software. 1305b261ecSmrg 1405b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1505b261ecSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1605b261ecSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 1705b261ecSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 1805b261ecSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 1905b261ecSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2005b261ecSmrg 2105b261ecSmrgExcept as contained in this notice, the name of The Open Group shall not be 2205b261ecSmrgused in advertising or otherwise to promote the sale, use or other dealings 2305b261ecSmrgin this Software without prior written authorization from The Open Group. 2405b261ecSmrg * 2505b261ecSmrg * Author: Keith Packard, MIT X Consortium 2605b261ecSmrg */ 2705b261ecSmrg 2805b261ecSmrg/* dixsleep.c - implement millisecond timeouts for X clients */ 2905b261ecSmrg 3005b261ecSmrg#ifdef HAVE_DIX_CONFIG_H 3105b261ecSmrg#include <dix-config.h> 3205b261ecSmrg#endif 3305b261ecSmrg 3405b261ecSmrg#include "sleepuntil.h" 3505b261ecSmrg#include <X11/X.h> 3605b261ecSmrg#include <X11/Xmd.h> 3705b261ecSmrg#include "misc.h" 3805b261ecSmrg#include "windowstr.h" 3905b261ecSmrg#include "dixstruct.h" 4005b261ecSmrg#include "pixmapstr.h" 4105b261ecSmrg#include "scrnintstr.h" 4205b261ecSmrg 4305b261ecSmrgtypedef struct _Sertafied { 4435c4bbdfSmrg struct _Sertafied *next; 4535c4bbdfSmrg TimeStamp revive; 4635c4bbdfSmrg ClientPtr pClient; 4735c4bbdfSmrg XID id; 4835c4bbdfSmrg void (*notifyFunc) (ClientPtr /* client */ , 4935c4bbdfSmrg void * /* closure */ 5035c4bbdfSmrg ); 5135c4bbdfSmrg 5235c4bbdfSmrg void *closure; 5305b261ecSmrg} SertafiedRec, *SertafiedPtr; 5405b261ecSmrg 5505b261ecSmrgstatic SertafiedPtr pPending; 5635c4bbdfSmrgstatic RESTYPE SertafiedResType; 5735c4bbdfSmrgstatic Bool BlockHandlerRegistered; 5835c4bbdfSmrgstatic int SertafiedGeneration; 5935c4bbdfSmrg 6035c4bbdfSmrgstatic void ClientAwaken(ClientPtr /* client */ , 6135c4bbdfSmrg void * /* closure */ 6235c4bbdfSmrg ); 6335c4bbdfSmrgstatic int SertafiedDelete(void * /* value */ , 6435c4bbdfSmrg XID /* id */ 6535c4bbdfSmrg ); 661b5d61b8Smrgstatic void SertafiedBlockHandler(void *data, 671b5d61b8Smrg void *timeout); 681b5d61b8Smrg 691b5d61b8Smrgstatic void SertafiedWakeupHandler(void *data, 701b5d61b8Smrg int i); 7105b261ecSmrg 726747b715Smrgint 7335c4bbdfSmrgClientSleepUntil(ClientPtr client, 7435c4bbdfSmrg TimeStamp *revive, 7535c4bbdfSmrg void (*notifyFunc) (ClientPtr, void *), void *closure) 7605b261ecSmrg{ 7735c4bbdfSmrg SertafiedPtr pRequest, pReq, pPrev; 7835c4bbdfSmrg 7935c4bbdfSmrg if (SertafiedGeneration != serverGeneration) { 8035c4bbdfSmrg SertafiedResType = CreateNewResourceType(SertafiedDelete, 8135c4bbdfSmrg "ClientSleep"); 8235c4bbdfSmrg if (!SertafiedResType) 8335c4bbdfSmrg return FALSE; 8435c4bbdfSmrg SertafiedGeneration = serverGeneration; 8535c4bbdfSmrg BlockHandlerRegistered = FALSE; 8605b261ecSmrg } 8735c4bbdfSmrg pRequest = malloc(sizeof(SertafiedRec)); 8805b261ecSmrg if (!pRequest) 8935c4bbdfSmrg return FALSE; 9005b261ecSmrg pRequest->pClient = client; 9105b261ecSmrg pRequest->revive = *revive; 9235c4bbdfSmrg pRequest->id = FakeClientID(client->index); 9305b261ecSmrg pRequest->closure = closure; 9435c4bbdfSmrg if (!BlockHandlerRegistered) { 9535c4bbdfSmrg if (!RegisterBlockAndWakeupHandlers(SertafiedBlockHandler, 9635c4bbdfSmrg SertafiedWakeupHandler, 9735c4bbdfSmrg (void *) 0)) { 9835c4bbdfSmrg free(pRequest); 9935c4bbdfSmrg return FALSE; 10035c4bbdfSmrg } 10135c4bbdfSmrg BlockHandlerRegistered = TRUE; 10205b261ecSmrg } 10305b261ecSmrg pRequest->notifyFunc = 0; 10435c4bbdfSmrg if (!AddResource(pRequest->id, SertafiedResType, (void *) pRequest)) 10535c4bbdfSmrg return FALSE; 10605b261ecSmrg if (!notifyFunc) 10735c4bbdfSmrg notifyFunc = ClientAwaken; 10805b261ecSmrg pRequest->notifyFunc = notifyFunc; 10905b261ecSmrg /* Insert into time-ordered queue, with earliest activation time coming first. */ 11005b261ecSmrg pPrev = 0; 11135c4bbdfSmrg for (pReq = pPending; pReq; pReq = pReq->next) { 11235c4bbdfSmrg if (CompareTimeStamps(pReq->revive, *revive) == LATER) 11335c4bbdfSmrg break; 11435c4bbdfSmrg pPrev = pReq; 11505b261ecSmrg } 11605b261ecSmrg if (pPrev) 11735c4bbdfSmrg pPrev->next = pRequest; 11805b261ecSmrg else 11935c4bbdfSmrg pPending = pRequest; 12005b261ecSmrg pRequest->next = pReq; 12135c4bbdfSmrg IgnoreClient(client); 12205b261ecSmrg return TRUE; 12305b261ecSmrg} 12405b261ecSmrg 12505b261ecSmrgstatic void 12635c4bbdfSmrgClientAwaken(ClientPtr client, void *closure) 12705b261ecSmrg{ 12825da500fSmrg AttendClient(client); 12905b261ecSmrg} 13005b261ecSmrg 13105b261ecSmrgstatic int 13235c4bbdfSmrgSertafiedDelete(void *value, XID id) 13305b261ecSmrg{ 13435c4bbdfSmrg SertafiedPtr pRequest = (SertafiedPtr) value; 13535c4bbdfSmrg SertafiedPtr pReq, pPrev; 13605b261ecSmrg 13705b261ecSmrg pPrev = 0; 13805b261ecSmrg for (pReq = pPending; pReq; pPrev = pReq, pReq = pReq->next) 13935c4bbdfSmrg if (pReq == pRequest) { 14035c4bbdfSmrg if (pPrev) 14135c4bbdfSmrg pPrev->next = pReq->next; 14235c4bbdfSmrg else 14335c4bbdfSmrg pPending = pReq->next; 14435c4bbdfSmrg break; 14535c4bbdfSmrg } 14605b261ecSmrg if (pRequest->notifyFunc) 14735c4bbdfSmrg (*pRequest->notifyFunc) (pRequest->pClient, pRequest->closure); 1486747b715Smrg free(pRequest); 14905b261ecSmrg return TRUE; 15005b261ecSmrg} 15105b261ecSmrg 15205b261ecSmrgstatic void 1531b5d61b8SmrgSertafiedBlockHandler(void *data, void *wt) 15405b261ecSmrg{ 15535c4bbdfSmrg SertafiedPtr pReq, pNext; 15635c4bbdfSmrg unsigned long delay; 15735c4bbdfSmrg TimeStamp now; 15805b261ecSmrg 15905b261ecSmrg if (!pPending) 16035c4bbdfSmrg return; 16135c4bbdfSmrg now.milliseconds = GetTimeInMillis(); 16205b261ecSmrg now.months = currentTime.months; 16305b261ecSmrg if ((int) (now.milliseconds - currentTime.milliseconds) < 0) 16435c4bbdfSmrg now.months++; 16535c4bbdfSmrg for (pReq = pPending; pReq; pReq = pNext) { 16635c4bbdfSmrg pNext = pReq->next; 16735c4bbdfSmrg if (CompareTimeStamps(pReq->revive, now) == LATER) 16835c4bbdfSmrg break; 16935c4bbdfSmrg FreeResource(pReq->id, RT_NONE); 17035c4bbdfSmrg 17135c4bbdfSmrg /* AttendClient() may have been called via the resource delete 17235c4bbdfSmrg * function so a client may have input to be processed and so 17335c4bbdfSmrg * set delay to 0 to prevent blocking in WaitForSomething(). 17435c4bbdfSmrg */ 17535c4bbdfSmrg AdjustWaitForDelay(wt, 0); 17605b261ecSmrg } 17705b261ecSmrg pReq = pPending; 17805b261ecSmrg if (!pReq) 17935c4bbdfSmrg return; 18005b261ecSmrg delay = pReq->revive.milliseconds - now.milliseconds; 18135c4bbdfSmrg AdjustWaitForDelay(wt, delay); 18205b261ecSmrg} 18305b261ecSmrg 18405b261ecSmrgstatic void 1851b5d61b8SmrgSertafiedWakeupHandler(void *data, int i) 18605b261ecSmrg{ 18735c4bbdfSmrg SertafiedPtr pReq, pNext; 18835c4bbdfSmrg TimeStamp now; 18905b261ecSmrg 19035c4bbdfSmrg now.milliseconds = GetTimeInMillis(); 19105b261ecSmrg now.months = currentTime.months; 19205b261ecSmrg if ((int) (now.milliseconds - currentTime.milliseconds) < 0) 19335c4bbdfSmrg now.months++; 19435c4bbdfSmrg for (pReq = pPending; pReq; pReq = pNext) { 19535c4bbdfSmrg pNext = pReq->next; 19635c4bbdfSmrg if (CompareTimeStamps(pReq->revive, now) == LATER) 19735c4bbdfSmrg break; 19835c4bbdfSmrg FreeResource(pReq->id, RT_NONE); 19905b261ecSmrg } 20035c4bbdfSmrg if (!pPending) { 20135c4bbdfSmrg RemoveBlockAndWakeupHandlers(SertafiedBlockHandler, 20235c4bbdfSmrg SertafiedWakeupHandler, (void *) 0); 20335c4bbdfSmrg BlockHandlerRegistered = FALSE; 20405b261ecSmrg } 20505b261ecSmrg} 206