}
static void
+IdleTimeCheckBrackets(SyncCounter *counter, XSyncValue idle, XSyncValue *less, XSyncValue *greater)
+{
+ if ((greater && XSyncValueGreaterOrEqual(idle, *greater)) ||
+ (less && XSyncValueLessOrEqual(idle, *less))) {
+ SyncChangeCounter(counter, idle);
+ }
+}
+
+static void
IdleTimeWakeupHandler(pointer pCounter, int rc, pointer LastSelectMask)
{
SyncCounter *counter = pCounter;
IdleTimeQueryValue(pCounter, &idle);
- if ((greater && XSyncValueGreaterOrEqual(idle, *greater)) ||
- (less && XSyncValueLessOrEqual(idle, *less))) {
- SyncChangeCounter(counter, idle);
+ /*
+ There is no guarantee for the WakeupHandler to be called within a specific
+ timeframe. Idletime may go to 0, but by the time we get here, it may be
+ non-zero and alarms for a pos. transition on 0 won't get triggered.
+ https://bugs.freedesktop.org/show_bug.cgi?id=70476
+ */
+ if (LastEventTimeWasReset(priv->deviceid)) {
+ LastEventTimeToggleResetFlag(priv->deviceid, FALSE);
+ if (!XSyncValueIsZero(idle)) {
+ XSyncValue zero;
+ XSyncIntsToValue(&zero, 0, 0);
+ IdleTimeCheckBrackets(counter, zero, less, greater);
+ less = priv->value_less;
+ greater = priv->value_greater;
+ }
}
+
+ IdleTimeCheckBrackets(counter, idle, less, greater);
}
static void
IdleTimeWakeupHandler, pCounter);
}
else if (!registered && (pbracket_less || pbracket_greater)) {
+ /* Reset flag must be zero so we don't force a idle timer reset on
+ the first wakeup */
+ LastEventTimeToggleResetAll(FALSE);
RegisterBlockAndWakeupHandlers(IdleTimeBlockHandler,
IdleTimeWakeupHandler, pCounter);
}
EventSyncInfoRec syncEvents;
-static TimeStamp lastDeviceEventTime[MAXDEVICES];
+static struct DeviceEventTime {
+ Bool reset;
+ TimeStamp time;
+} lastDeviceEventTime[MAXDEVICES];
/**
* The root window the given device is currently on.
void
NoticeTime(const DeviceIntPtr dev, TimeStamp time)
{
- lastDeviceEventTime[XIAllDevices] = currentTime;
- lastDeviceEventTime[dev->id] = currentTime;
+ lastDeviceEventTime[XIAllDevices].time = currentTime;
+ lastDeviceEventTime[dev->id].time = currentTime;
+
+ LastEventTimeToggleResetFlag(dev->id, TRUE);
+ LastEventTimeToggleResetFlag(XIAllDevices, TRUE);
}
static void
TimeStamp
LastEventTime(int deviceid)
{
- return lastDeviceEventTime[deviceid];
+ return lastDeviceEventTime[deviceid].time;
+}
+
+Bool
+LastEventTimeWasReset(int deviceid)
+{
+ return lastDeviceEventTime[deviceid].reset;
+}
+
+void
+LastEventTimeToggleResetFlag(int deviceid, Bool state)
+{
+ lastDeviceEventTime[deviceid].reset = state;
+}
+
+void
+LastEventTimeToggleResetAll(Bool state)
+{
+ DeviceIntPtr dev;
+ nt_list_for_each_entry(dev, inputInfo.devices, next) {
+ LastEventTimeToggleResetFlag(dev->id, FALSE);
+ }
+ LastEventTimeToggleResetFlag(XIAllDevices, FALSE);
+ LastEventTimeToggleResetFlag(XIAllMasterDevices, FALSE);
}
/**************************************************************************
dummy.id = i;
NoticeTime(&dummy, currentTime);
+ LastEventTimeToggleResetFlag(i, FALSE);
}
syncEvents.replayDev = (DeviceIntPtr) NULL;