diff options
author | Mike Gabriel <mike.gabriel@das-netzwerkteam.de> | 2018-07-03 14:43:26 +0200 |
---|---|---|
committer | Mike Gabriel <mike.gabriel@das-netzwerkteam.de> | 2018-07-03 15:26:15 +0200 |
commit | 14f734873d2b2c5d96d563482384a996c50f1068 (patch) | |
tree | 7adf68ffc91becd374a3a2ffe5f633f928932745 /nx-X11/programs | |
parent | 72f11ee838e67757e235e7216fb82679cc3f7d67 (diff) | |
download | nx-libs-14f734873d2b2c5d96d563482384a996c50f1068.tar.gz nx-libs-14f734873d2b2c5d96d563482384a996c50f1068.tar.bz2 nx-libs-14f734873d2b2c5d96d563482384a996c50f1068.zip |
Backport IDLETIME system counter to nx-X11 Xserver.
This resolves issues with non-starting mate-screensaver which
relies on the IDLETIME API these days.
This commit backports the following X.org Xserver commits:
commit a2e67a6412386782cb8b644b86a5744591397d45
Author: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com>
Date: Mon Dec 6 11:24:01 2010 +1100
IDLETIME: Fix edge-case in IdleTimeBlockHandler
Ensure that if we're called exactly on the threshold of a
NegativeTransition trigger that we reshedule to pick up
an idle time over the threshold.
Signed-off-by: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com>
Reviewed-by: Adam Jackson <ajax@redhat.com>
Signed-off-by: Keith Packard <keithp@keithp.com>
commit 1f4fb0225b278d1cf4145aebeb0bdd23dc8f62d5
Author: Adam Jackson <ajax@redhat.com>
Date: Wed Dec 10 16:13:20 2008 -0500
xsync: Fix wakeup storm in idletime counter.
Wakeup scheduling only considered the threshold values, and not whether
the trigger was edge or level.
See also:
https://bugzilla.redhat.com/show_bug.cgi?id=474586
http://svn.gnome.org/viewvc/gnome-screensaver/trunk/src/test-idle-ext.c?view=markup
commit 0f9e89b4e309e570d7d366489d250ca2143f0ad7
Author: Fredrik Höglund <fredrik@kde.org>
Date: Tue Aug 14 22:47:49 2007 +0200
Fix the value comparisons in the IDLETIME wakeup handler.
LessThan/GreaterThan comparisons were used in the wakeup handler,
and LessOrEqual/GreaterOrEqual in the block handler.
Change it to use LessOrEqual/GreaterOrEqual in both functions,
since this is what XSyncNegativeComparison and
XSyncPositiveComparison imply.
commit 7e2c935920cafadbd87c351f1a3239932864fb90
Author: Fredrik Höglund <fredrik@kde.org>
Date: Fri May 18 20:06:14 2007 +0200
Add a new IDLETIME system sync counter.
This counter exposes the time in milliseconds since the last
input event. Clients such as screen savers and power managers
can set an alarm on this counter to find out when the idle time
reaches a certain value, without having to poll the server.
Backport-to-NX-by: Mike Gabriel <mike.gabriel@das-netzwerkteam.de>
Diffstat (limited to 'nx-X11/programs')
-rw-r--r-- | nx-X11/programs/Xserver/Xext/sync.c | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/nx-X11/programs/Xserver/Xext/sync.c b/nx-X11/programs/Xserver/Xext/sync.c index e90e35db9..a0711b77a 100644 --- a/nx-X11/programs/Xserver/Xext/sync.c +++ b/nx-X11/programs/Xserver/Xext/sync.c @@ -240,6 +240,11 @@ SyncInitServerTime( void ); +static void +SyncInitIdleTime( + void +); + static void SyncResetProc( ExtensionEntry * /* extEntry */ @@ -2365,6 +2370,7 @@ SyncExtensionInit(void) * because there is always a servertime counter. */ SyncInitServerTime(); + SyncInitIdleTime(); #ifdef DEBUG fprintf(stderr, "Sync Extension %d.%d\n", @@ -2485,3 +2491,156 @@ SyncInitServerTime() ServertimeQueryValue, ServertimeBracketValues); pnext_time = NULL; } + + +/* + * IDLETIME implementation + */ + +static SyncCounter *IdleTimeCounter; +static XSyncValue *pIdleTimeValueLess; +static XSyncValue *pIdleTimeValueGreater; + +static void +IdleTimeQueryValue (pointer pCounter, CARD64 *pValue_return) +{ + CARD32 idle = GetTimeInMillis() - lastDeviceEventTime.milliseconds; + XSyncIntsToValue (pValue_return, idle, 0); +} + +static void +IdleTimeBlockHandler (pointer env, struct timeval **wt, pointer LastSelectMask) +{ + XSyncValue idle, old_idle; + SyncTriggerList *list = IdleTimeCounter->pTriglist; + SyncTrigger *trig; + + if (!pIdleTimeValueLess && !pIdleTimeValueGreater) + return; + + old_idle = IdleTimeCounter->value; + IdleTimeQueryValue (NULL, &idle); + IdleTimeCounter->value = idle; /* push, so CheckTrigger works */ + + if (pIdleTimeValueLess && + XSyncValueLessOrEqual (idle, *pIdleTimeValueLess)) + { + /* + * We've been idle for less than the threshold value, and someone + * wants to know about that, but now we need to know whether they + * want level or edge trigger. Check the trigger list against the + * current idle time, and if any succeed, bomb out of select() + * immediately so we can reschedule. + */ + + for (list = IdleTimeCounter->pTriglist; list; list = list->next) { + trig = list->pTrigger; + if (trig->CheckTrigger(trig, old_idle)) { + AdjustWaitForDelay(wt, 0); + break; + } + } + + /* + * We've been called exactly on the idle time, but we have a + * NegativeTransition trigger which requires a transition from an + * idle time greater than this. Schedule a wakeup for the next + * millisecond so we won't miss a transition. + */ + if (XSyncValueEqual (idle, *pIdleTimeValueLess)) + AdjustWaitForDelay(wt, 1); + } + else if (pIdleTimeValueGreater) + { + /* + * There's a threshold in the positive direction. If we've been + * idle less than it, schedule a wakeup for sometime in the future. + * If we've been idle more than it, and someone wants to know about + * that level-triggered, schedule an immediate wakeup. + */ + unsigned long timeout = -1; + + if (XSyncValueLessThan (idle, *pIdleTimeValueGreater)) { + XSyncValue value; + Bool overflow; + + XSyncValueSubtract (&value, *pIdleTimeValueGreater, + idle, &overflow); + timeout = min(timeout, XSyncValueLow32 (value)); + } else { + for (list = IdleTimeCounter->pTriglist; list; list = list->next) { + trig = list->pTrigger; + if (trig->CheckTrigger(trig, old_idle)) { + timeout = min(timeout, 0); + break; + } + } + } + + AdjustWaitForDelay (wt, timeout); + } + + IdleTimeCounter->value = old_idle; /* pop */ +} + +static void +IdleTimeWakeupHandler (pointer env, + int rc, + pointer LastSelectMask) +{ + XSyncValue idle; + + if (!pIdleTimeValueLess && !pIdleTimeValueGreater) + return; + + IdleTimeQueryValue (NULL, &idle); + + if ((pIdleTimeValueGreater && + XSyncValueGreaterOrEqual (idle, *pIdleTimeValueGreater)) || + (pIdleTimeValueLess && + XSyncValueLessOrEqual (idle, *pIdleTimeValueLess))) + { + SyncChangeCounter (IdleTimeCounter, idle); + } +} + +static void +IdleTimeBracketValues (pointer pCounter, + CARD64 *pbracket_less, + CARD64 *pbracket_greater) +{ + Bool registered = (pIdleTimeValueLess || pIdleTimeValueGreater); + + if (registered && !pbracket_less && !pbracket_greater) + { + RemoveBlockAndWakeupHandlers(IdleTimeBlockHandler, + IdleTimeWakeupHandler, + NULL); + } + else if (!registered && (pbracket_less || pbracket_greater)) + { + RegisterBlockAndWakeupHandlers(IdleTimeBlockHandler, + IdleTimeWakeupHandler, + NULL); + } + + pIdleTimeValueGreater = pbracket_greater; + pIdleTimeValueLess = pbracket_less; +} + +static void +SyncInitIdleTime (void) +{ + CARD64 resolution; + XSyncValue idle; + + IdleTimeQueryValue (NULL, &idle); + XSyncIntToValue (&resolution, 4); + + IdleTimeCounter = SyncCreateSystemCounter ("IDLETIME", idle, resolution, + XSyncCounterUnrestricted, + IdleTimeQueryValue, + IdleTimeBracketValues); + + pIdleTimeValueLess = pIdleTimeValueGreater = NULL; +} |