From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Raffael Stocker Newsgroups: gmane.emacs.bugs Subject: bug#69083: Emacs's keyboard hook state is not reset on session lock (Windows) Date: Mon, 26 Feb 2024 21:50:43 +0100 Message-ID: References: <86cyt1qvmt.fsf@gnu.org> <861q9exmhe.fsf@gnu.org> <86v86im1r9.fsf@gnu.org> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="10798"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: mu4e 1.10.8; emacs 29.2 Cc: 69083@debbugs.gnu.org To: Eli Zaretskii Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Mon Feb 26 22:10:12 2024 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1reiEl-0002Zx-7W for geb-bug-gnu-emacs@m.gmane-mx.org; Mon, 26 Feb 2024 22:10:11 +0100 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1reiEJ-00078v-4s; Mon, 26 Feb 2024 16:09:43 -0500 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1reiEE-00078Z-P2 for bug-gnu-emacs@gnu.org; Mon, 26 Feb 2024 16:09:38 -0500 Original-Received: from debbugs.gnu.org ([2001:470:142:5::43]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1reiED-0007wY-33 for bug-gnu-emacs@gnu.org; Mon, 26 Feb 2024 16:09:38 -0500 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1reiEc-0007lD-IU for bug-gnu-emacs@gnu.org; Mon, 26 Feb 2024 16:10:02 -0500 X-Loop: help-debbugs@gnu.org Resent-From: Raffael Stocker Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Mon, 26 Feb 2024 21:10:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 69083 X-GNU-PR-Package: emacs Original-Received: via spool by 69083-submit@debbugs.gnu.org id=B69083.170898177429751 (code B ref 69083); Mon, 26 Feb 2024 21:10:02 +0000 Original-Received: (at 69083) by debbugs.gnu.org; 26 Feb 2024 21:09:34 +0000 Original-Received: from localhost ([127.0.0.1]:38863 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1reiE9-0007jn-Dn for submit@debbugs.gnu.org; Mon, 26 Feb 2024 16:09:34 -0500 Original-Received: from mail-out.m-online.net ([212.18.0.10]:46309) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1reiE6-0007ja-Ot for 69083@debbugs.gnu.org; Mon, 26 Feb 2024 16:09:31 -0500 Original-Received: from frontend01.mail.m-online.net (unknown [192.168.8.182]) by mail-out.m-online.net (Postfix) with ESMTP id 4TkCrN2PX2z1syC3; Mon, 26 Feb 2024 22:08:04 +0100 (CET) Original-Received: from localhost (dynscan1.mnet-online.de [192.168.6.68]) by mail.m-online.net (Postfix) with ESMTP id 4TkCrN002Nz1qqlS; Mon, 26 Feb 2024 22:08:03 +0100 (CET) X-Virus-Scanned: amavis at mnet-online.de Original-Received: from mail.mnet-online.de ([192.168.8.182]) by localhost (dynscan1.mail.m-online.net [192.168.6.68]) (amavis, port 10024) with ESMTP id Nizch24jIfLo; Mon, 26 Feb 2024 22:08:03 +0100 (CET) X-Auth-Info: rN/PZsdlIi76GnHlTZsj959t670HXxQq5C7epjs7ckuHMkpJJia6+8MIJLVEjFUp Original-Received: from Whiteflame (ppp-212-114-182-86.dynamic.mnet-online.de [212.114.182.86]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-256) server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mail.mnet-online.de (Postfix) with ESMTPSA; Mon, 26 Feb 2024 22:08:02 +0100 (CET) In-reply-to: <86v86im1r9.fsf@gnu.org> X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.bugs:280705 Archived-At: --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Eli Zaretskii writes: >> Is there a better place where the remove_w32_kbdhook call could go such >> that cleanup can always happen? > > I think that place is term_ntproc. I have added a call to =E2=80=98remove_w32_kbdhook=E2=80=99 there, but also= left it with the WM_DESTROY message. The cleanup now always happens and the setup/remove calls are correctly nested when using multiple frames. >> >> Unfortunately, this didn't work for me. I tried calling >> >> =E2=80=98EnumWindows(find_child_console, ...)=E2=80=99 with a =E2=80= =98child_process=E2=80=99 instance >> >> containing the current process id as returned by =E2=80=98GetCurrentP= rocessId=E2=80=99, >> >> but I don't seem to get a useful window handle. >> > >> > What do you mean? What is the result of using find_child_console? >> > does the condition in find_child_console, which looks at the >> > process_id of all windows, never match the process ID of the Emacs >> > session running with -nw? Or what else goes wrong? I figured this out now. The =E2=80=98find_child_console=E2=80=99 function = looks for a =E2=80=98ConsoleWindowClass=E2=80=99 window, but the Emacs process itself o= nly has =E2=80=98Emacs Clipboard=E2=80=99 and =E2=80=98IME=E2=80=99 windows. The l= atter seems to be the one I need. I added a function =E2=80=98find_ime_window=E2=80=99 in =E2=80=98w32= console.c=E2=80=99 that checks for this window when called through =E2=80=98EnumThreadWindows=E2=80= =99. I can now register for session notifications using this window. To handle the notifications, I added some code to =E2=80=98drain_message_qu= eue=E2=80=99, calling =E2=80=98reset_w32_kbdhook_state=E2=80=99 from there. This now cor= rectly resets the hook state in console Emacs. I added =E2=80=98WINDOWSNT=E2=80=99 #ifdefs around calls to and the definit= ion of =E2=80=98reset_w32_kbdhook_state=E2=80=99, as with the setup/remove functio= ns. I also cleaned up the =E2=80=98remove_w32_kbdhook=E2=80=99 function to use the pre= viously obtained function pointer. I believe the attached version should now tick all the important boxes. Regards, Raffael --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=reset_kbdhook_2.patch Content-Description: reset_kbdhook_state patch diff --git a/src/w32.c b/src/w32.c index df5465c2135..6744b45bde7 100644 --- a/src/w32.c +++ b/src/w32.c @@ -10392,11 +10392,17 @@ check_windows_init_file (void) } } +/* from w32fns.c */ +extern void +remove_w32_kbdhook (void); + void term_ntproc (int ignored) { (void)ignored; + remove_w32_kbdhook (); + term_timers (); /* shutdown the socket interface if necessary */ diff --git a/src/w32console.c b/src/w32console.c index 0936b5f37e6..bcee9e18fe6 100644 --- a/src/w32console.c +++ b/src/w32console.c @@ -659,6 +659,24 @@ w32_face_attributes (struct frame *f, int face_id) return char_attr; } +/* The IME window is needed to receive the session notifications + required to reset the low level keyboard hook state. */ + +static BOOL CALLBACK +find_ime_window (HWND hwnd, LPARAM arg) +{ + char window_class[32]; + + GetClassName (hwnd, window_class, sizeof (window_class)); + if (strcmp (window_class, "IME") == 0) + { + *(HWND *) arg = hwnd; + return FALSE; + } + /* keep looking */ + return TRUE; +} + void initialize_w32_display (struct terminal *term, int *width, int *height) { @@ -821,8 +839,11 @@ initialize_w32_display (struct terminal *term, int *width, int *height) /* Setup w32_display_info structure for this frame. */ w32_initialize_display_info (build_string ("Console")); - /* Set up the keyboard hook. */ - setup_w32_kbdhook (); + HWND hwnd = NULL; + EnumThreadWindows (GetCurrentThreadId (), find_ime_window, (LPARAM) &hwnd); + + /* Set up the keyboard hook. */ + setup_w32_kbdhook (hwnd); } diff --git a/src/w32fns.c b/src/w32fns.c index 8d4bd00b91c..168763f7215 100644 --- a/src/w32fns.c +++ b/src/w32fns.c @@ -49,6 +49,7 @@ #define _WIN32_WINNT 0x0600 #ifdef WINDOWSNT #include #include /* for _getmbcp */ +#include /* for WTS(Un)RegisterSessionNotification */ #endif /* WINDOWSNT */ #if CYGWIN @@ -204,6 +205,10 @@ DECLARE_HANDLE(HMONITOR); typedef HRESULT (WINAPI * DwmSetWindowAttribute_Proc) (HWND hwnd, DWORD dwAttribute, IN LPCVOID pvAttribute, DWORD cbAttribute); +typedef BOOL (WINAPI * WTSRegisterSessionNotification_Proc) + (HWND hwnd, DWORD dwFlags); +typedef BOOL (WINAPI * WTSUnRegisterSessionNotification_Proc) (HWND hwnd); + TrackMouseEvent_Proc track_mouse_event_fn = NULL; ImmGetCompositionString_Proc get_composition_string_fn = NULL; ImmGetContext_Proc get_ime_context_fn = NULL; @@ -220,6 +225,7 @@ DECLARE_HANDLE(HMONITOR); SetThreadDescription_Proc set_thread_description = NULL; SetWindowTheme_Proc SetWindowTheme_fn = NULL; DwmSetWindowAttribute_Proc DwmSetWindowAttribute_fn = NULL; +WTSUnRegisterSessionNotification_Proc WTSUnRegisterSessionNotification_fn = NULL; extern AppendMenuW_Proc unicode_append_menu; @@ -307,6 +313,7 @@ #define WS_EX_NOACTIVATE 0x08000000L int hook_count; /* counter, if several windows are created */ HHOOK hook; /* hook handle */ HWND console; /* console window handle */ + HWND window; /* window handle used for session notification */ int lwindown; /* Left Windows key currently pressed (and hooked) */ int rwindown; /* Right Windows key currently pressed (and hooked) */ @@ -2744,7 +2751,7 @@ funhook (int code, WPARAM w, LPARAM l) /* Set up the hook; can be called several times, with matching remove_w32_kbdhook calls. */ void -setup_w32_kbdhook (void) +setup_w32_kbdhook (HWND hwnd) { kbdhook.hook_count++; @@ -2800,6 +2807,21 @@ setup_w32_kbdhook (void) /* Set the hook. */ kbdhook.hook = SetWindowsHookEx (WH_KEYBOARD_LL, funhook, GetModuleHandle (NULL), 0); + + /* Register session notifications so we get notified about the + computer being locked. */ + if (hwnd != NULL) + { + kbdhook.window = hwnd; + HMODULE wtsapi32_lib = LoadLibrary ("wtsapi32.dll"); + WTSRegisterSessionNotification_Proc WTSRegisterSessionNotification_fn + = (WTSRegisterSessionNotification_Proc) + get_proc_addr (wtsapi32_lib, "WTSRegisterSessionNotification"); + WTSUnRegisterSessionNotification_fn = (WTSUnRegisterSessionNotification_Proc) + get_proc_addr (wtsapi32_lib, "WTSUnRegisterSessionNotification"); + if (WTSRegisterSessionNotification_fn != NULL) + WTSRegisterSessionNotification_fn (hwnd, NOTIFY_FOR_THIS_SESSION); + } } } @@ -2811,6 +2833,9 @@ remove_w32_kbdhook (void) if (kbdhook.hook_count == 0 && w32_kbdhook_active) { UnhookWindowsHookEx (kbdhook.hook); + if (kbdhook.window != NULL + && WTSUnRegisterSessionNotification_fn != NULL) + WTSUnRegisterSessionNotification_fn (kbdhook.window); kbdhook.hook = NULL; } } @@ -2884,13 +2909,12 @@ check_w32_winkey_state (int vkey) } return 0; } -#endif /* WINDOWSNT */ /* Reset the keyboard hook state. Locking the workstation with Win-L leaves the Win key(s) "down" from the hook's point of view - the keyup event is never seen. Thus, this function must be called when the system is locked. */ -static void +void reset_w32_kbdhook_state (void) { kbdhook.lwindown = 0; @@ -2900,6 +2924,7 @@ reset_w32_kbdhook_state (void) kbdhook.suppress_lone = 0; kbdhook.winseen = 0; } +#endif /* WINDOWSNT */ /* GetKeyState and MapVirtualKey on Windows 95 do not actually distinguish between left and right keys as advertised. We test for this @@ -5301,7 +5326,7 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) #ifdef WINDOWSNT case WM_CREATE: - setup_w32_kbdhook (); + setup_w32_kbdhook (hwnd); goto dflt; #endif @@ -5312,10 +5337,12 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) CoUninitialize (); return 0; +#ifdef WINDOWSNT case WM_WTSSESSION_CHANGE: if (wParam == WTS_SESSION_LOCK) reset_w32_kbdhook_state (); goto dflt; +#endif case WM_CLOSE: wmsg.dwModifiers = w32_get_modifiers (); diff --git a/src/w32term.h b/src/w32term.h index 29ace0b2797..3120c8bd71f 100644 --- a/src/w32term.h +++ b/src/w32term.h @@ -779,8 +779,9 @@ #define FILE_NOTIFICATIONS_SIZE 16384 #ifdef WINDOWSNT /* Keyboard hooks. */ -extern void setup_w32_kbdhook (void); +extern void setup_w32_kbdhook (HWND); extern void remove_w32_kbdhook (void); +extern void reset_w32_kbdhook_state (void); extern int check_w32_winkey_state (int); #define w32_kbdhook_active (os_subtype != OS_SUBTYPE_9X) #else diff --git a/src/w32xfns.c b/src/w32xfns.c index fa7d5fbdb61..3d7a1514f72 100644 --- a/src/w32xfns.c +++ b/src/w32xfns.c @@ -413,8 +413,16 @@ drain_message_queue (void) while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) { - if (msg.message == WM_EMACS_FILENOTIFY) - retval = 1; + switch (msg.message) + { + case WM_WTSSESSION_CHANGE: + if (msg.wParam == WTS_SESSION_LOCK) + reset_w32_kbdhook_state (); + break; + case WM_EMACS_FILENOTIFY: + retval = 1; + break; + } TranslateMessage (&msg); DispatchMessage (&msg); } --=-=-=--