xref: /OK3568_Linux_fs/external/xserver/Xext/sleepuntil.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  *
3*4882a593Smuzhiyun Copyright 1992, 1998  The Open Group
4*4882a593Smuzhiyun 
5*4882a593Smuzhiyun Permission to use, copy, modify, distribute, and sell this software and its
6*4882a593Smuzhiyun documentation for any purpose is hereby granted without fee, provided that
7*4882a593Smuzhiyun the above copyright notice appear in all copies and that both that
8*4882a593Smuzhiyun copyright notice and this permission notice appear in supporting
9*4882a593Smuzhiyun documentation.
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun The above copyright notice and this permission notice shall be included in
12*4882a593Smuzhiyun all copies or substantial portions of the Software.
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15*4882a593Smuzhiyun IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16*4882a593Smuzhiyun FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17*4882a593Smuzhiyun OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18*4882a593Smuzhiyun AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19*4882a593Smuzhiyun CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun Except as contained in this notice, the name of The Open Group shall not be
22*4882a593Smuzhiyun used in advertising or otherwise to promote the sale, use or other dealings
23*4882a593Smuzhiyun in this Software without prior written authorization from The Open Group.
24*4882a593Smuzhiyun  *
25*4882a593Smuzhiyun  * Author:  Keith Packard, MIT X Consortium
26*4882a593Smuzhiyun  */
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun /* dixsleep.c - implement millisecond timeouts for X clients */
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun #ifdef HAVE_DIX_CONFIG_H
31*4882a593Smuzhiyun #include <dix-config.h>
32*4882a593Smuzhiyun #endif
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun #include "sleepuntil.h"
35*4882a593Smuzhiyun #include <X11/X.h>
36*4882a593Smuzhiyun #include <X11/Xmd.h>
37*4882a593Smuzhiyun #include "misc.h"
38*4882a593Smuzhiyun #include "windowstr.h"
39*4882a593Smuzhiyun #include "dixstruct.h"
40*4882a593Smuzhiyun #include "pixmapstr.h"
41*4882a593Smuzhiyun #include "scrnintstr.h"
42*4882a593Smuzhiyun 
43*4882a593Smuzhiyun typedef struct _Sertafied {
44*4882a593Smuzhiyun     struct _Sertafied *next;
45*4882a593Smuzhiyun     TimeStamp revive;
46*4882a593Smuzhiyun     ClientPtr pClient;
47*4882a593Smuzhiyun     XID id;
48*4882a593Smuzhiyun     void (*notifyFunc) (ClientPtr /* client */ ,
49*4882a593Smuzhiyun                         void *    /* closure */
50*4882a593Smuzhiyun         );
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun     void *closure;
53*4882a593Smuzhiyun } SertafiedRec, *SertafiedPtr;
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun static SertafiedPtr pPending;
56*4882a593Smuzhiyun static RESTYPE SertafiedResType;
57*4882a593Smuzhiyun static Bool BlockHandlerRegistered;
58*4882a593Smuzhiyun static int SertafiedGeneration;
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun static void ClientAwaken(ClientPtr /* client */ ,
61*4882a593Smuzhiyun                          void *    /* closure */
62*4882a593Smuzhiyun     );
63*4882a593Smuzhiyun static int SertafiedDelete(void *  /* value */ ,
64*4882a593Smuzhiyun                            XID     /* id */
65*4882a593Smuzhiyun     );
66*4882a593Smuzhiyun static void SertafiedBlockHandler(void *data,
67*4882a593Smuzhiyun                                   void *timeout);
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun static void SertafiedWakeupHandler(void *data,
70*4882a593Smuzhiyun                                    int i);
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun int
ClientSleepUntil(ClientPtr client,TimeStamp * revive,void (* notifyFunc)(ClientPtr,void *),void * closure)73*4882a593Smuzhiyun ClientSleepUntil(ClientPtr client,
74*4882a593Smuzhiyun                  TimeStamp *revive,
75*4882a593Smuzhiyun                  void (*notifyFunc) (ClientPtr, void *), void *closure)
76*4882a593Smuzhiyun {
77*4882a593Smuzhiyun     SertafiedPtr pRequest, pReq, pPrev;
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun     if (SertafiedGeneration != serverGeneration) {
80*4882a593Smuzhiyun         SertafiedResType = CreateNewResourceType(SertafiedDelete,
81*4882a593Smuzhiyun                                                  "ClientSleep");
82*4882a593Smuzhiyun         if (!SertafiedResType)
83*4882a593Smuzhiyun             return FALSE;
84*4882a593Smuzhiyun         SertafiedGeneration = serverGeneration;
85*4882a593Smuzhiyun         BlockHandlerRegistered = FALSE;
86*4882a593Smuzhiyun     }
87*4882a593Smuzhiyun     pRequest = malloc(sizeof(SertafiedRec));
88*4882a593Smuzhiyun     if (!pRequest)
89*4882a593Smuzhiyun         return FALSE;
90*4882a593Smuzhiyun     pRequest->pClient = client;
91*4882a593Smuzhiyun     pRequest->revive = *revive;
92*4882a593Smuzhiyun     pRequest->id = FakeClientID(client->index);
93*4882a593Smuzhiyun     pRequest->closure = closure;
94*4882a593Smuzhiyun     if (!BlockHandlerRegistered) {
95*4882a593Smuzhiyun         if (!RegisterBlockAndWakeupHandlers(SertafiedBlockHandler,
96*4882a593Smuzhiyun                                             SertafiedWakeupHandler,
97*4882a593Smuzhiyun                                             (void *) 0)) {
98*4882a593Smuzhiyun             free(pRequest);
99*4882a593Smuzhiyun             return FALSE;
100*4882a593Smuzhiyun         }
101*4882a593Smuzhiyun         BlockHandlerRegistered = TRUE;
102*4882a593Smuzhiyun     }
103*4882a593Smuzhiyun     pRequest->notifyFunc = 0;
104*4882a593Smuzhiyun     if (!AddResource(pRequest->id, SertafiedResType, (void *) pRequest))
105*4882a593Smuzhiyun         return FALSE;
106*4882a593Smuzhiyun     if (!notifyFunc)
107*4882a593Smuzhiyun         notifyFunc = ClientAwaken;
108*4882a593Smuzhiyun     pRequest->notifyFunc = notifyFunc;
109*4882a593Smuzhiyun     /* Insert into time-ordered queue, with earliest activation time coming first. */
110*4882a593Smuzhiyun     pPrev = 0;
111*4882a593Smuzhiyun     for (pReq = pPending; pReq; pReq = pReq->next) {
112*4882a593Smuzhiyun         if (CompareTimeStamps(pReq->revive, *revive) == LATER)
113*4882a593Smuzhiyun             break;
114*4882a593Smuzhiyun         pPrev = pReq;
115*4882a593Smuzhiyun     }
116*4882a593Smuzhiyun     if (pPrev)
117*4882a593Smuzhiyun         pPrev->next = pRequest;
118*4882a593Smuzhiyun     else
119*4882a593Smuzhiyun         pPending = pRequest;
120*4882a593Smuzhiyun     pRequest->next = pReq;
121*4882a593Smuzhiyun     IgnoreClient(client);
122*4882a593Smuzhiyun     return TRUE;
123*4882a593Smuzhiyun }
124*4882a593Smuzhiyun 
125*4882a593Smuzhiyun static void
ClientAwaken(ClientPtr client,void * closure)126*4882a593Smuzhiyun ClientAwaken(ClientPtr client, void *closure)
127*4882a593Smuzhiyun {
128*4882a593Smuzhiyun     AttendClient(client);
129*4882a593Smuzhiyun }
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun static int
SertafiedDelete(void * value,XID id)132*4882a593Smuzhiyun SertafiedDelete(void *value, XID id)
133*4882a593Smuzhiyun {
134*4882a593Smuzhiyun     SertafiedPtr pRequest = (SertafiedPtr) value;
135*4882a593Smuzhiyun     SertafiedPtr pReq, pPrev;
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun     pPrev = 0;
138*4882a593Smuzhiyun     for (pReq = pPending; pReq; pPrev = pReq, pReq = pReq->next)
139*4882a593Smuzhiyun         if (pReq == pRequest) {
140*4882a593Smuzhiyun             if (pPrev)
141*4882a593Smuzhiyun                 pPrev->next = pReq->next;
142*4882a593Smuzhiyun             else
143*4882a593Smuzhiyun                 pPending = pReq->next;
144*4882a593Smuzhiyun             break;
145*4882a593Smuzhiyun         }
146*4882a593Smuzhiyun     if (pRequest->notifyFunc)
147*4882a593Smuzhiyun         (*pRequest->notifyFunc) (pRequest->pClient, pRequest->closure);
148*4882a593Smuzhiyun     free(pRequest);
149*4882a593Smuzhiyun     return TRUE;
150*4882a593Smuzhiyun }
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun static void
SertafiedBlockHandler(void * data,void * wt)153*4882a593Smuzhiyun SertafiedBlockHandler(void *data, void *wt)
154*4882a593Smuzhiyun {
155*4882a593Smuzhiyun     SertafiedPtr pReq, pNext;
156*4882a593Smuzhiyun     unsigned long delay;
157*4882a593Smuzhiyun     TimeStamp now;
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun     if (!pPending)
160*4882a593Smuzhiyun         return;
161*4882a593Smuzhiyun     now.milliseconds = GetTimeInMillis();
162*4882a593Smuzhiyun     now.months = currentTime.months;
163*4882a593Smuzhiyun     if ((int) (now.milliseconds - currentTime.milliseconds) < 0)
164*4882a593Smuzhiyun         now.months++;
165*4882a593Smuzhiyun     for (pReq = pPending; pReq; pReq = pNext) {
166*4882a593Smuzhiyun         pNext = pReq->next;
167*4882a593Smuzhiyun         if (CompareTimeStamps(pReq->revive, now) == LATER)
168*4882a593Smuzhiyun             break;
169*4882a593Smuzhiyun         FreeResource(pReq->id, RT_NONE);
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun         /* AttendClient() may have been called via the resource delete
172*4882a593Smuzhiyun          * function so a client may have input to be processed and so
173*4882a593Smuzhiyun          *  set delay to 0 to prevent blocking in WaitForSomething().
174*4882a593Smuzhiyun          */
175*4882a593Smuzhiyun         AdjustWaitForDelay(wt, 0);
176*4882a593Smuzhiyun     }
177*4882a593Smuzhiyun     pReq = pPending;
178*4882a593Smuzhiyun     if (!pReq)
179*4882a593Smuzhiyun         return;
180*4882a593Smuzhiyun     delay = pReq->revive.milliseconds - now.milliseconds;
181*4882a593Smuzhiyun     AdjustWaitForDelay(wt, delay);
182*4882a593Smuzhiyun }
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun static void
SertafiedWakeupHandler(void * data,int i)185*4882a593Smuzhiyun SertafiedWakeupHandler(void *data, int i)
186*4882a593Smuzhiyun {
187*4882a593Smuzhiyun     SertafiedPtr pReq, pNext;
188*4882a593Smuzhiyun     TimeStamp now;
189*4882a593Smuzhiyun 
190*4882a593Smuzhiyun     now.milliseconds = GetTimeInMillis();
191*4882a593Smuzhiyun     now.months = currentTime.months;
192*4882a593Smuzhiyun     if ((int) (now.milliseconds - currentTime.milliseconds) < 0)
193*4882a593Smuzhiyun         now.months++;
194*4882a593Smuzhiyun     for (pReq = pPending; pReq; pReq = pNext) {
195*4882a593Smuzhiyun         pNext = pReq->next;
196*4882a593Smuzhiyun         if (CompareTimeStamps(pReq->revive, now) == LATER)
197*4882a593Smuzhiyun             break;
198*4882a593Smuzhiyun         FreeResource(pReq->id, RT_NONE);
199*4882a593Smuzhiyun     }
200*4882a593Smuzhiyun     if (!pPending) {
201*4882a593Smuzhiyun         RemoveBlockAndWakeupHandlers(SertafiedBlockHandler,
202*4882a593Smuzhiyun                                      SertafiedWakeupHandler, (void *) 0);
203*4882a593Smuzhiyun         BlockHandlerRegistered = FALSE;
204*4882a593Smuzhiyun     }
205*4882a593Smuzhiyun }
206