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