1 /***********************************************************
3 Copyright 1987, 1998 The Open Group
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
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
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.
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.
26 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
30 Permission to use, copy, modify, and distribute this software and its
31 documentation for any purpose and without fee is hereby granted,
32 provided that the above copyright notice appear in all copies and that
33 both that copyright notice and this permission notice appear in
34 supporting documentation, and that the name of Digital not be
35 used in advertising or publicity pertaining to distribution of the
36 software without specific, written prior permission.
38 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
39 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
40 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
41 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
42 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
43 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
46 ******************************************************************/
49 /*****************************************************************
50 * OS Dependent input routines:
53 * TimerForce, TimerSet, TimerCheck, TimerFree
55 *****************************************************************/
57 #ifdef HAVE_DIX_CONFIG_H
58 #include <dix-config.h>
62 #include <X11/Xwinsock.h>
64 #include <X11/Xos.h> /* for strings, fcntl, time */
71 #include <X11/Xpoll.h>
72 #include "dixstruct.h"
79 /* Error codes from windows sockets differ from fileio error codes */
81 #define EINTR WSAEINTR
83 #define EINVAL WSAEINVAL
85 #define EBADF WSAENOTSOCK
86 /* Windows select does not set errno. Use GetErrno as wrapper for
88 #define GetErrno WSAGetLastError
90 /* This is just a fallback to errno to hide the differences between unix and
91 Windows in the code */
92 #define GetErrno() errno
95 /* modifications by raphael */
113 #include <X11/extensions/dpms.h>
120 OsTimerCallback callback
;
124 static void DoTimer(OsTimerPtr timer
, CARD32 now
, OsTimerPtr
*prev
);
125 static void CheckAllTimers(void);
126 static OsTimerPtr timers
= NULL
;
130 * Make the server suspend until there is
131 * 1. data from clients or
132 * 2. input events available or
133 * 3. ddx notices something of interest (graphics
134 * queue ready, etc.) or
135 * 4. clients that have buffered replies/events are ready
137 * If the time between INPUT events is
138 * greater than ScreenSaverTime, the display is turned off (or
139 * saved, depending on the hardware). So, WaitForSomething()
140 * has to handle this also (that's why the select() has a timeout.
141 * For more info on ClientsWithInput, see ReadRequestFromClient().
142 * pClientsReady is an array to store ready client->index values into.
146 WaitForSomething(int *pClientsReady
)
149 struct timeval waittime
, *wt
;
151 fd_set clientsReadable
;
152 fd_set clientsWritable
;
156 fd_set devicesReadable
;
158 #ifdef SMART_SCHEDULE
159 Bool someReady
= FALSE
;
162 FD_ZERO(&clientsReadable
);
164 /* We need a while loop here to handle
165 crashed connections and the screen saver timeout */
168 /* deal with any blocked jobs */
171 if (XFD_ANYSET (&ClientsWithInput
))
173 #ifdef SMART_SCHEDULE
174 if (!SmartScheduleDisable
)
178 waittime
.tv_usec
= 0;
184 XFD_COPYSET (&ClientsWithInput
, &clientsReadable
);
188 #ifdef SMART_SCHEDULE
191 XFD_COPYSET(&AllSockets
, &LastSelectMask
);
192 XFD_UNSET(&LastSelectMask
, &ClientsWithInput
);
200 now
= GetTimeInMillis();
201 timeout
= timers
->expires
- now
;
202 if (timeout
> 0 && timeout
> timers
->delta
+ 250) {
203 /* time has rewound. reset the timers. */
208 timeout
= timers
->expires
- now
;
211 waittime
.tv_sec
= timeout
/ MILLI_PER_SECOND
;
212 waittime
.tv_usec
= (timeout
% MILLI_PER_SECOND
) *
213 (1000000 / MILLI_PER_SECOND
);
217 XFD_COPYSET(&AllSockets
, &LastSelectMask
);
218 #ifdef SMART_SCHEDULE
220 SmartScheduleIdle
= TRUE
;
222 BlockHandler((pointer
)&wt
, (pointer
)&LastSelectMask
);
223 if (NewOutputPending
)
225 /* keep this check close to select() call to minimize race */
226 if (dispatchException
)
228 else if (AnyClientsWriteBlocked
)
230 XFD_COPYSET(&ClientsWriteBlocked
, &clientsWritable
);
231 i
= Select (MaxClients
, &LastSelectMask
, &clientsWritable
, NULL
, wt
);
235 i
= Select (MaxClients
, &LastSelectMask
, NULL
, NULL
, wt
);
237 selecterr
= GetErrno();
238 WakeupHandler(i
, (pointer
)&LastSelectMask
);
239 #ifdef SMART_SCHEDULE
242 SmartScheduleIdle
= FALSE
;
243 SmartScheduleIdleCount
= 0;
244 if (SmartScheduleTimerStopped
)
245 (void) SmartScheduleStartTimer ();
248 if (i
<= 0) /* An error or timeout occurred */
250 if (dispatchException
)
254 if (selecterr
== EBADF
) /* Some client disconnected */
257 if (! XFD_ANYSET (&AllClients
))
260 else if (selecterr
== EINVAL
)
262 FatalError("WaitForSomething(): select: errno=%d\n",
265 else if (selecterr
!= EINTR
)
267 ErrorF("WaitForSomething(): select: errno=%d\n",
271 #ifdef SMART_SCHEDULE
275 * If no-one else is home, bail quickly
277 XFD_COPYSET(&ClientsWithInput
, &LastSelectMask
);
278 XFD_COPYSET(&ClientsWithInput
, &clientsReadable
);
282 if (*checkForInput
[0] != *checkForInput
[1])
288 now
= GetTimeInMillis();
289 if ((int) (timers
->expires
- now
) <= 0)
292 while (timers
&& (int) (timers
->expires
- now
) <= 0)
293 DoTimer(timers
, now
, &timers
);
303 if (*checkForInput
[0] == *checkForInput
[1]) {
307 now
= GetTimeInMillis();
308 if ((int) (timers
->expires
- now
) <= 0)
311 while (timers
&& (int) (timers
->expires
- now
) <= 0)
312 DoTimer(timers
, now
, &timers
);
318 #ifdef SMART_SCHEDULE
320 XFD_ORSET(&LastSelectMask
, &ClientsWithInput
, &LastSelectMask
);
322 if (AnyClientsWriteBlocked
&& XFD_ANYSET (&clientsWritable
))
324 NewOutputPending
= TRUE
;
325 XFD_ORSET(&OutputPending
, &clientsWritable
, &OutputPending
);
326 XFD_UNSET(&ClientsWriteBlocked
, &clientsWritable
);
327 if (! XFD_ANYSET(&ClientsWriteBlocked
))
328 AnyClientsWriteBlocked
= FALSE
;
331 XFD_ANDSET(&devicesReadable
, &LastSelectMask
, &EnabledDevices
);
332 XFD_ANDSET(&clientsReadable
, &LastSelectMask
, &AllClients
);
333 XFD_ANDSET(&tmp_set
, &LastSelectMask
, &WellKnownConnections
);
334 if (XFD_ANYSET(&tmp_set
))
335 QueueWorkProc(EstablishNewConnections
, NULL
,
336 (pointer
)&LastSelectMask
);
338 if (XFD_ANYSET (&devicesReadable
) || XFD_ANYSET (&clientsReadable
))
341 /* Windows keyboard and mouse events are added to the input queue
342 in Block- and WakupHandlers. There is no device to check if
343 data is ready. So check here if new input is available */
344 if (*checkForInput
[0] != *checkForInput
[1])
351 if (XFD_ANYSET (&clientsReadable
))
354 for (i
=0; i
<howmany(XFD_SETSIZE
, NFDBITS
); i
++)
356 int highest_priority
= 0;
358 while (clientsReadable
.fds_bits
[i
])
360 int client_priority
, client_index
;
362 curclient
= ffs (clientsReadable
.fds_bits
[i
]) - 1;
363 client_index
= /* raphael: modified */
364 ConnectionTranslation
[curclient
+ (i
* (sizeof(fd_mask
) * 8))];
366 int highest_priority
= 0;
367 fd_set savedClientsReadable
;
368 XFD_COPYSET(&clientsReadable
, &savedClientsReadable
);
369 for (i
= 0; i
< XFD_SETCOUNT(&savedClientsReadable
); i
++)
371 int client_priority
, client_index
;
373 curclient
= XFD_FD(&savedClientsReadable
, i
);
374 client_index
= GetConnectionTranslation(curclient
);
377 /* We implement "strict" priorities.
378 * Only the highest priority client is returned to
379 * dix. If multiple clients at the same priority are
380 * ready, they are all returned. This means that an
381 * aggressive client could take over the server.
382 * This was not considered a big problem because
383 * aggressive clients can hose the server in so many
386 client_priority
= clients
[client_index
]->priority
;
387 if (nready
== 0 || client_priority
> highest_priority
)
389 /* Either we found the first client, or we found
390 * a client whose priority is greater than all others
391 * that have been found so far. Either way, we want
392 * to initialize the list of clients to contain just
395 pClientsReady
[0] = client_index
;
396 highest_priority
= client_priority
;
399 /* the following if makes sure that multiple same-priority
400 * clients get batched together
402 else if (client_priority
== highest_priority
)
405 pClientsReady
[nready
++] = client_index
;
408 clientsReadable
.fds_bits
[i
] &= ~(((fd_mask
)1L) << curclient
);
411 FD_CLR(curclient
, &clientsReadable
);
420 * This is not always a macro.
426 for (i
=0; i
<mskcnt
; i
++)
433 /* If time has rewound, re-run every affected timer.
434 * Timers might drop out of the list, so we have to restart every time. */
442 now
= GetTimeInMillis();
444 for (timer
= timers
; timer
; timer
= timer
->next
) {
445 if (timer
->expires
- now
> timer
->delta
+ 250) {
453 DoTimer(OsTimerPtr timer
, CARD32 now
, OsTimerPtr
*prev
)
459 newTime
= (*timer
->callback
)(timer
, now
, timer
->arg
);
461 TimerSet(timer
, 0, newTime
, timer
->callback
, timer
->arg
);
465 TimerSet(OsTimerPtr timer
, int flags
, CARD32 millis
,
466 OsTimerCallback func
, pointer arg
)
468 register OsTimerPtr
*prev
;
469 CARD32 now
= GetTimeInMillis();
473 timer
= (OsTimerPtr
)xalloc(sizeof(struct _OsTimerRec
));
479 for (prev
= &timers
; *prev
; prev
= &(*prev
)->next
)
484 if (flags
& TimerForceOld
)
485 (void)(*timer
->callback
)(timer
, now
, timer
->arg
);
492 if (flags
& TimerAbsolute
) {
493 timer
->delta
= millis
- now
;
496 timer
->delta
= millis
;
499 timer
->expires
= millis
;
500 timer
->callback
= func
;
502 if ((int) (millis
- now
) <= 0)
505 millis
= (*timer
->callback
)(timer
, now
, timer
->arg
);
510 *prev
&& (int) ((*prev
)->expires
- millis
) <= 0;
511 prev
= &(*prev
)->next
)
519 TimerForce(OsTimerPtr timer
)
523 for (prev
= &timers
; *prev
; prev
= &(*prev
)->next
)
527 DoTimer(timer
, GetTimeInMillis(), prev
);
536 TimerCancel(OsTimerPtr timer
)
542 for (prev
= &timers
; *prev
; prev
= &(*prev
)->next
)
553 TimerFree(OsTimerPtr timer
)
564 CARD32 now
= GetTimeInMillis();
566 while (timers
&& (int) (timers
->expires
- now
) <= 0)
567 DoTimer(timers
, now
, &timers
);
575 while ((timer
= timers
))
577 timers
= timer
->next
;
584 #define DPMS_CHECK_MODE(mode,time)\
585 if (time > 0 && DPMSPowerLevel < mode && timeout >= time)\
588 #define DPMS_CHECK_TIMEOUT(time)\
589 if (time > 0 && (time - timeout) > 0)\
590 return time - timeout;
593 NextDPMSTimeout(INT32 timeout
)
596 * Return the amount of time remaining until we should set
597 * the next power level. Fallthroughs are intentional.
599 switch (DPMSPowerLevel
)
602 DPMS_CHECK_TIMEOUT(DPMSStandbyTime
)
604 case DPMSModeStandby
:
605 DPMS_CHECK_TIMEOUT(DPMSSuspendTime
)
607 case DPMSModeSuspend
:
608 DPMS_CHECK_TIMEOUT(DPMSOffTime
)
610 default: /* DPMSModeOff */
614 #endif /* DPMSExtension */
617 ScreenSaverTimeoutExpire(OsTimerPtr timer
,CARD32 now
,pointer arg
)
619 INT32 timeout
= now
- lastDeviceEventTime
.milliseconds
;
620 CARD32 nextTimeout
= 0;
624 * Check each mode lowest to highest, since a lower mode can
625 * have the same timeout as a higher one.
629 DPMS_CHECK_MODE(DPMSModeOff
, DPMSOffTime
)
630 DPMS_CHECK_MODE(DPMSModeSuspend
, DPMSSuspendTime
)
631 DPMS_CHECK_MODE(DPMSModeStandby
, DPMSStandbyTime
)
633 nextTimeout
= NextDPMSTimeout(timeout
);
637 * Only do the screensaver checks if we're not in a DPMS
640 if (DPMSPowerLevel
!= DPMSModeOn
)
642 #endif /* DPMSExtension */
644 if (!ScreenSaverTime
)
647 if (timeout
< ScreenSaverTime
)
649 return nextTimeout
> 0 ?
650 min(ScreenSaverTime
- timeout
, nextTimeout
) :
651 ScreenSaverTime
- timeout
;
654 ResetOsBuffers(); /* not ideal, but better than nothing */
655 SaveScreens(SCREEN_SAVER_ON
, ScreenSaverActive
);
657 if (ScreenSaverInterval
> 0)
659 nextTimeout
= nextTimeout
> 0 ?
660 min(ScreenSaverInterval
, nextTimeout
) :
667 static OsTimerPtr ScreenSaverTimer
= NULL
;
670 FreeScreenSaverTimer(void)
672 if (ScreenSaverTimer
) {
673 TimerFree(ScreenSaverTimer
);
674 ScreenSaverTimer
= NULL
;
679 SetScreenSaverTimer(void)
687 * A higher DPMS level has a timeout that's either less
688 * than or equal to that of a lower DPMS level.
690 if (DPMSStandbyTime
> 0)
691 timeout
= DPMSStandbyTime
;
693 else if (DPMSSuspendTime
> 0)
694 timeout
= DPMSSuspendTime
;
696 else if (DPMSOffTime
> 0)
697 timeout
= DPMSOffTime
;
701 if (ScreenSaverTime
> 0)
703 timeout
= timeout
> 0 ?
704 min(ScreenSaverTime
, timeout
) :
709 if (timeout
&& !screenSaverSuspended
) {
713 ScreenSaverTimer
= TimerSet(ScreenSaverTimer
, 0, timeout
,
714 ScreenSaverTimeoutExpire
, NULL
);
716 else if (ScreenSaverTimer
) {
717 FreeScreenSaverTimer();