[PATCH] winex11.drv: Send WM_SYSKEYDOWN if the Alt+F4 shortcut was used to close the window.
Gabriel Ivăncescu
gabrielopcode at gmail.com
Thu Aug 6 09:06:13 CDT 2020
Some applications (e.g. Brothers - A Tale of Two Sons) are sensitive to the
difference between Alt+F4 and a normal close of the window. Window Managers
typically have the Alt+F4 configured to send the WM_DELETE_WINDOW message,
which won't even send a F4 key press at all to the window. So we have to
distinguish between that and another source of that message (for example,
clicking the X button) while handling it.
Signed-off-by: Gabriel Ivăncescu <gabrielopcode at gmail.com>
---
dlls/winex11.drv/event.c | 2 ++
dlls/winex11.drv/keyboard.c | 49 +++++++++++++++++++++++++++++++++++++
dlls/winex11.drv/x11drv.h | 1 +
3 files changed, 52 insertions(+)
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c
index 07f7a1a..99077ad 100644
--- a/dlls/winex11.drv/event.c
+++ b/dlls/winex11.drv/event.c
@@ -688,6 +688,8 @@ static void handle_wm_protocols( HWND hwnd, XClientMessageEvent *event )
break;
}
}
+ else if (X11DRV_HandleKeyCloseShortcut( hwnd, event->display, event_time ))
+ return;
PostMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, 0 );
}
diff --git a/dlls/winex11.drv/keyboard.c b/dlls/winex11.drv/keyboard.c
index 48da12c..4efee15 100644
--- a/dlls/winex11.drv/keyboard.c
+++ b/dlls/winex11.drv/keyboard.c
@@ -1417,6 +1417,55 @@ BOOL X11DRV_KeyEvent( HWND hwnd, XEvent *xev )
return TRUE;
}
+/***********************************************************************
+ * X11DRV_HandleKeyCloseShortcut
+ *
+ * Handle the close shortcut (Alt+F4) on a delete window message.
+ */
+BOOL X11DRV_HandleKeyCloseShortcut(HWND hwnd, Display *display, Time event_time)
+{
+ unsigned int pressed = 0, i;
+ BYTE keystate[256];
+ char keys[32];
+ WORD scan = 0;
+
+ /* WMs handle this shortcut and not send it to the window at all,
+ so we have to query the keymap and see whether it is pressed. */
+ XQueryKeymap(display, keys);
+
+ /* The minimum keycode is always greater or equal to 8. */
+ for (i = 8; i < 256; i++)
+ {
+ switch (keyc2vkey[i])
+ {
+ case VK_MENU:
+ case VK_LMENU:
+ case VK_RMENU:
+ if (keys[i / 8] & (1 << (i % 8)))
+ pressed |= 1;
+ break;
+ case VK_F4:
+ if (keys[i / 8] & (1 << (i % 8)))
+ {
+ scan = keyc2scan[i] & 0xFF;
+ pressed |= 2;
+ }
+ break;
+ }
+ }
+ if (pressed != 3) return FALSE;
+
+ /* In this case, the Alt keystate must match, but not the VK_F4. */
+ if (!get_async_key_state(keystate)) return FALSE;
+ if (!(keystate[VK_MENU] & 0x80) || (keystate[VK_F4] & 0x80)) return FALSE;
+
+ /* Simulate the VK_F4 press, since it's eaten by the WM (the release is not). */
+ update_user_time(event_time);
+ X11DRV_send_keyboard_input(hwnd, VK_F4, scan, 0, EVENT_x11_time_to_win32_time(event_time));
+
+ return TRUE;
+}
+
/**********************************************************************
* X11DRV_KEYBOARD_DetectLayout
*
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h
index 375fd14..f294c10 100644
--- a/dlls/winex11.drv/x11drv.h
+++ b/dlls/winex11.drv/x11drv.h
@@ -632,6 +632,7 @@ extern void reset_clipping_window(void) DECLSPEC_HIDDEN;
extern void retry_grab_clipping_window(void) DECLSPEC_HIDDEN;
extern BOOL clip_fullscreen_window( HWND hwnd, BOOL reset ) DECLSPEC_HIDDEN;
extern void move_resize_window( HWND hwnd, int dir ) DECLSPEC_HIDDEN;
+extern BOOL X11DRV_HandleKeyCloseShortcut( HWND hwnd, Display *display, Time event_time ) DECLSPEC_HIDDEN;
extern void X11DRV_InitKeyboard( Display *display ) DECLSPEC_HIDDEN;
extern DWORD CDECL X11DRV_MsgWaitForMultipleObjectsEx( DWORD count, const HANDLE *handles, DWORD timeout,
DWORD mask, DWORD flags ) DECLSPEC_HIDDEN;
--
2.21.0
More information about the wine-devel
mailing list