2740dc1937
V2: Moves InputCheckPending() into dix.h Bumps required version of xproto to 7.0.30 ================== WARNING: ThreadSanitizer: data race (pid=4943) Read of size 4 at 0x00010c4e3854 by thread T8: #0 WaitForSomething WaitFor.c:237 (X11.bin+0x00010049216c) #1 Dispatch dispatch.c:413 (X11.bin+0x000100352ed9) #2 dix_main main.c:287 (X11.bin+0x00010036e894) #3 server_thread quartzStartup.c:66 (X11.bin+0x000100039e63) Previous write of size 4 at 0x00010c4e3854 by thread T12 (mutexes: write M856, write M1976): #0 mieqEnqueue mieq.c:263 (X11.bin+0x000100448d14) #1 DarwinSendDDXEvent darwinEvents.c:641 (X11.bin+0x000100033613) #2 DarwinProcessFDAdditionQueue_thread darwinEvents.c:338 (X11.bin+0x000100032039) Location is global 'miEventQueue' at 0x00010c4e3850 (X11.bin+0x0001005ab854) Mutex M856 (0x00010c4c8c80) created at: #0 pthread_mutex_lock <null>:144 (libclang_rt.tsan_osx_dynamic.dylib+0x0000000321fe) #1 DarwinListenOnOpenFD darwinEvents.c:300 (X11.bin+0x000100031607) #2 socket_handoff bundle-main.c:288 (X11.bin+0x000100002b40) #3 __do_request_fd_handoff_socket_block_invoke bundle-main.c:379 (X11.bin+0x0001000029ba) #4 __tsan::invoke_and_release_block(void*) <null>:144 (libclang_rt.tsan_osx_dynamic.dylib+0x00000005d97b) #5 _dispatch_client_callout <null>:33 (libdispatch.dylib+0x0000000020ef) Mutex M1976 (0x00010c4e3d68) created at: #0 pthread_mutex_init <null>:144 (libclang_rt.tsan_osx_dynamic.dylib+0x0000000253c3) #1 input_lock inputthread.c:103 (X11.bin+0x00010049fd10) #2 TimerSet WaitFor.c:343 (X11.bin+0x0001004926c2) #3 RootlessQueueRedisplay rootlessScreen.c:594 (X11.bin+0x000100065d7f) #4 RootlessInstallColormap rootlessScreen.c:514 (X11.bin+0x000100069f1a) #5 miSpriteInstallColormap misprite.c:562 (X11.bin+0x000100467095) #6 miCreateDefColormap micmap.c:270 (X11.bin+0x000100440399) #7 DarwinScreenInit darwin.c:285 (X11.bin+0x0001000303bb) #8 AddScreen dispatch.c:3908 (X11.bin+0x00010036c417) #9 InitOutput darwin.c:671 (X11.bin+0x00010002fdeb) #10 dix_main main.c:197 (X11.bin+0x00010036e228) #11 server_thread quartzStartup.c:66 (X11.bin+0x000100039e63) Thread T8 (tid=4198779, running) created by main thread at: #0 pthread_create <null>:144 (libclang_rt.tsan_osx_dynamic.dylib+0x000000024490) #1 create_thread quartzStartup.c:78 (X11.bin+0x000100039dad) #2 QuartzInitServer quartzStartup.c:95 (X11.bin+0x000100039c16) #3 X11ApplicationMain X11Application.m:1238 (X11.bin+0x00010001cde4) #4 X11ControllerMain X11Controller.m:984 (X11.bin+0x00010002a642) #5 server_main quartzStartup.c:136 (X11.bin+0x00010003a03b) #6 do_start_x11_server bundle-main.c:436 (X11.bin+0x000100002eb5) #7 _Xstart_x11_server mach_startupServer.c:189 (X11.bin+0x000100004e99) #8 mach_startup_server mach_startupServer.c:399 (X11.bin+0x000100005734) #9 mach_msg_server mach_msg.c:563 (libsystem_kernel.dylib+0x000000012186) #10 start <null>:29 (libdyld.dylib+0x000000005254) Thread T12 (tid=4198797, running) created by thread T8 at: #0 pthread_create <null>:144 (libclang_rt.tsan_osx_dynamic.dylib+0x000000024490) #1 create_thread darwinEvents.c:121 (X11.bin+0x000100031ecf) #2 DarwinEQInit darwinEvents.c:365 (X11.bin+0x000100031860) #3 InitInput darwin.c:571 (X11.bin+0x00010002ea09) #4 dix_main main.c:261 (X11.bin+0x00010036e7ce) #5 server_thread quartzStartup.c:66 (X11.bin+0x000100039e63) SUMMARY: ThreadSanitizer: data race WaitFor.c:237 in WaitForSomething ================== ================== WARNING: ThreadSanitizer: data race (pid=22841) Write of size 4 at 0x000105bbd864 by main thread (mutexes: write M1945): #0 mieqEnqueue mieq.c:263 (X11.bin+0x000100448cf4) #1 DarwinSendDDXEvent darwinEvents.c:642 (X11.bin+0x000100033693) #2 -[X11Controller set_window_menu:] X11Controller.m:275 (X11.bin+0x0001000222fd) #3 -[X11Application set_window_menu:] X11Application.m:486 (X11.bin+0x000100018b44) #4 -[X11Application handleMachMessage:] X11Application.m:177 (X11.bin+0x000100016678) #5 __NSFireMachPort <null>:69 (Foundation+0x00000009b62b) #6 X11ControllerMain X11Controller.m:984 (X11.bin+0x00010002a5f2) #7 server_main quartzStartup.c:136 (X11.bin+0x000100039ffb) #8 do_start_x11_server bundle-main.c:436 (X11.bin+0x000100002e65) #9 _Xstart_x11_server mach_startupServer.c:189 (X11.bin+0x000100004e49) #10 mach_startup_server mach_startupServer.c:399 (X11.bin+0x0001000056e4) #11 mach_msg_server mach_msg.c:563 (libsystem_kernel.dylib+0x000000012186) #12 start <null>:29 (libdyld.dylib+0x000000005254) Previous read of size 4 at 0x000105bbd864 by thread T7: #0 Dispatch dispatch.c:434 (X11.bin+0x000100352fc8) #1 dix_main main.c:287 (X11.bin+0x00010036e874) #2 server_thread quartzStartup.c:66 (X11.bin+0x000100039e23) Location is global 'miEventQueue' at 0x000105bbd860 (X11.bin+0x0001005ab864) Mutex M1945 (0x000105bbdd78) created at: #0 pthread_mutex_init <null>:144 (libclang_rt.tsan_osx_dynamic.dylib+0x0000000253c3) #1 input_lock inputthread.c:103 (X11.bin+0x00010049fd10) #2 TimerSet WaitFor.c:348 (X11.bin+0x0001004926c2) #3 RootlessQueueRedisplay rootlessScreen.c:594 (X11.bin+0x000100065d3f) #4 RootlessInstallColormap rootlessScreen.c:514 (X11.bin+0x000100069eda) #5 miSpriteInstallColormap misprite.c:562 (X11.bin+0x000100467075) #6 miCreateDefColormap micmap.c:270 (X11.bin+0x000100440379) #7 DarwinScreenInit darwin.c:285 (X11.bin+0x00010003036b) #8 AddScreen dispatch.c:3914 (X11.bin+0x00010036c3f7) #9 InitOutput darwin.c:671 (X11.bin+0x00010002fd9b) #10 dix_main main.c:197 (X11.bin+0x00010036e208) #11 server_thread quartzStartup.c:66 (X11.bin+0x000100039e23) Thread T7 (tid=4257217, running) created by main thread at: #0 pthread_create <null>:144 (libclang_rt.tsan_osx_dynamic.dylib+0x000000024490) #1 create_thread quartzStartup.c:78 (X11.bin+0x000100039d6d) #2 QuartzInitServer quartzStartup.c:95 (X11.bin+0x000100039bd6) #3 X11ApplicationMain X11Application.m:1238 (X11.bin+0x00010001cd94) #4 X11ControllerMain X11Controller.m:984 (X11.bin+0x00010002a5f2) #5 server_main quartzStartup.c:136 (X11.bin+0x000100039ffb) #6 do_start_x11_server bundle-main.c:436 (X11.bin+0x000100002e65) #7 _Xstart_x11_server mach_startupServer.c:189 (X11.bin+0x000100004e49) #8 mach_startup_server mach_startupServer.c:399 (X11.bin+0x0001000056e4) #9 mach_msg_server mach_msg.c:563 (libsystem_kernel.dylib+0x000000012186) #10 start <null>:29 (libdyld.dylib+0x000000005254) SUMMARY: ThreadSanitizer: data race mieq.c:263 in mieqEnqueue ================== Signed-off-by: Jeremy Huddleston Sequoia <jeremyhu@apple.com> Reviewed-by: Keith Packard <keithp@keithp.com>
544 lines
14 KiB
C
544 lines
14 KiB
C
/***********************************************************
|
|
|
|
Copyright 1987, 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.
|
|
|
|
Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
|
|
|
|
All Rights Reserved
|
|
|
|
Permission to use, copy, modify, and distribute this software and its
|
|
documentation for any purpose and without fee is hereby granted,
|
|
provided that the above copyright notice appear in all copies and that
|
|
both that copyright notice and this permission notice appear in
|
|
supporting documentation, and that the name of Digital not be
|
|
used in advertising or publicity pertaining to distribution of the
|
|
software without specific, written prior permission.
|
|
|
|
DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
|
|
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
|
|
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
|
|
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
|
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
|
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
|
SOFTWARE.
|
|
|
|
******************************************************************/
|
|
|
|
/*****************************************************************
|
|
* OS Dependent input routines:
|
|
*
|
|
* WaitForSomething
|
|
* TimerForce, TimerSet, TimerCheck, TimerFree
|
|
*
|
|
*****************************************************************/
|
|
|
|
#ifdef HAVE_DIX_CONFIG_H
|
|
#include <dix-config.h>
|
|
#endif
|
|
|
|
#ifdef WIN32
|
|
#include <X11/Xwinsock.h>
|
|
#endif
|
|
#include <X11/Xos.h> /* for strings, fcntl, time */
|
|
#include <errno.h>
|
|
#include <stdio.h>
|
|
#include <X11/X.h>
|
|
#include "misc.h"
|
|
|
|
#include "osdep.h"
|
|
#include "dixstruct.h"
|
|
#include "opaque.h"
|
|
#ifdef DPMSExtension
|
|
#include "dpmsproc.h"
|
|
#endif
|
|
#include "busfault.h"
|
|
|
|
#ifdef WIN32
|
|
/* Error codes from windows sockets differ from fileio error codes */
|
|
#undef EINTR
|
|
#define EINTR WSAEINTR
|
|
#undef EINVAL
|
|
#define EINVAL WSAEINVAL
|
|
#undef EBADF
|
|
#define EBADF WSAENOTSOCK
|
|
/* Windows select does not set errno. Use GetErrno as wrapper for
|
|
WSAGetLastError */
|
|
#define GetErrno WSAGetLastError
|
|
#else
|
|
/* This is just a fallback to errno to hide the differences between unix and
|
|
Windows in the code */
|
|
#define GetErrno() errno
|
|
#endif
|
|
|
|
/* like ffs, but uses fd_mask instead of int as argument, so it works
|
|
when fd_mask is longer than an int, such as common 64-bit platforms */
|
|
/* modifications by raphael */
|
|
int
|
|
mffs(fd_mask mask)
|
|
{
|
|
int i;
|
|
|
|
if (!mask)
|
|
return 0;
|
|
i = 1;
|
|
while (!(mask & 1)) {
|
|
i++;
|
|
mask >>= 1;
|
|
}
|
|
return i;
|
|
}
|
|
|
|
#ifdef DPMSExtension
|
|
#include <X11/extensions/dpmsconst.h>
|
|
#endif
|
|
|
|
struct _OsTimerRec {
|
|
struct xorg_list list;
|
|
CARD32 expires;
|
|
CARD32 delta;
|
|
OsTimerCallback callback;
|
|
void *arg;
|
|
};
|
|
|
|
static void DoTimer(OsTimerPtr timer, CARD32 now);
|
|
static void DoTimers(CARD32 now);
|
|
static void CheckAllTimers(void);
|
|
static volatile struct xorg_list timers;
|
|
|
|
static inline OsTimerPtr
|
|
first_timer(void)
|
|
{
|
|
/* inline xorg_list_is_empty which can't handle volatile */
|
|
if (timers.next == &timers)
|
|
return NULL;
|
|
return xorg_list_first_entry(&timers, struct _OsTimerRec, list);
|
|
}
|
|
|
|
/*
|
|
* Compute timeout until next timer, running
|
|
* any expired timers
|
|
*/
|
|
static int
|
|
check_timers(void)
|
|
{
|
|
OsTimerPtr timer;
|
|
|
|
while ((timer = first_timer()) != NULL) {
|
|
CARD32 now = GetTimeInMillis();
|
|
int timeout = timer->expires - now;
|
|
|
|
if (timeout <= 0) {
|
|
DoTimers(now);
|
|
} else {
|
|
/* Make sure the timeout is sane */
|
|
if (timeout < timer->delta + 250)
|
|
return timeout;
|
|
|
|
/* time has rewound. reset the timers. */
|
|
CheckAllTimers();
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/*****************
|
|
* WaitForSomething:
|
|
* Make the server suspend until there is
|
|
* 1. data from clients or
|
|
* 2. input events available or
|
|
* 3. ddx notices something of interest (graphics
|
|
* queue ready, etc.) or
|
|
* 4. clients that have buffered replies/events are ready
|
|
*
|
|
* If the time between INPUT events is
|
|
* greater than ScreenSaverTime, the display is turned off (or
|
|
* saved, depending on the hardware). So, WaitForSomething()
|
|
* has to handle this also (that's why the select() has a timeout.
|
|
* For more info on ClientsWithInput, see ReadRequestFromClient().
|
|
* pClientsReady is an array to store ready client->index values into.
|
|
*****************/
|
|
|
|
Bool
|
|
WaitForSomething(Bool are_ready)
|
|
{
|
|
int i;
|
|
int timeout;
|
|
int pollerr;
|
|
static Bool were_ready;
|
|
Bool timer_is_running;
|
|
|
|
timer_is_running = were_ready;
|
|
|
|
if (were_ready && !are_ready) {
|
|
timer_is_running = FALSE;
|
|
SmartScheduleStopTimer();
|
|
}
|
|
|
|
were_ready = FALSE;
|
|
|
|
#ifdef BUSFAULT
|
|
busfault_check();
|
|
#endif
|
|
|
|
/* We need a while loop here to handle
|
|
crashed connections and the screen saver timeout */
|
|
while (1) {
|
|
/* deal with any blocked jobs */
|
|
if (workQueue)
|
|
ProcessWorkQueue();
|
|
|
|
if (are_ready)
|
|
timeout = 0;
|
|
else
|
|
timeout = check_timers();
|
|
|
|
BlockHandler(&timeout);
|
|
if (NewOutputPending)
|
|
FlushAllOutput();
|
|
/* keep this check close to select() call to minimize race */
|
|
if (dispatchException)
|
|
i = -1;
|
|
else
|
|
i = ospoll_wait(server_poll, timeout);
|
|
pollerr = GetErrno();
|
|
WakeupHandler(i);
|
|
if (i <= 0) { /* An error or timeout occurred */
|
|
if (dispatchException)
|
|
return FALSE;
|
|
if (i < 0) {
|
|
if (pollerr != EINTR && !ETEST(pollerr)) {
|
|
ErrorF("WaitForSomething(): poll: %s\n",
|
|
strerror(pollerr));
|
|
}
|
|
}
|
|
} else
|
|
are_ready = clients_are_ready();
|
|
|
|
if (InputCheckPending())
|
|
return FALSE;
|
|
|
|
if (are_ready) {
|
|
were_ready = TRUE;
|
|
if (!timer_is_running)
|
|
SmartScheduleStartTimer();
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
AdjustWaitForDelay(void *waitTime, int newdelay)
|
|
{
|
|
int *timeoutp = waitTime;
|
|
int timeout = *timeoutp;
|
|
|
|
if (timeout < 0 || newdelay < timeout)
|
|
*timeoutp = newdelay;
|
|
}
|
|
|
|
static inline Bool timer_pending(OsTimerPtr timer) {
|
|
return !xorg_list_is_empty(&timer->list);
|
|
}
|
|
|
|
/* If time has rewound, re-run every affected timer.
|
|
* Timers might drop out of the list, so we have to restart every time. */
|
|
static void
|
|
CheckAllTimers(void)
|
|
{
|
|
OsTimerPtr timer;
|
|
CARD32 now;
|
|
|
|
input_lock();
|
|
start:
|
|
now = GetTimeInMillis();
|
|
|
|
xorg_list_for_each_entry(timer, &timers, list) {
|
|
if (timer->expires - now > timer->delta + 250) {
|
|
DoTimer(timer, now);
|
|
goto start;
|
|
}
|
|
}
|
|
input_unlock();
|
|
}
|
|
|
|
static void
|
|
DoTimer(OsTimerPtr timer, CARD32 now)
|
|
{
|
|
CARD32 newTime;
|
|
|
|
xorg_list_del(&timer->list);
|
|
newTime = (*timer->callback) (timer, now, timer->arg);
|
|
if (newTime)
|
|
TimerSet(timer, 0, newTime, timer->callback, timer->arg);
|
|
}
|
|
|
|
static void
|
|
DoTimers(CARD32 now)
|
|
{
|
|
OsTimerPtr timer;
|
|
|
|
input_lock();
|
|
while ((timer = first_timer())) {
|
|
if ((int) (timer->expires - now) > 0)
|
|
break;
|
|
DoTimer(timer, now);
|
|
}
|
|
input_unlock();
|
|
}
|
|
|
|
OsTimerPtr
|
|
TimerSet(OsTimerPtr timer, int flags, CARD32 millis,
|
|
OsTimerCallback func, void *arg)
|
|
{
|
|
OsTimerPtr existing, tmp;
|
|
CARD32 now = GetTimeInMillis();
|
|
|
|
if (!timer) {
|
|
timer = calloc(1, sizeof(struct _OsTimerRec));
|
|
if (!timer)
|
|
return NULL;
|
|
xorg_list_init(&timer->list);
|
|
}
|
|
else {
|
|
input_lock();
|
|
if (timer_pending(timer)) {
|
|
xorg_list_del(&timer->list);
|
|
if (flags & TimerForceOld)
|
|
(void) (*timer->callback) (timer, now, timer->arg);
|
|
}
|
|
input_unlock();
|
|
}
|
|
if (!millis)
|
|
return timer;
|
|
if (flags & TimerAbsolute) {
|
|
timer->delta = millis - now;
|
|
}
|
|
else {
|
|
timer->delta = millis;
|
|
millis += now;
|
|
}
|
|
timer->expires = millis;
|
|
timer->callback = func;
|
|
timer->arg = arg;
|
|
input_lock();
|
|
|
|
/* Sort into list */
|
|
xorg_list_for_each_entry_safe(existing, tmp, &timers, list)
|
|
if ((int) (existing->expires - millis) > 0)
|
|
break;
|
|
/* This even works at the end of the list -- existing->list will be timers */
|
|
xorg_list_add(&timer->list, existing->list.prev);
|
|
|
|
/* Check to see if the timer is ready to run now */
|
|
if ((int) (millis - now) <= 0)
|
|
DoTimer(timer, now);
|
|
|
|
input_unlock();
|
|
return timer;
|
|
}
|
|
|
|
Bool
|
|
TimerForce(OsTimerPtr timer)
|
|
{
|
|
int pending;
|
|
|
|
input_lock();
|
|
pending = timer_pending(timer);
|
|
if (pending)
|
|
DoTimer(timer, GetTimeInMillis());
|
|
input_unlock();
|
|
return pending;
|
|
}
|
|
|
|
void
|
|
TimerCancel(OsTimerPtr timer)
|
|
{
|
|
if (!timer)
|
|
return;
|
|
input_lock();
|
|
xorg_list_del(&timer->list);
|
|
input_unlock();
|
|
}
|
|
|
|
void
|
|
TimerFree(OsTimerPtr timer)
|
|
{
|
|
if (!timer)
|
|
return;
|
|
TimerCancel(timer);
|
|
free(timer);
|
|
}
|
|
|
|
void
|
|
TimerCheck(void)
|
|
{
|
|
DoTimers(GetTimeInMillis());
|
|
}
|
|
|
|
void
|
|
TimerInit(void)
|
|
{
|
|
static Bool been_here;
|
|
OsTimerPtr timer, tmp;
|
|
|
|
if (!been_here) {
|
|
been_here = TRUE;
|
|
xorg_list_init((struct xorg_list*) &timers);
|
|
}
|
|
|
|
xorg_list_for_each_entry_safe(timer, tmp, &timers, list) {
|
|
xorg_list_del(&timer->list);
|
|
free(timer);
|
|
}
|
|
}
|
|
|
|
#ifdef DPMSExtension
|
|
|
|
#define DPMS_CHECK_MODE(mode,time)\
|
|
if (time > 0 && DPMSPowerLevel < mode && timeout >= time)\
|
|
DPMSSet(serverClient, mode);
|
|
|
|
#define DPMS_CHECK_TIMEOUT(time)\
|
|
if (time > 0 && (time - timeout) > 0)\
|
|
return time - timeout;
|
|
|
|
static CARD32
|
|
NextDPMSTimeout(INT32 timeout)
|
|
{
|
|
/*
|
|
* Return the amount of time remaining until we should set
|
|
* the next power level. Fallthroughs are intentional.
|
|
*/
|
|
switch (DPMSPowerLevel) {
|
|
case DPMSModeOn:
|
|
DPMS_CHECK_TIMEOUT(DPMSStandbyTime)
|
|
|
|
case DPMSModeStandby:
|
|
DPMS_CHECK_TIMEOUT(DPMSSuspendTime)
|
|
|
|
case DPMSModeSuspend:
|
|
DPMS_CHECK_TIMEOUT(DPMSOffTime)
|
|
|
|
default: /* DPMSModeOff */
|
|
return 0;
|
|
}
|
|
}
|
|
#endif /* DPMSExtension */
|
|
|
|
static CARD32
|
|
ScreenSaverTimeoutExpire(OsTimerPtr timer, CARD32 now, void *arg)
|
|
{
|
|
INT32 timeout = now - LastEventTime(XIAllDevices).milliseconds;
|
|
CARD32 nextTimeout = 0;
|
|
|
|
#ifdef DPMSExtension
|
|
/*
|
|
* Check each mode lowest to highest, since a lower mode can
|
|
* have the same timeout as a higher one.
|
|
*/
|
|
if (DPMSEnabled) {
|
|
DPMS_CHECK_MODE(DPMSModeOff, DPMSOffTime)
|
|
DPMS_CHECK_MODE(DPMSModeSuspend, DPMSSuspendTime)
|
|
DPMS_CHECK_MODE(DPMSModeStandby, DPMSStandbyTime)
|
|
|
|
nextTimeout = NextDPMSTimeout(timeout);
|
|
}
|
|
|
|
/*
|
|
* Only do the screensaver checks if we're not in a DPMS
|
|
* power saving mode
|
|
*/
|
|
if (DPMSPowerLevel != DPMSModeOn)
|
|
return nextTimeout;
|
|
#endif /* DPMSExtension */
|
|
|
|
if (!ScreenSaverTime)
|
|
return nextTimeout;
|
|
|
|
if (timeout < ScreenSaverTime) {
|
|
return nextTimeout > 0 ?
|
|
min(ScreenSaverTime - timeout, nextTimeout) :
|
|
ScreenSaverTime - timeout;
|
|
}
|
|
|
|
ResetOsBuffers(); /* not ideal, but better than nothing */
|
|
dixSaveScreens(serverClient, SCREEN_SAVER_ON, ScreenSaverActive);
|
|
|
|
if (ScreenSaverInterval > 0) {
|
|
nextTimeout = nextTimeout > 0 ?
|
|
min(ScreenSaverInterval, nextTimeout) : ScreenSaverInterval;
|
|
}
|
|
|
|
return nextTimeout;
|
|
}
|
|
|
|
static OsTimerPtr ScreenSaverTimer = NULL;
|
|
|
|
void
|
|
FreeScreenSaverTimer(void)
|
|
{
|
|
if (ScreenSaverTimer) {
|
|
TimerFree(ScreenSaverTimer);
|
|
ScreenSaverTimer = NULL;
|
|
}
|
|
}
|
|
|
|
void
|
|
SetScreenSaverTimer(void)
|
|
{
|
|
CARD32 timeout = 0;
|
|
|
|
#ifdef DPMSExtension
|
|
if (DPMSEnabled) {
|
|
/*
|
|
* A higher DPMS level has a timeout that's either less
|
|
* than or equal to that of a lower DPMS level.
|
|
*/
|
|
if (DPMSStandbyTime > 0)
|
|
timeout = DPMSStandbyTime;
|
|
|
|
else if (DPMSSuspendTime > 0)
|
|
timeout = DPMSSuspendTime;
|
|
|
|
else if (DPMSOffTime > 0)
|
|
timeout = DPMSOffTime;
|
|
}
|
|
#endif
|
|
|
|
if (ScreenSaverTime > 0) {
|
|
timeout = timeout > 0 ? min(ScreenSaverTime, timeout) : ScreenSaverTime;
|
|
}
|
|
|
|
#ifdef SCREENSAVER
|
|
if (timeout && !screenSaverSuspended) {
|
|
#else
|
|
if (timeout) {
|
|
#endif
|
|
ScreenSaverTimer = TimerSet(ScreenSaverTimer, 0, timeout,
|
|
ScreenSaverTimeoutExpire, NULL);
|
|
}
|
|
else if (ScreenSaverTimer) {
|
|
FreeScreenSaverTimer();
|
|
}
|
|
}
|