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: Wed, 14 Feb 2024 21:20:35 +0100 Message-ID: References: <86cyt1qvmt.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="6111"; 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 Wed Feb 14 21:59:00 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 1raMLM-0001Ly-1b for geb-bug-gnu-emacs@m.gmane-mx.org; Wed, 14 Feb 2024 21:59:00 +0100 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1raML9-0001TL-JQ; Wed, 14 Feb 2024 15:58:47 -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 1raML7-0001So-3e for bug-gnu-emacs@gnu.org; Wed, 14 Feb 2024 15:58:45 -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 1raML6-0001ZH-QB for bug-gnu-emacs@gnu.org; Wed, 14 Feb 2024 15:58:44 -0500 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1raMLO-0003Z7-0g for bug-gnu-emacs@gnu.org; Wed, 14 Feb 2024 15:59: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: Wed, 14 Feb 2024 20:59:01 +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.170794433013685 (code B ref 69083); Wed, 14 Feb 2024 20:59:01 +0000 Original-Received: (at 69083) by debbugs.gnu.org; 14 Feb 2024 20:58:50 +0000 Original-Received: from localhost ([127.0.0.1]:53255 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1raMLB-0003Yf-SA for submit@debbugs.gnu.org; Wed, 14 Feb 2024 15:58:50 -0500 Original-Received: from mail-out.m-online.net ([212.18.0.9]:53003) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1raML8-0003YV-Td for 69083@debbugs.gnu.org; Wed, 14 Feb 2024 15:58:48 -0500 Original-Received: from frontend01.mail.m-online.net (unknown [192.168.8.182]) by mail-out.m-online.net (Postfix) with ESMTP id 4TZrBq365Cz1qsPZ; Wed, 14 Feb 2024 21:58:27 +0100 (CET) Original-Received: from localhost (dynscan1.mnet-online.de [192.168.6.68]) by mail.m-online.net (Postfix) with ESMTP id 4TZrBq1tBnz1qqlW; Wed, 14 Feb 2024 21:58:27 +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 s5Wecemvidn9; Wed, 14 Feb 2024 21:58:25 +0100 (CET) X-Auth-Info: swj2Jo+6+H9jcdyJvNGXPJNkF6MHP4A5ILBd8okrMpJXsGDlEdaKqi5oUXoVzNS3 Original-Received: from Whiteflame (ppp-212-114-182-219.dynamic.mnet-online.de [212.114.182.219]) (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; Wed, 14 Feb 2024 21:58:25 +0100 (CET) In-reply-to: <86cyt1qvmt.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:280031 Archived-At: --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Eli Zaretskii writes: > So we need to load that DLL at run time via LoadLibrary, ... I have added that. > (I'm a bit surprised that Remote Desktop Services need to be used for > this purpose. Are you sure there's no other way for Emacs to know > that the system is going to be locked? Where did you read about the > need to reset the keyboard hook state in that case, and the way to do > it?) For me, the need to reset the hook state is implied by the existence of the =E2=80=98reset_w32_kbdhook_state=E2=80=99 function defined in =E2=80=98= w32fns.c=E2=80=99 and its call site. This function has been there since 2016, but was never called, because the =E2=80=98WM_WTSSESSION_CHANGE=E2=80=99 message wasn't r= eceived. >From [0]: MS> This message is sent only to applications that have registered to MS> receive this message by calling WTSRegisterSessionNotification. This seems to be the only way to find out it's being locked; at least I couldn't find anything indicating otherwise on the Microsoft website and a quick web search didn't turn up anything either. >> To receive session notifications, one must provide a window handle, >> which is fine if Emacs does not run in console mode. I don't know >> whether it is possible to get these notifications in console Emacs; at >> least using the console handle didn't work for me. > > Please try the technique used by the function find_child_console which > is defined in w32proc.c. Unfortunately, this didn't work for me. I tried calling =E2=80=98EnumWindows(find_child_console, ...)=E2=80=99 with a =E2=80=98chil= d_process=E2=80=99 instance containing the current process id as returned by =E2=80=98GetCurrentProcess= Id=E2=80=99, but I don't seem to get a useful window handle. I must be doing something wrong here. OTOH, [1] says: MS> Note For Windows 8 and later, EnumWindows enumerates only top-level MS> windows of desktop apps. Does this mean that =E2=80=98EnumWindows=E2=80=99 it doesn't work for conso= le windows or is this remark irrelevant here? I am not familiar with the Windows terminology. Come to think of it, don't I need the window handle of the console window that Emacs is running in, which would imply that a handle for Emacs' pid doesn't exist? I was starting Emacs in cmd.exe using =E2=80=98e= macs -Q -nw=E2=80=99, so I would probably have to find the pid of the =E2=80=98c= md=E2=80=99 process first, right? >> I also noticed that while the keyboard hook is set up in console mode >> using =E2=80=98setup_w32_kbdhook=E2=80=99, there does not seem to be a c= orresponding >> call to =E2=80=98remove_w32_kbdhook=E2=80=99. > > Doesn't Windows remove the hook when the process exits? According to [2] we have to remove the hook: MS> Before terminating, an application must call the UnhookWindowsHookEx MS> function function to free system resources associated with the hook. >> Also, in console mode the keyboard hook is always installed, while >> in GUI Emacs it is only installed when =E2=80=98WINDOWSNT=E2=80=99 is de= fined. > > That's because w32console.c is not compiled into the Cygwin build > (which does not define WINDOWSNT), whereas w32fns.c is. Ok, that makes sense, I have removed my superfluous #ifdef. > Do we really need to use WTSRegisterSessionNotificationEx? Can't we > use WTSRegisterSessionNotification instead? AFAIK, the latter is > available since Windows XP, whereas the former only since Vista. Yes, =E2=80=98WTSRegisterSessionNotification=E2=80=99 works, too. However,= [3] says that the minimum supported client here is Windows Vista, as with the =E2=80=98-Ex=E2=80=99 version. I attached my current patch version. Regards, Raffael [0] https://learn.microsoft.com/en-us/windows/win32/termserv/wm-wtssession-= change [1] https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-= enumwindows [2] https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-= setwindowshookexa [3] https://learn.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi3= 2-wtsregistersessionnotification --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=reset_kbdhook_1.patch Content-Description: reset kbdhook patch diff --git a/src/w32console.c b/src/w32console.c index 0936b5f37e6..2161e738252 100644 --- a/src/w32console.c +++ b/src/w32console.c @@ -822,7 +822,9 @@ initialize_w32_display (struct terminal *term, int *width, int *height) w32_initialize_display_info (build_string ("Console")); /* Set up the keyboard hook. */ - setup_w32_kbdhook (); + /* FIXME where can this be cleaned up, that is, where can we call + remove_w32_kbdhook? */ + setup_w32_kbdhook (NULL); } diff --git a/src/w32fns.c b/src/w32fns.c index 8d4bd00b91c..1f2a68c2fed 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)RegisterSessionNotificationEx */ #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; @@ -2744,7 +2749,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,17 +2805,35 @@ setup_w32_kbdhook (void) /* Set the hook. */ kbdhook.hook = SetWindowsHookEx (WH_KEYBOARD_LL, funhook, GetModuleHandle (NULL), 0); + if (hwnd != NULL) + { + HMODULE wtsapi32_lib = LoadLibrary ("wtsapi32.dll"); + WTSRegisterSessionNotification_Proc WTSRegisterSessionNotification_fn + = (WTSRegisterSessionNotification_Proc) + get_proc_addr (wtsapi32_lib, "WTSRegisterSessionNotification"); + if (WTSRegisterSessionNotification_fn != NULL) + WTSRegisterSessionNotification_fn (hwnd, NOTIFY_FOR_THIS_SESSION); + } } } /* Remove the hook. */ void -remove_w32_kbdhook (void) +remove_w32_kbdhook (HWND hwnd) { kbdhook.hook_count--; if (kbdhook.hook_count == 0 && w32_kbdhook_active) { UnhookWindowsHookEx (kbdhook.hook); + if (hwnd != NULL) + { + HMODULE wtsapi32_lib = GetModuleHandle ("wtsapi32.dll"); + WTSUnRegisterSessionNotification_Proc WTSUnRegisterSessionNotification_fn + = (WTSUnRegisterSessionNotification_Proc) + get_proc_addr (wtsapi32_lib, "WTSUnRegisterSessionNotification"); + if (WTSUnRegisterSessionNotification_fn != NULL) + WTSUnRegisterSessionNotification_fn (hwnd); + } kbdhook.hook = NULL; } } @@ -5301,13 +5324,13 @@ 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 case WM_DESTROY: #ifdef WINDOWSNT - remove_w32_kbdhook (); + remove_w32_kbdhook (hwnd); #endif CoUninitialize (); return 0; diff --git a/src/w32term.h b/src/w32term.h index 29ace0b2797..374c8055ed8 100644 --- a/src/w32term.h +++ b/src/w32term.h @@ -779,8 +779,8 @@ #define FILE_NOTIFICATIONS_SIZE 16384 #ifdef WINDOWSNT /* Keyboard hooks. */ -extern void setup_w32_kbdhook (void); -extern void remove_w32_kbdhook (void); +extern void setup_w32_kbdhook (HWND); +extern void remove_w32_kbdhook (HWND); extern int check_w32_winkey_state (int); #define w32_kbdhook_active (os_subtype != OS_SUBTYPE_9X) #else --=-=-=--