RFC: fix accelerators/Alt state on Alt+TAB window switch

Krzysztof Foltman kfoltman at portal.onet.pl
Sat Mar 5 06:00:30 CST 2005


This patch fixes (or attempts to fix) a problem with Alt key being 
partially stuck on switch to different window with Alt+TAB. Partially 
means it doesn't interfere with normal characters, but it does interfere 
  with accelerator keys (ie. after switching windows Ctrl+C is reported 
as Ctrl+Alt+C). This problem is said not to happen with some window 
managers, although I don't see any mechanism that would

It does two things:

1. It sends WM_SYSKEYUP with VK_MENU on window switch.  That's what 
Windows does: it sends WM_SYSKEYUP just after WM_CANCELMODE, even if the 
Alt key is still pressed.

For some reason, the WM_CANCELMODE and WM_SYSKEYDOWN/WM_SYSKEYUP aren't 
sent to the same window in Windows. The possible explanation is that 
WM_SYSKEY* are sent to the focused window, while WM_CANCELMODE is sent 
to the top level window.

2. It resets the window menu flag on WM_CANCELMODE. The window menu flag 
is responsible for activation of window menu bar by tapping Alt. The 
change seems to be necessary on its own, however, it's essential for the 
first patch to work correctly.

Without this patch, the window menu would be activated on every Alt+TAB, 
because of WM_SYSKEYDOWN (Alt keypress in Alt+TAB)/WM_SYSKEYUP (the fake 
one generated by the first patch).

Please test this patch, regardless if you have Alt+TAB related problems 
or not. Comments or alternative solutions are welcome.

ChangeLog:
   Krzysztof Foltman (krzysztof at foltman.com)

   * WM_CANCELMODE resets menu flag in the default window procedure (so 
that releasing Alt key won't bring the menu bar is WM_CANCELMODE was 
received between WM_SYSKEYDOWN and WM_SYSKEYUP)
   * Deactivating a window sends a fake Alt key release (that's what 
Windows does immediately after deactivating a window, regardless if the 
Alt key was really released or not)

Krzysztof
-------------- next part --------------
Index: dlls/x11drv/event.c
===================================================================
RCS file: /home/wine/wine/dlls/x11drv/event.c,v
retrieving revision 1.49
diff -u -r1.49 event.c
--- dlls/x11drv/event.c	1 Mar 2005 11:52:02 -0000	1.49
+++ dlls/x11drv/event.c	5 Mar 2005 11:18:08 -0000
@@ -479,8 +479,9 @@
         wine_tsx11_unlock();
     }
     if (hwnd != GetForegroundWindow()) return;
+    TRACE("Sending WM_CANCELMODE\n");
     SendMessageA( hwnd, WM_CANCELMODE, 0, 0 );
-
+    
     /* don't reset the foreground window, if the window which is
        getting the focus is a Wine window */
 
@@ -505,6 +506,18 @@
             SetForegroundWindow( 0 );
         }
     }
+    if (GetAsyncKeyState(VK_MENU)<0)
+    {
+      INPUT fake_alt_release;
+      fake_alt_release.type = INPUT_KEYBOARD;
+      fake_alt_release.ki.wVk = VK_MENU;
+      fake_alt_release.ki.wScan = 0;
+      fake_alt_release.ki.dwFlags = KEYEVENTF_KEYUP;
+      fake_alt_release.ki.time = GetTickCount(); /* is it really this kind of timestamp ? */
+      fake_alt_release.ki.dwExtraInfo = 0;
+      SendInput(1, &fake_alt_release, sizeof(INPUT));
+    }
+
 }
 
 
Index: windows/defwnd.c
===================================================================
RCS file: /home/wine/wine/windows/defwnd.c,v
retrieving revision 1.104
diff -u -r1.104 defwnd.c
--- windows/defwnd.c	15 Feb 2005 21:51:06 -0000	1.104
+++ windows/defwnd.c	5 Mar 2005 11:18:10 -0000
@@ -591,6 +591,7 @@
         }
 
     case WM_CANCELMODE:
+        iMenuSysKey = 0;
         if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD)) EndMenu();
 	if (GetCapture() == hwnd) ReleaseCapture();
 	break;


More information about the wine-patches mailing list