Fix for focus loops

Jukka Heinonen jhei at iki.fi
Tue Apr 30 15:26:29 CDT 2002


This is perhaps third or fourth time I send some
kind of patch that would fix this annoying bug
that locks several games (unless you use desktop
mode). This time I try to make the patch as small as
possible.

The patch should not change how Wine handles
focus (even though Wine focus handling is quite
far from ICCCM compliance). The patch adds one 
SetFocus call, the missing of which is actually bug 
because it means that X11 and Wine may have different 
ideas about which window has focus.

Changelog:
  Changed the input model of managed windows from
  passive input into globally active input.
  Moved code to detect focus changes from FocusIn
  handler to WM_TAKE_FOCUS handler.


Index: dlls/x11drv/window.c
===================================================================
RCS file: /home/wine/wine/dlls/x11drv/window.c,v
retrieving revision 1.31
diff -u -b -r1.31 window.c
--- dlls/x11drv/window.c        9 Mar 2002 23:44:35 -0000       1.31
+++ dlls/x11drv/window.c        30 Apr 2002 20:02:31 -0000
@@ -637,8 +637,7 @@
     winContext     = XUniqueContext();
     wmProtocols    = XInternAtom( display, "WM_PROTOCOLS", False );
     wmDeleteWindow = XInternAtom( display, "WM_DELETE_WINDOW", False );
-/*    wmTakeFocus    = XInternAtom( display, "WM_TAKE_FOCUS", False );*/
-    wmTakeFocus = 0;  /* not yet */
+    wmTakeFocus    = XInternAtom( display, "WM_TAKE_FOCUS", False );
     dndProtocol = XInternAtom( display, "DndProtocol" , False );
     dndSelection = XInternAtom( display, "DndSelection" , False );
     wmChangeState = XInternAtom( display, "WM_CHANGE_STATE", False );



Index: windows/x11drv/event.c
===================================================================
RCS file: /home/wine/wine/windows/x11drv/event.c,v
retrieving revision 1.115
diff -u -b -r1.115 event.c
--- windows/x11drv/event.c      22 Mar 2002 01:03:36 -0000      1.115
+++ windows/x11drv/event.c      30 Apr 2002 20:03:05 -0000
@@ -56,6 +56,7 @@
 
 extern Atom wmProtocols;
 extern Atom wmDeleteWindow;
+extern Atom wmTakeFocus;
 extern Atom dndProtocol;
 extern Atom dndSelection;
 
@@ -99,6 +100,7 @@
 static void EVENT_SelectionClear( HWND hWnd, XSelectionClearEvent *event);
 static void EVENT_PropertyNotify( XPropertyEvent *event );
 static void EVENT_ClientMessage( HWND hWnd, XClientMessageEvent *event );
+static void EVENT_TakeFocus( HWND hWnd, XClientMessageEvent *event );
 
 extern void X11DRV_ButtonPress( HWND hwnd, XButtonEvent *event );
 extern void X11DRV_ButtonRelease( HWND hwnd, XButtonEvent *event );
@@ -368,7 +370,15 @@
  */
 static void EVENT_FocusIn( HWND hWnd, XFocusChangeEvent *event )
 {
-    WND *pWndLastFocus;
+}
+
+
+/**********************************************************************
+ *              EVENT_TakeFocus
+ */
+static void EVENT_TakeFocus( HWND hWnd, XClientMessageEvent *event )
+{
+    HWND pWndLastFocus;
     XWindowAttributes win_attr;
     BOOL bIsDisabled;
 
@@ -391,15 +401,21 @@
             if (XGetWindowAttributes( event->display, glastXFocusWin, &win_attr ) &&
                 (win_attr.map_state == IsViewable) )
             {
+             /*
+              * FIXME: The call below is required because time stamp used by
+              *        X11DRV_SetFocus is not valid in all cases. When
+              *        that routine is fixed, this call can be deleted,
+              *        since SetFocus calls X11DRV_SetFocus.
+              */
                 XSetInputFocus( event->display, glastXFocusWin, RevertToParent, CurrentTime );
                 wine_tsx11_unlock();
+                SetFocus(pWndLastFocus);
                 return;
             }
         }
         wine_tsx11_unlock();
     }
 
-    if (event->detail != NotifyPointer && hWnd != GetForegroundWindow())
         SetForegroundWindow( hWnd );
 }
 
@@ -1252,6 +1268,11 @@
         /* Ignore the delete window request if the window has been disabled */
         if (!(GetWindowLongA( hWnd, GWL_STYLE ) & WS_DISABLED))
             PostMessageA( hWnd, WM_SYSCOMMAND, SC_CLOSE, 0 );
+    }
+    else if (event->message_type == wmProtocols &&
+            (Atom)event->data.l[0] == wmTakeFocus)
+    {
+      EVENT_TakeFocus(hWnd, event);
     }
     else if (event->message_type == dndProtocol)
     {



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



More information about the wine-patches mailing list