105b261ecSmrg/*********************************************************** 205b261ecSmrg 305b261ecSmrgCopyright 1987, 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 2505b261ecSmrgCopyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. 2605b261ecSmrg 2705b261ecSmrg All Rights Reserved 2805b261ecSmrg 29f7df2e56SmrgPermission to use, copy, modify, and distribute this software and its 30f7df2e56Smrgdocumentation for any purpose and without fee is hereby granted, 3105b261ecSmrgprovided that the above copyright notice appear in all copies and that 32f7df2e56Smrgboth that copyright notice and this permission notice appear in 3305b261ecSmrgsupporting documentation, and that the name of Digital not be 3405b261ecSmrgused in advertising or publicity pertaining to distribution of the 35f7df2e56Smrgsoftware without specific, written prior permission. 3605b261ecSmrg 3705b261ecSmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 3805b261ecSmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 3905b261ecSmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 4005b261ecSmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 4105b261ecSmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 4205b261ecSmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 4305b261ecSmrgSOFTWARE. 4405b261ecSmrg 4505b261ecSmrg******************************************************************/ 4605b261ecSmrg 4705b261ecSmrg/***************************************************************** 4805b261ecSmrg * OS Dependent input routines: 4905b261ecSmrg * 5005b261ecSmrg * WaitForSomething 5105b261ecSmrg * TimerForce, TimerSet, TimerCheck, TimerFree 5205b261ecSmrg * 5305b261ecSmrg *****************************************************************/ 5405b261ecSmrg 555bd42952Smrg#include <X11/Xpoll.h> 565bd42952Smrg 5705b261ecSmrg#ifdef HAVE_DIX_CONFIG_H 5805b261ecSmrg#include <dix-config.h> 5905b261ecSmrg#endif 6005b261ecSmrg 6105b261ecSmrg#ifdef WIN32 6205b261ecSmrg#include <X11/Xwinsock.h> 6305b261ecSmrg#endif 64f7df2e56Smrg#include <X11/Xos.h> /* for strings, fcntl, time */ 6505b261ecSmrg#include <errno.h> 6605b261ecSmrg#include <stdio.h> 6705b261ecSmrg#include <X11/X.h> 6805b261ecSmrg#include "misc.h" 6905b261ecSmrg 7005b261ecSmrg#include "osdep.h" 7105b261ecSmrg#include "dixstruct.h" 7205b261ecSmrg#include "opaque.h" 7305b261ecSmrg#ifdef DPMSExtension 7405b261ecSmrg#include "dpmsproc.h" 7505b261ecSmrg#endif 76f7df2e56Smrg#include "busfault.h" 7705b261ecSmrg 7805b261ecSmrg#ifdef WIN32 7905b261ecSmrg/* Error codes from windows sockets differ from fileio error codes */ 8005b261ecSmrg#undef EINTR 8105b261ecSmrg#define EINTR WSAEINTR 8205b261ecSmrg#undef EINVAL 8305b261ecSmrg#define EINVAL WSAEINVAL 8405b261ecSmrg#undef EBADF 8505b261ecSmrg#define EBADF WSAENOTSOCK 86f7df2e56Smrg/* Windows select does not set errno. Use GetErrno as wrapper for 8705b261ecSmrg WSAGetLastError */ 8805b261ecSmrg#define GetErrno WSAGetLastError 8905b261ecSmrg#else 9005b261ecSmrg/* This is just a fallback to errno to hide the differences between unix and 9105b261ecSmrg Windows in the code */ 9205b261ecSmrg#define GetErrno() errno 9305b261ecSmrg#endif 9405b261ecSmrg 9505b261ecSmrg#ifdef DPMSExtension 966747b715Smrg#include <X11/extensions/dpmsconst.h> 9705b261ecSmrg#endif 9805b261ecSmrg 9905b261ecSmrgstruct _OsTimerRec { 1007e31ba66Smrg struct xorg_list list; 101f7df2e56Smrg CARD32 expires; 102f7df2e56Smrg CARD32 delta; 103f7df2e56Smrg OsTimerCallback callback; 104f7df2e56Smrg void *arg; 10505b261ecSmrg}; 10605b261ecSmrg 1077e31ba66Smrgstatic void DoTimer(OsTimerPtr timer, CARD32 now); 1087e31ba66Smrgstatic void DoTimers(CARD32 now); 10905b261ecSmrgstatic void CheckAllTimers(void); 1107e31ba66Smrgstatic volatile struct xorg_list timers; 1117e31ba66Smrg 1127e31ba66Smrgstatic inline OsTimerPtr 1137e31ba66Smrgfirst_timer(void) 1147e31ba66Smrg{ 1157e31ba66Smrg /* inline xorg_list_is_empty which can't handle volatile */ 1167e31ba66Smrg if (timers.next == &timers) 1177e31ba66Smrg return NULL; 1187e31ba66Smrg return xorg_list_first_entry(&timers, struct _OsTimerRec, list); 1197e31ba66Smrg} 1207e31ba66Smrg 1217e31ba66Smrg/* 1227e31ba66Smrg * Compute timeout until next timer, running 1237e31ba66Smrg * any expired timers 1247e31ba66Smrg */ 1257e31ba66Smrgstatic int 1267e31ba66Smrgcheck_timers(void) 1277e31ba66Smrg{ 1287e31ba66Smrg OsTimerPtr timer; 1297e31ba66Smrg 1307e31ba66Smrg if ((timer = first_timer()) != NULL) { 1317e31ba66Smrg CARD32 now = GetTimeInMillis(); 1327e31ba66Smrg int timeout = timer->expires - now; 1337e31ba66Smrg 1347e31ba66Smrg if (timeout <= 0) { 1357e31ba66Smrg DoTimers(now); 1367e31ba66Smrg } else { 1377e31ba66Smrg /* Make sure the timeout is sane */ 1387e31ba66Smrg if (timeout < timer->delta + 250) 1397e31ba66Smrg return timeout; 1407e31ba66Smrg 1417e31ba66Smrg /* time has rewound. reset the timers. */ 1427e31ba66Smrg CheckAllTimers(); 1437e31ba66Smrg } 1447e31ba66Smrg 1457e31ba66Smrg return 0; 1467e31ba66Smrg } 1477e31ba66Smrg return -1; 1487e31ba66Smrg} 14905b261ecSmrg 15005b261ecSmrg/***************** 15105b261ecSmrg * WaitForSomething: 15205b261ecSmrg * Make the server suspend until there is 15305b261ecSmrg * 1. data from clients or 15405b261ecSmrg * 2. input events available or 15505b261ecSmrg * 3. ddx notices something of interest (graphics 15605b261ecSmrg * queue ready, etc.) or 15705b261ecSmrg * 4. clients that have buffered replies/events are ready 15805b261ecSmrg * 15905b261ecSmrg * If the time between INPUT events is 16005b261ecSmrg * greater than ScreenSaverTime, the display is turned off (or 16105b261ecSmrg * saved, depending on the hardware). So, WaitForSomething() 16205b261ecSmrg * has to handle this also (that's why the select() has a timeout. 16305b261ecSmrg * For more info on ClientsWithInput, see ReadRequestFromClient(). 16405b261ecSmrg * pClientsReady is an array to store ready client->index values into. 16505b261ecSmrg *****************/ 16605b261ecSmrg 1677e31ba66SmrgBool 1687e31ba66SmrgWaitForSomething(Bool are_ready) 16905b261ecSmrg{ 17005b261ecSmrg int i; 1717e31ba66Smrg int timeout; 1727e31ba66Smrg int pollerr; 1737e31ba66Smrg static Bool were_ready; 1747e31ba66Smrg Bool timer_is_running; 1757e31ba66Smrg 1767e31ba66Smrg timer_is_running = were_ready; 1777e31ba66Smrg 1787e31ba66Smrg if (were_ready && !are_ready) { 1797e31ba66Smrg timer_is_running = FALSE; 1809ace9065Smrg SmartScheduleStopTimer(); 1817e31ba66Smrg } 1827e31ba66Smrg 1837e31ba66Smrg were_ready = FALSE; 1849ace9065Smrg 185f7df2e56Smrg#ifdef BUSFAULT 186f7df2e56Smrg busfault_check(); 187f7df2e56Smrg#endif 188f7df2e56Smrg 189f7df2e56Smrg /* We need a while loop here to handle 19005b261ecSmrg crashed connections and the screen saver timeout */ 191f7df2e56Smrg while (1) { 192f7df2e56Smrg /* deal with any blocked jobs */ 1937e31ba66Smrg if (workQueue) { 194f7df2e56Smrg ProcessWorkQueue(); 195f7df2e56Smrg } 196f7df2e56Smrg 1977e31ba66Smrg timeout = check_timers(); 1987e31ba66Smrg are_ready = clients_are_ready(); 19905b261ecSmrg 2007e31ba66Smrg if (are_ready) 2017e31ba66Smrg timeout = 0; 2027e31ba66Smrg 2037e31ba66Smrg BlockHandler(&timeout); 204f7df2e56Smrg if (NewOutputPending) 205f7df2e56Smrg FlushAllOutput(); 206f7df2e56Smrg /* keep this check close to select() call to minimize race */ 207f7df2e56Smrg if (dispatchException) 208f7df2e56Smrg i = -1; 2097e31ba66Smrg else 2107e31ba66Smrg i = ospoll_wait(server_poll, timeout); 2117e31ba66Smrg pollerr = GetErrno(); 2127e31ba66Smrg WakeupHandler(i); 213f7df2e56Smrg if (i <= 0) { /* An error or timeout occurred */ 214f7df2e56Smrg if (dispatchException) 2157e31ba66Smrg return FALSE; 216f7df2e56Smrg if (i < 0) { 2177e31ba66Smrg if (pollerr != EINTR && !ETEST(pollerr)) { 2187e31ba66Smrg ErrorF("WaitForSomething(): poll: %s\n", 2197e31ba66Smrg strerror(pollerr)); 220f7df2e56Smrg } 221f7df2e56Smrg } 2227e31ba66Smrg } else 2237e31ba66Smrg are_ready = clients_are_ready(); 224f7df2e56Smrg 2257e31ba66Smrg if (InputCheckPending()) 2267e31ba66Smrg return FALSE; 22705b261ecSmrg 2287e31ba66Smrg if (are_ready) { 2297e31ba66Smrg were_ready = TRUE; 2307e31ba66Smrg if (!timer_is_running) 2317e31ba66Smrg SmartScheduleStartTimer(); 2327e31ba66Smrg return TRUE; 233f7df2e56Smrg } 23405b261ecSmrg } 2357e31ba66Smrg} 23605b261ecSmrg 2377e31ba66Smrgvoid 2387e31ba66SmrgAdjustWaitForDelay(void *waitTime, int newdelay) 2397e31ba66Smrg{ 2407e31ba66Smrg int *timeoutp = waitTime; 2417e31ba66Smrg int timeout = *timeoutp; 2429ace9065Smrg 2437e31ba66Smrg if (timeout < 0 || newdelay < timeout) 2447e31ba66Smrg *timeoutp = newdelay; 2457e31ba66Smrg} 2469ace9065Smrg 2477e31ba66Smrgstatic inline Bool timer_pending(OsTimerPtr timer) { 2487e31ba66Smrg return !xorg_list_is_empty(&timer->list); 24905b261ecSmrg} 25005b261ecSmrg 25105b261ecSmrg/* If time has rewound, re-run every affected timer. 25205b261ecSmrg * Timers might drop out of the list, so we have to restart every time. */ 25305b261ecSmrgstatic void 25405b261ecSmrgCheckAllTimers(void) 25505b261ecSmrg{ 25605b261ecSmrg OsTimerPtr timer; 25705b261ecSmrg CARD32 now; 25805b261ecSmrg 2597e31ba66Smrg input_lock(); 260f7df2e56Smrg start: 26105b261ecSmrg now = GetTimeInMillis(); 26205b261ecSmrg 2637e31ba66Smrg xorg_list_for_each_entry(timer, &timers, list) { 26405b261ecSmrg if (timer->expires - now > timer->delta + 250) { 2657e31ba66Smrg DoTimer(timer, now); 26605b261ecSmrg goto start; 26705b261ecSmrg } 26805b261ecSmrg } 2697e31ba66Smrg input_unlock(); 27005b261ecSmrg} 27105b261ecSmrg 27205b261ecSmrgstatic void 2737e31ba66SmrgDoTimer(OsTimerPtr timer, CARD32 now) 27405b261ecSmrg{ 27505b261ecSmrg CARD32 newTime; 27605b261ecSmrg 2777e31ba66Smrg xorg_list_del(&timer->list); 278f7df2e56Smrg newTime = (*timer->callback) (timer, now, timer->arg); 27905b261ecSmrg if (newTime) 280f7df2e56Smrg TimerSet(timer, 0, newTime, timer->callback, timer->arg); 28105b261ecSmrg} 28205b261ecSmrg 2837e31ba66Smrgstatic void 2847e31ba66SmrgDoTimers(CARD32 now) 2857e31ba66Smrg{ 2867e31ba66Smrg OsTimerPtr timer; 2877e31ba66Smrg 2887e31ba66Smrg input_lock(); 2897e31ba66Smrg while ((timer = first_timer())) { 2907e31ba66Smrg if ((int) (timer->expires - now) > 0) 2917e31ba66Smrg break; 2927e31ba66Smrg DoTimer(timer, now); 2937e31ba66Smrg } 2947e31ba66Smrg input_unlock(); 2957e31ba66Smrg} 2967e31ba66Smrg 2976747b715SmrgOsTimerPtr 298f7df2e56SmrgTimerSet(OsTimerPtr timer, int flags, CARD32 millis, 299f7df2e56Smrg OsTimerCallback func, void *arg) 30005b261ecSmrg{ 3015a112b11Smrg OsTimerPtr existing; 30205b261ecSmrg CARD32 now = GetTimeInMillis(); 30305b261ecSmrg 304f7df2e56Smrg if (!timer) { 3057e31ba66Smrg timer = calloc(1, sizeof(struct _OsTimerRec)); 306f7df2e56Smrg if (!timer) 307f7df2e56Smrg return NULL; 3087e31ba66Smrg xorg_list_init(&timer->list); 30905b261ecSmrg } 310f7df2e56Smrg else { 3117e31ba66Smrg input_lock(); 3127e31ba66Smrg if (timer_pending(timer)) { 3137e31ba66Smrg xorg_list_del(&timer->list); 3147e31ba66Smrg if (flags & TimerForceOld) 3157e31ba66Smrg (void) (*timer->callback) (timer, now, timer->arg); 316f7df2e56Smrg } 3177e31ba66Smrg input_unlock(); 31805b261ecSmrg } 31905b261ecSmrg if (!millis) 320f7df2e56Smrg return timer; 32105b261ecSmrg if (flags & TimerAbsolute) { 32205b261ecSmrg timer->delta = millis - now; 32305b261ecSmrg } 32405b261ecSmrg else { 32505b261ecSmrg timer->delta = millis; 326f7df2e56Smrg millis += now; 32705b261ecSmrg } 32805b261ecSmrg timer->expires = millis; 32905b261ecSmrg timer->callback = func; 33005b261ecSmrg timer->arg = arg; 3317e31ba66Smrg input_lock(); 3327e31ba66Smrg 3337e31ba66Smrg /* Sort into list */ 3345a112b11Smrg xorg_list_for_each_entry(existing, &timers, list) 3357e31ba66Smrg if ((int) (existing->expires - millis) > 0) 3367e31ba66Smrg break; 3377e31ba66Smrg /* This even works at the end of the list -- existing->list will be timers */ 3385a112b11Smrg xorg_list_append(&timer->list, &existing->list); 3397e31ba66Smrg 3407e31ba66Smrg /* Check to see if the timer is ready to run now */ 3417e31ba66Smrg if ((int) (millis - now) <= 0) 3427e31ba66Smrg DoTimer(timer, now); 3437e31ba66Smrg 3447e31ba66Smrg input_unlock(); 34505b261ecSmrg return timer; 34605b261ecSmrg} 34705b261ecSmrg 34805b261ecSmrgBool 34905b261ecSmrgTimerForce(OsTimerPtr timer) 35005b261ecSmrg{ 3517e31ba66Smrg int pending; 3527e31ba66Smrg 3537e31ba66Smrg input_lock(); 3547e31ba66Smrg pending = timer_pending(timer); 3557e31ba66Smrg if (pending) 3567e31ba66Smrg DoTimer(timer, GetTimeInMillis()); 3577e31ba66Smrg input_unlock(); 3587e31ba66Smrg return pending; 35905b261ecSmrg} 36005b261ecSmrg 3616747b715Smrgvoid 36205b261ecSmrgTimerCancel(OsTimerPtr timer) 36305b261ecSmrg{ 36405b261ecSmrg if (!timer) 365f7df2e56Smrg return; 3667e31ba66Smrg input_lock(); 3677e31ba66Smrg xorg_list_del(&timer->list); 3687e31ba66Smrg input_unlock(); 36905b261ecSmrg} 37005b261ecSmrg 3716747b715Smrgvoid 37205b261ecSmrgTimerFree(OsTimerPtr timer) 37305b261ecSmrg{ 37405b261ecSmrg if (!timer) 375f7df2e56Smrg return; 37605b261ecSmrg TimerCancel(timer); 3776747b715Smrg free(timer); 37805b261ecSmrg} 37905b261ecSmrg 38005b261ecSmrgvoid 38105b261ecSmrgTimerCheck(void) 38205b261ecSmrg{ 3837e31ba66Smrg DoTimers(GetTimeInMillis()); 38405b261ecSmrg} 38505b261ecSmrg 38605b261ecSmrgvoid 38705b261ecSmrgTimerInit(void) 38805b261ecSmrg{ 3897e31ba66Smrg static Bool been_here; 3907e31ba66Smrg OsTimerPtr timer, tmp; 3917e31ba66Smrg 3927e31ba66Smrg if (!been_here) { 3937e31ba66Smrg been_here = TRUE; 3947e31ba66Smrg xorg_list_init((struct xorg_list*) &timers); 3957e31ba66Smrg } 39605b261ecSmrg 3977e31ba66Smrg xorg_list_for_each_entry_safe(timer, tmp, &timers, list) { 3987e31ba66Smrg xorg_list_del(&timer->list); 399f7df2e56Smrg free(timer); 40005b261ecSmrg } 40105b261ecSmrg} 40205b261ecSmrg 40305b261ecSmrg#ifdef DPMSExtension 40405b261ecSmrg 40505b261ecSmrg#define DPMS_CHECK_MODE(mode,time)\ 40605b261ecSmrg if (time > 0 && DPMSPowerLevel < mode && timeout >= time)\ 4074642e01fSmrg DPMSSet(serverClient, mode); 40805b261ecSmrg 40905b261ecSmrg#define DPMS_CHECK_TIMEOUT(time)\ 41005b261ecSmrg if (time > 0 && (time - timeout) > 0)\ 41105b261ecSmrg return time - timeout; 41205b261ecSmrg 41305b261ecSmrgstatic CARD32 41405b261ecSmrgNextDPMSTimeout(INT32 timeout) 41505b261ecSmrg{ 41605b261ecSmrg /* 41705b261ecSmrg * Return the amount of time remaining until we should set 41805b261ecSmrg * the next power level. Fallthroughs are intentional. 41905b261ecSmrg */ 420f7df2e56Smrg switch (DPMSPowerLevel) { 421f7df2e56Smrg case DPMSModeOn: 422f7df2e56Smrg DPMS_CHECK_TIMEOUT(DPMSStandbyTime) 423d566a54bSmrg /* fallthrough */ 424f7df2e56Smrg case DPMSModeStandby: 425f7df2e56Smrg DPMS_CHECK_TIMEOUT(DPMSSuspendTime) 426d566a54bSmrg /* fallthrough */ 427f7df2e56Smrg case DPMSModeSuspend: 428f7df2e56Smrg DPMS_CHECK_TIMEOUT(DPMSOffTime) 429d566a54bSmrg /* fallthrough */ 430f7df2e56Smrg default: /* DPMSModeOff */ 431f7df2e56Smrg return 0; 43205b261ecSmrg } 43305b261ecSmrg} 434f7df2e56Smrg#endif /* DPMSExtension */ 43505b261ecSmrg 43605b261ecSmrgstatic CARD32 437f7df2e56SmrgScreenSaverTimeoutExpire(OsTimerPtr timer, CARD32 now, void *arg) 43805b261ecSmrg{ 439f7df2e56Smrg INT32 timeout = now - LastEventTime(XIAllDevices).milliseconds; 44005b261ecSmrg CARD32 nextTimeout = 0; 44105b261ecSmrg 44205b261ecSmrg#ifdef DPMSExtension 44305b261ecSmrg /* 44405b261ecSmrg * Check each mode lowest to highest, since a lower mode can 44505b261ecSmrg * have the same timeout as a higher one. 44605b261ecSmrg */ 447f7df2e56Smrg if (DPMSEnabled) { 448f7df2e56Smrg DPMS_CHECK_MODE(DPMSModeOff, DPMSOffTime) 449f7df2e56Smrg DPMS_CHECK_MODE(DPMSModeSuspend, DPMSSuspendTime) 450f7df2e56Smrg DPMS_CHECK_MODE(DPMSModeStandby, DPMSStandbyTime) 45105b261ecSmrg 452f7df2e56Smrg nextTimeout = NextDPMSTimeout(timeout); 45305b261ecSmrg } 45405b261ecSmrg 45505b261ecSmrg /* 45605b261ecSmrg * Only do the screensaver checks if we're not in a DPMS 45705b261ecSmrg * power saving mode 45805b261ecSmrg */ 45905b261ecSmrg if (DPMSPowerLevel != DPMSModeOn) 460f7df2e56Smrg return nextTimeout; 461f7df2e56Smrg#endif /* DPMSExtension */ 46205b261ecSmrg 46305b261ecSmrg if (!ScreenSaverTime) 464f7df2e56Smrg return nextTimeout; 46505b261ecSmrg 466f7df2e56Smrg if (timeout < ScreenSaverTime) { 467f7df2e56Smrg return nextTimeout > 0 ? 468f7df2e56Smrg min(ScreenSaverTime - timeout, nextTimeout) : 469f7df2e56Smrg ScreenSaverTime - timeout; 47005b261ecSmrg } 47105b261ecSmrg 472f7df2e56Smrg ResetOsBuffers(); /* not ideal, but better than nothing */ 4734642e01fSmrg dixSaveScreens(serverClient, SCREEN_SAVER_ON, ScreenSaverActive); 47405b261ecSmrg 475f7df2e56Smrg if (ScreenSaverInterval > 0) { 476f7df2e56Smrg nextTimeout = nextTimeout > 0 ? 477f7df2e56Smrg min(ScreenSaverInterval, nextTimeout) : ScreenSaverInterval; 47805b261ecSmrg } 47905b261ecSmrg 48005b261ecSmrg return nextTimeout; 48105b261ecSmrg} 48205b261ecSmrg 48305b261ecSmrgstatic OsTimerPtr ScreenSaverTimer = NULL; 48405b261ecSmrg 48505b261ecSmrgvoid 48605b261ecSmrgFreeScreenSaverTimer(void) 48705b261ecSmrg{ 48805b261ecSmrg if (ScreenSaverTimer) { 489f7df2e56Smrg TimerFree(ScreenSaverTimer); 490f7df2e56Smrg ScreenSaverTimer = NULL; 49105b261ecSmrg } 49205b261ecSmrg} 49305b261ecSmrg 49405b261ecSmrgvoid 49505b261ecSmrgSetScreenSaverTimer(void) 49605b261ecSmrg{ 49705b261ecSmrg CARD32 timeout = 0; 49805b261ecSmrg 49905b261ecSmrg#ifdef DPMSExtension 500f7df2e56Smrg if (DPMSEnabled) { 501f7df2e56Smrg /* 502f7df2e56Smrg * A higher DPMS level has a timeout that's either less 503f7df2e56Smrg * than or equal to that of a lower DPMS level. 504f7df2e56Smrg */ 505f7df2e56Smrg if (DPMSStandbyTime > 0) 506f7df2e56Smrg timeout = DPMSStandbyTime; 507f7df2e56Smrg 508f7df2e56Smrg else if (DPMSSuspendTime > 0) 509f7df2e56Smrg timeout = DPMSSuspendTime; 510f7df2e56Smrg 511f7df2e56Smrg else if (DPMSOffTime > 0) 512f7df2e56Smrg timeout = DPMSOffTime; 51305b261ecSmrg } 51405b261ecSmrg#endif 51505b261ecSmrg 516f7df2e56Smrg if (ScreenSaverTime > 0) { 517f7df2e56Smrg timeout = timeout > 0 ? min(ScreenSaverTime, timeout) : ScreenSaverTime; 51805b261ecSmrg } 51905b261ecSmrg 52005b261ecSmrg#ifdef SCREENSAVER 52105b261ecSmrg if (timeout && !screenSaverSuspended) { 52205b261ecSmrg#else 52305b261ecSmrg if (timeout) { 52405b261ecSmrg#endif 525f7df2e56Smrg ScreenSaverTimer = TimerSet(ScreenSaverTimer, 0, timeout, 526f7df2e56Smrg ScreenSaverTimeoutExpire, NULL); 52705b261ecSmrg } 52805b261ecSmrg else if (ScreenSaverTimer) { 529f7df2e56Smrg FreeScreenSaverTimer(); 53005b261ecSmrg } 53105b261ecSmrg} 532