From 14f734873d2b2c5d96d563482384a996c50f1068 Mon Sep 17 00:00:00 2001 From: Mike Gabriel Date: Tue, 3 Jul 2018 14:43:26 +0200 Subject: Backport IDLETIME system counter to nx-X11 Xserver. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 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 Reviewed-by: Adam Jackson Signed-off-by: Keith Packard commit 1f4fb0225b278d1cf4145aebeb0bdd23dc8f62d5 Author: Adam Jackson 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 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 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 --- nx-X11/programs/Xserver/Xext/sync.c | 159 ++++++++++++++++++++++++++++++++++++ 1 file changed, 159 insertions(+) (limited to 'nx-X11') 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; +} -- cgit v1.2.3 From 7401a6691a9a3cd77431466b941eaf169c9b2b2c Mon Sep 17 00:00:00 2001 From: Richard Hughes Date: Tue, 3 Jul 2018 14:48:43 +0200 Subject: Do not reset lastDeviceEventTime when we do dixSaveScreens Backported from X.org's Xserver: commit 6b5978dcf1f7ac3ecc2f22df06f7000f360e2066 Author: Richard Hughes Date: Mon Aug 17 09:15:32 2009 +0100 Do not reset lastDeviceEventTime when we do dixSaveScreens When we turn off DPMS with DPMSModeOff and do dixSaveScreens, don't reset the event time else session clients using IDLETIME will be reset. Signed-off-by: Peter Hutterer Backported-to-NX-by: Mike Gabriel --- nx-X11/programs/Xserver/dix/window.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'nx-X11') diff --git a/nx-X11/programs/Xserver/dix/window.c b/nx-X11/programs/Xserver/dix/window.c index 300c1a7fc..79045767f 100644 --- a/nx-X11/programs/Xserver/dix/window.c +++ b/nx-X11/programs/Xserver/dix/window.c @@ -3348,8 +3348,6 @@ SaveScreens(int on, int mode) if (on == SCREEN_SAVER_FORCER) { - UpdateCurrentTimeIf(); - lastDeviceEventTime = currentTime; if (mode == ScreenSaverReset) what = SCREEN_SAVER_OFF; else -- cgit v1.2.3 From 222153af4406e74c9d8a8a752ae220663432905d Mon Sep 17 00:00:00 2001 From: Mike Gabriel Date: Tue, 3 Jul 2018 14:50:32 +0200 Subject: Don't reset the lastDeviceEventTime when doing DPMS actions Backported from X.org's Xserver: commit c1d901d723c3bee523736eacc15b44a7dff484fe Author: Richard Hughes Date: Fri Aug 14 11:44:35 2009 +0100 Don't reset the lastDeviceEventTime when doing DPMS actions When we change the DPMS mode, don't play games with the last event time as this breaks applications using IDLETIME to turn the backlight off after a preset time. This patch fixes gnome-power-manager and xfce-power-manager Signed-off-by: Peter Hutterer Backport-to-NX-by: Mike Gabriel --- nx-X11/programs/Xserver/Xext/dpms.c | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) (limited to 'nx-X11') diff --git a/nx-X11/programs/Xserver/Xext/dpms.c b/nx-X11/programs/Xserver/Xext/dpms.c index 74969bb52..81bbd5179 100644 --- a/nx-X11/programs/Xserver/Xext/dpms.c +++ b/nx-X11/programs/Xserver/Xext/dpms.c @@ -232,19 +232,10 @@ ProcDPMSForceLevel(client) if (!DPMSEnabled) return BadMatch; - if (stuff->level == DPMSModeOn) { - lastDeviceEventTime.milliseconds = - GetTimeInMillis(); - } else if (stuff->level == DPMSModeStandby) { - lastDeviceEventTime.milliseconds = - GetTimeInMillis() - DPMSStandbyTime; - } else if (stuff->level == DPMSModeSuspend) { - lastDeviceEventTime.milliseconds = - GetTimeInMillis() - DPMSSuspendTime; - } else if (stuff->level == DPMSModeOff) { - lastDeviceEventTime.milliseconds = - GetTimeInMillis() - DPMSOffTime; - } else { + if (stuff->level != DPMSModeOn && + stuff->level != DPMSModeStandby && + stuff->level != DPMSModeSuspend && + stuff->level != DPMSModeOff) { client->errorValue = stuff->level; return BadValue; } -- cgit v1.2.3