I made new version of the patch.
The issue Keith pointed is fixed.

Also I added a flag for timers TimerNeedsCheckInput.  The timers without this
flag are processed before the select all others are delaied until the second
timers check.  (The second check doesn't distinguish those timers.)

Also I found another issue.  The thing is that the procedure xf86Wakeup that
reads input devices processes only one device in a turn because, as it is said
in comments, it "Must break [loop] here because more than one device may share
the same file descriptor".  Now the built-in keyboard driver is called
separately before the loop and all works well.  But if a keyboard is served
by a module driver and there are more than one devices with 'ready for reading'
events there is not guaranty that all input devices events will be read before
the timers checking.

I made a separate patch for xf86Wakeup (in a separate attachment).
Please review.

-- 
 Ivan U. Pascal         |   e-mail: [EMAIL PROTECTED]
   Administrator of     |   Tomsk State University
     University Network |       Tomsk, Russia
--- xc/programs/Xserver/os/WaitFor.c.orig       Wed Sep 17 17:24:12 2003
+++ xc/programs/Xserver/os/WaitFor.c            Mon Sep 22 19:34:55 2003
@@ -109,6 +109,7 @@
     CARD32             expires;
     OsTimerCallback    callback;
     pointer            arg;
+    int                        flags;
 };
 
 static void DoTimer(OsTimerPtr timer, CARD32 now, OsTimerPtr *prev);
@@ -131,17 +132,12 @@
  *     pClientsReady is an array to store ready client->index values into.
  *****************/
 
-static INT32 timeTilFrob = 0;          /* while screen saving */
-
 int
 WaitForSomething(int *pClientsReady)
 {
     int i;
     struct timeval waittime, *wt;
     INT32 timeout = 0;
-#ifdef DPMSExtension
-    INT32 standbyTimeout = 0, suspendTimeout = 0, offTimeout = 0;
-#endif
     fd_set clientsReadable;
     fd_set clientsWritable;
     int curclient;
@@ -188,138 +184,37 @@
        else
        {
 #endif
-#ifdef DPMSExtension
-       if (ScreenSaverTime > 0 || DPMSEnabled || timers)
-#else
-       if (ScreenSaverTime > 0 || timers)
-#endif
-           now = GetTimeInMillis();
-       wt = NULL;
+        wt = NULL;
        if (timers)
-       {
-           while (timers && (int) (timers->expires - now) <= 0)
-               DoTimer(timers, now, &timers);
-           if (timers)
-           {
-               timeout = timers->expires - now;
-               waittime.tv_sec = timeout / MILLI_PER_SECOND;
-               waittime.tv_usec = (timeout % MILLI_PER_SECOND) *
-                   (1000000 / MILLI_PER_SECOND);
-               wt = &waittime;
-           }
-       }
-       if (ScreenSaverTime > 0
-#ifdef DPMSExtension
-           || (DPMSEnabled &&
-            (DPMSStandbyTime > 0 || DPMSSuspendTime > 0 || DPMSOffTime > 0))
-#endif
-       ) {
-#ifdef DPMSExtension
-           if (ScreenSaverTime > 0)
-#endif
-               timeout = (ScreenSaverTime -
-                          (now - lastDeviceEventTime.milliseconds));
-#ifdef DPMSExtension
-           if (DPMSStandbyTime > 0)
-               standbyTimeout = (DPMSStandbyTime -
-                                 (now - lastDeviceEventTime.milliseconds));
-           if (DPMSSuspendTime > 0)
-               suspendTimeout = (DPMSSuspendTime -
-                                 (now - lastDeviceEventTime.milliseconds));
-           if (DPMSOffTime > 0)
-               offTimeout = (DPMSOffTime -
-                             (now - lastDeviceEventTime.milliseconds));
-#endif /* DPMSExtension */
-
-           if (
-               timeout <= 0
-#ifdef DPMSExtension
-                && ScreenSaverTime > 0
-#endif /* DPMSExtension */
-           ) {
-               INT32 timeSinceSave;
-
-               timeSinceSave = -timeout;
-               if (timeSinceSave >= timeTilFrob && timeTilFrob >= 0)
-               {
-                   ResetOsBuffers(); /* not ideal, but better than nothing */
-                   SaveScreens(SCREEN_SAVER_ON, ScreenSaverActive);
-#ifdef DPMSExtension
-                   if (ScreenSaverInterval > 0 &&
-                       DPMSPowerLevel == DPMSModeOn)
-#else
-                   if (ScreenSaverInterval)
-#endif /* DPMSExtension */
-                       /* round up to the next ScreenSaverInterval */
-                       timeTilFrob = ScreenSaverInterval *
-                               ((timeSinceSave + ScreenSaverInterval) /
-                                       ScreenSaverInterval);
-                   else
-                       timeTilFrob = -1;
-               }
-               timeout = timeTilFrob - timeSinceSave;
-           }
-           else
-           {
-               if (ScreenSaverTime > 0 && timeout > ScreenSaverTime)
-                   timeout = ScreenSaverTime;
-               timeTilFrob = 0;
-           }
-#ifdef DPMSExtension
-           if (DPMSEnabled)
-           {
-               if (standbyTimeout > 0 
-                   && (timeout <= 0 || timeout > standbyTimeout))
-                   timeout = standbyTimeout;
-               if (suspendTimeout > 0 
-                   && (timeout <= 0 || timeout > suspendTimeout))
-                   timeout = suspendTimeout;
-               if (offTimeout > 0 
-                   && (timeout <= 0 || timeout > offTimeout))
-                   timeout = offTimeout;
-           }
-#endif
-           if (timeout > 0 && (!wt || timeout < (int) (timers->expires - now)))
-           {
-               waittime.tv_sec = timeout / MILLI_PER_SECOND;
-               waittime.tv_usec = (timeout % MILLI_PER_SECOND) *
-                                       (1000000 / MILLI_PER_SECOND);
-               wt = &waittime;
-           }
-#ifdef DPMSExtension
-           /* don't bother unless it's switched on */
-           if (DPMSEnabled) {
-               /*
-                * If this mode's enabled, and if the time's come
-                * and if we're still at a lesser mode, do it now.
-                */
-               if (DPMSStandbyTime > 0) {
-                   if (standbyTimeout <= 0) {
-                       if (DPMSPowerLevel < DPMSModeStandby) {
-                           DPMSSet(DPMSModeStandby);
-                       }
-                   }
-               }
-               /*
-                * and ditto.  Note that since these modes can have the
-                * same timeouts, they can happen at the same time.
-                */
-               if (DPMSSuspendTime > 0) {
-                   if (suspendTimeout <= 0) {
-                       if (DPMSPowerLevel < DPMSModeSuspend) {
-                           DPMSSet(DPMSModeSuspend);
-                       }
-                   }
-               }
-               if (DPMSOffTime > 0) {
-                   if (offTimeout <= 0) {
-                       if (DPMSPowerLevel < DPMSModeOff) {
-                           DPMSSet(DPMSModeOff);
-                       }
-                   }
-               }
-           }
-#endif
+        {
+            OsTimerPtr delaied = NULL, current = NULL;
+            now = GetTimeInMillis();
+            while (timers && (int) (timers->expires - now) <= 0) {
+                if (!(timers->flags & TimerNeedsCheckInput)) {
+                    DoTimer(timers, now, &timers);
+                } else {
+                    if (!delaied) {
+                        delaied = timers;
+                    } else {
+                        current->next = timers;
+                    }
+                    current = timers;
+                    timers = timers->next;
+                }
+            }
+            if (delaied) {
+                current->next = timers;
+                timers = delaied;
+            }
+       }
+        if (timers) {
+           timeout = timers->expires - now;
+            if (timeout < 0)
+                timeout = 0;
+           waittime.tv_sec = timeout / MILLI_PER_SECOND;
+           waittime.tv_usec = (timeout % MILLI_PER_SECOND) *
+                              (1000000 / MILLI_PER_SECOND);
+           wt = &waittime;
        }
        XFD_COPYSET(&AllSockets, &LastSelectMask);
 #ifdef SMART_SCHEDULE
@@ -350,6 +245,14 @@
        }
        selecterr = errno;
        WakeupHandler(i, (pointer)&LastSelectMask);
+        ProcessInputEvents();
+       if (timers)
+       {
+           now = GetTimeInMillis();
+           while (timers && (int) (timers->expires - now) <= 0)
+               DoTimer(timers, now, &timers);
+       }
+
 #ifdef XTESTEXT1
        if (playback_on) {
            i = XTestProcessInputAction (i, &waittime);
@@ -398,12 +301,6 @@
                break;
            }
 #endif
-           if (timers)
-           {
-               now = GetTimeInMillis();
-               while (timers && (int) (timers->expires - now) <= 0)
-                   DoTimer(timers, now, &timers);
-           }
            if (*checkForInput[0] != *checkForInput[1])
                return 0;
        }
@@ -560,6 +457,7 @@
            }
        }
     }
+    timer->flags = flags;
     if (!millis)
        return timer;
     if (!(flags & TimerAbsolute))
@@ -646,3 +544,112 @@
        xfree(timer);
     }
 }
+
+static CARD32
+ScreenSaverTimeoutExpire(OsTimerPtr timer,CARD32 now,pointer arg)
+{
+    INT32 timeout = now - lastDeviceEventTime.milliseconds;
+
+    if (timeout < ScreenSaverTime) {
+        return ScreenSaverTime - timeout;
+    }
+
+    ResetOsBuffers(); /* not ideal, but better than nothing */
+    SaveScreens(SCREEN_SAVER_ON, ScreenSaverActive);
+
+#ifdef DPMSExtension
+    if (ScreenSaverInterval > 0 && DPMSPowerLevel == DPMSModeOn)
+#else
+    if (ScreenSaverInterval > 0)
+#endif /* DPMSExtension */
+        return ScreenSaverInterval;
+
+    return 0;
+}
+
+static OsTimerPtr ScreenSaverTimer = NULL;
+
+void
+SetScreenSaverTimer(void)
+{
+    if (ScreenSaverTime > 0) {
+       ScreenSaverTimer = TimerSet(ScreenSaverTimer, TimerNeedsCheckInput,
+                                   ScreenSaverTime,
+                                   ScreenSaverTimeoutExpire, NULL);
+    } else if (ScreenSaverTimer) {
+       TimerFree(ScreenSaverTimer);
+       ScreenSaverTimer = NULL;
+    }
+}
+
+#ifdef DPMSExtension
+
+static OsTimerPtr DPMSStandbyTimer = NULL;
+static OsTimerPtr DPMSSuspendTimer = NULL;
+static OsTimerPtr DPMSOffTimer = NULL;
+
+static CARD32
+DPMSStandbyTimerExpire(OsTimerPtr timer,CARD32 now,pointer arg)
+{
+    INT32 timeout = now - lastDeviceEventTime.milliseconds;
+
+    if (timeout < DPMSStandbyTime) {
+        return DPMSStandbyTime - timeout;
+    }
+    if (DPMSPowerLevel < DPMSModeStandby) {
+        DPMSSet(DPMSModeStandby);
+    }
+    return DPMSStandbyTime;
+}
+
+static CARD32
+DPMSSuspendTimerExpire(OsTimerPtr timer,CARD32 now,pointer arg)
+{
+    INT32 timeout = now - lastDeviceEventTime.milliseconds;
+
+    if (timeout < DPMSSuspendTime) {
+        return DPMSSuspendTime - timeout;
+    }
+    if (DPMSPowerLevel < DPMSModeSuspend) {
+        DPMSSet(DPMSModeSuspend);
+    }
+    return DPMSSuspendTime;
+}
+
+static CARD32
+DPMSOffTimerExpire(OsTimerPtr timer,CARD32 now,pointer arg)
+{
+    INT32 timeout = now - lastDeviceEventTime.milliseconds;
+
+    if (timeout < DPMSOffTime) {
+        return DPMSOffTime - timeout;
+    }
+    if (DPMSPowerLevel < DPMSModeOff) {
+        DPMSSet(DPMSModeOff);
+    }
+    return DPMSOffTime;
+}
+
+void
+SetDPMSTimers(void)
+{
+    if (!DPMSEnabled)
+        return;
+
+    if (DPMSStandbyTime > 0) {
+        DPMSStandbyTimer = TimerSet(DPMSStandbyTimer, TimerNeedsCheckInput,
+                                    DPMSStandbyTime,
+                                    DPMSStandbyTimerExpire, NULL);
+    }
+    if (DPMSSuspendTime > 0) {
+        DPMSStandbyTimer = TimerSet(DPMSSuspendTimer, TimerNeedsCheckInput,
+                                    DPMSSuspendTime,
+                                    DPMSSuspendTimerExpire, NULL);
+    }
+    if (DPMSOffTime > 0) {
+        DPMSOffTimer = TimerSet(DPMSOffTimer, TimerNeedsCheckInput,
+                                DPMSOffTime,
+                                DPMSOffTimerExpire, NULL);
+    }
+}
+#endif
--- xc/programs/Xserver/include/os.h.orig       Wed Sep 17 18:41:35 2003
+++ xc/programs/Xserver/include/os.h            Mon Sep 22 18:30:03 2003
@@ -206,6 +206,7 @@
 
 #define TimerAbsolute (1<<0)
 #define TimerForceOld (1<<1)
+#define TimerNeedsCheckInput (1<<2)
 
 extern OsTimerPtr TimerSet(
     OsTimerPtr /* timer */,
@@ -219,6 +220,12 @@
 extern void TimerCancel(OsTimerPtr /* pTimer */);
 
 extern void TimerFree(OsTimerPtr /* pTimer */);
+
+extern void SetScreenSaverTimer(void);
+
+#ifdef DPMSExtension
+extern void SetDPMSTimers(void);
+#endif
 
 extern SIGVAL AutoResetServer(int /*sig*/);
 
--- xc/programs/Xserver/dix/main.c.orig Fri Sep 19 19:08:28 2003
+++ xc/programs/Xserver/dix/main.c      Fri Sep 19 19:12:30 2003
@@ -420,6 +420,9 @@
            InitRootWindow(WindowTable[i]);
         DefineInitialRootWindow(WindowTable[0]);
        SaveScreens(SCREEN_SAVER_FORCER, ScreenSaverReset);
+#ifdef DPMSExtension
+        SetDPMSTimers();
+#endif
 
 #ifdef PANORAMIX
        if (!noPanoramiXExtension) {
--- xc/programs/Xserver/dix/window.c.orig       Wed Sep 17 18:43:23 2003
+++ xc/programs/Xserver/dix/window.c            Wed Sep 17 18:47:06 2003
@@ -3487,6 +3487,8 @@
        }
     }
     screenIsSaved = what;
+    if (mode == ScreenSaverReset)
+       SetScreenSaverTimer();
 }
 
 static Bool
--- xc/programs/Xserver/xkb/xkbAccessX.c.orig   Mon Sep 22 19:14:48 2003
+++ xc/programs/Xserver/xkb/xkbAccessX.c        Mon Sep 22 19:31:36 2003
@@ -436,7 +436,8 @@
            {
                xkbi->repeatKey = xkbi->slowKey;
                xkbi->repeatKeyTimer= TimerSet(xkbi->repeatKeyTimer,
-                                       0, ctrls->repeat_delay,
+                                       TimerNeedsCheckInput,
+                                        ctrls->repeat_delay,
                                        AccessXRepeatKeyExpire, (pointer)keybd);
            }
        }
@@ -630,7 +631,8 @@
 #endif     
                xkbi->repeatKey = key;
                xkbi->repeatKeyTimer= TimerSet(xkbi->repeatKeyTimer,
-                                       0, ctrls->repeat_delay,
+                                       TimerNeedsCheckInput,
+                                       ctrls->repeat_delay,
                                        AccessXRepeatKeyExpire, (pointer)keybd);
            }
        }
--- xc/programs/Xserver/hw/xfree86/common/xf86Events.c.orig     Mon Sep 22 19:43:39 
2003
+++ xc/programs/Xserver/hw/xfree86/common/xf86Events.c          Mon Sep 22 19:45:21 
2003
@@ -1150,7 +1150,7 @@
            pInfo = xf86InputDevs;
            while (pInfo) {
                if (pInfo->read_input && pInfo->fd >= 0 &&
-                   (FD_ISSET(pInfo->fd, ((fd_set *)pReadmask)) != 0)) {
+                   (FD_ISSET(pInfo->fd, &devicesWithInput) != 0)) {
                    int sigstate = xf86BlockSIGIO();
                    
                    pInfo->read_input(pInfo);
@@ -1159,7 +1159,7 @@
                     * Must break here because more than one device may share
                     * the same file descriptor.
                     */
-                   break;
+                   FD_CLR(pInfo->fd, &devicesWithInput);
                }
                pInfo = pInfo->next;
            }

Reply via email to