Focus livelock fix

Jukka Heinonen jhei at iki.fi
Fri Aug 31 15:33:43 CDT 2001


It seems that Wine focus handling is subject to a livelock.
This is triggered by at least Colonization for Windows.
The cause of the livelock is that the handler for FocusIn X11-event
calls indirectly XSetInputFocus. This makes it possible for two or more
windows to start ping-ponging focus between them, as demonstrated below:

 Wine: Application calls CreateWindow(A) -> calls SetInputFocus(A)
 X11-queue: FocusIn(A)
 A is active Wine window.

 Wine: Application calls CreateWindow(B) -> calls SetInputFocus(B)
 X11-queue: FocusIn(A),FocusIn(B)
 B is active Wine window.

 Wine: Processing event FocusIn(A) -> calls SetInputFocus(A)
 X11-queue: FocusIn(B),FocusIn(A)
 A is active Wine window.

 Wine: Processing event FocusIn(B) -> calls SetInputFocus(B)
 X11-queue: FocusIn(A),FocusIn(B)
 B is active Wine window.

 Wine: Processing event FocusIn(A) -> calls SetInputFocus(A)
 X11-queue: FocusIn(B),FocusIn(A)
 A is active Wine window.

 ... (livelock!)

The following patch removes this livelock. However, it still
makes wine focus fluctuate, which I don't believe Windows focus
does (not verified!). But at least the end result - focus held by
window B in finite time scale - is correct:

 Wine: Application calls CreateWindow(A) -> calls SetInputFocus(A)
 X11-queue: FocusIn(A) 
 A is active Wine window.

 Wine: Application calls CreateWindow(B) -> calls SetInputFocus(B)
 X11-queue: FocusIn(A),FocusIn(B)
 B is active Wine window.

 Wine: Processing event FocusIn(A)
 X11-queue: FocusIn(B)
 A is active Wine window.

 Wine: Processing event FocusIn(B)
 X11-queue: -
 B is active Wine window.

Changelog:
  Fixed focus related livelock.

Index: wine/windows/x11drv/event.c
===================================================================
RCS file: /home/wine/wine/windows/x11drv/event.c,v
retrieving revision 1.107
diff -u -r1.107 event.c
--- wine/windows/x11drv/event.c 2001/08/24 00:27:00     1.107
+++ wine/windows/x11drv/event.c 2001/08/31 18:10:49
@@ -70,6 +70,9 @@
 /* The last X window which had the focus */
 static Window glastXFocusWin = 0;
 
+/* The current X window that has focus */
+extern Window currentX11FocusWindow;
+
 static const char * const event_names[] =
 {
   "", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
@@ -559,6 +562,8 @@
         wine_tsx11_unlock();
     }
 
+    currentX11FocusWindow = event->window;
+
     if (event->detail != NotifyPointer && hWnd != GetForegroundWindow())
     {
         SetForegroundWindow( hWnd );
@@ -576,6 +581,10 @@
 {
     /* Save the last window which had the focus */
     glastXFocusWin = event->window;
+
+    if(event->window == currentX11FocusWindow)
+        currentX11FocusWindow = 0;
+
     if (!hWnd) return;
     if (GetWindowLongA( hWnd, GWL_STYLE ) & WS_DISABLED) glastXFocusWin = 0;
 

Index: wine/dlls/x11drv/window.c
===================================================================
RCS file: /home/wine/wine/dlls/x11drv/window.c,v
retrieving revision 1.20
diff -u -r1.20 window.c
--- wine/dlls/x11drv/window.c   2001/08/24 19:28:21     1.20
+++ wine/dlls/x11drv/window.c   2001/08/31 18:11:10
@@ -43,6 +43,7 @@
 Atom wmChangeState = None;
 Atom kwmDockWindow = None;
 Atom _kde_net_wm_system_tray_window_for = None; /* KDE 2 Final */
+Window currentX11FocusWindow = 0;
 
 
 /***********************************************************************
@@ -1141,8 +1142,13 @@
 
         /* we must not use CurrentTime (ICCCM), so try to use last message time instead */
         /* FIXME: this is not entirely correct */
-        XSetInputFocus( display, win, RevertToParent,
-                        /*CurrentTime*/ GetMessageTime() + X11DRV_server_startticks );
+        if(currentX11FocusWindow != win) {
+           XSetInputFocus( display, win, RevertToParent,
+                           /*CurrentTime*/ 
+                           GetMessageTime() + X11DRV_server_startticks );
+           currentX11FocusWindow = win;
+        }
+
         if (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_PRIVATE)
             XInstallColormap( display, X11DRV_PALETTE_PaletteXColormap );
     }

-- 
Jukka Heinonen <http://www.iki.fi/jhei/>


-- 
Jukka Heinonen <http://www.iki.fi/jhei/>




More information about the wine-patches mailing list