Subject: bug#68914: Windows makes Emacs choke on and swallow the WIN keys

From: Eli Zaretskii <[email-masked]>
Date: Sun, 04 Feb 2024 08:31:15 +0200

> From: Raffael Stocker <[email-masked]>
> Date: Sat, 03 Feb 2024 21:45:46 +0100
> 
> It seems that this might be what happens to Emacs.  Possibly Windows
> removes the keyboard hook due to a timeout, not giving Emacs a chance to
> produce a ‘WM_KEYUP’ event.  And it seems to be correlated with working
> on Windows network shares; we also have Windows Defender active, which
> might make matters worse by slowing Emacs down while it is writing to a
> file.
> 
> We have had good results with increasing the ‘LowLevelHooksTimeout’, but
> we had to set it to the maximum value of 1000 ms.  I am not sure about
> the default value; the internet claims it to be 200 ms.  A mid-range
> value (500 ms) alleviated the problem somewhat, but it seems to require
> the maximum to vanish, at least judging by a limited experience of a few
> days of observation.

It would be better to have some independent verification that this is
what happens.  Is there any way to find out whether the hook was
removed, even from outside of Emacs?  I find it hard to believe that
we could miss the 200-ms deadline on modern systems.  Are your systems
heavily loaded at times?  What kind of CPU do you have on those
systems?  Emacs can hog CPU with only a single thread, so if your
systems have a reasonably modern CPU, Windows should have plenty of
execution units to spread any additional load without preempting
Emacs.

Another idea is to add code to Emacs that measures the time it takes
Emacs to produce the WM_KEYUP event, and log some message if that
takes more than some threshold.

> - Might it be possible to find a way to trigger this behaviour using a
>   debugger?  Unfortunately, I can neither compile nor debug on the
>   Windows machines (company computers with limited usefulness...).

That's probably tricky, given the time constraints.

> - If Emacs being too slow somewhere is indeed the problem, can it be
>   sped up, maybe by putting the slow stuff in a different thread than
>   the low level keyboard handling?

According to the MS documentation, the hook is called by sending a
message to the thread that installed the hook, which in our case is
already a separate thread, not the main Lisp thread (which is likely
to be busy at times).  The thread which handles the hook callbacks is
the input thread, which is relatively light-weight and shouldn't be
too busy.

> - Can we put the workaround described above (with the LowLevelHooksTimeout
>   value) into the Emacs documentation so it is findable?

Please suggest the text to put in the manual to document this.

> In related news, I noticed that the input events constructed in
> ‘funhook’ seem to use incorrect scan codes, for example starting at line
> 2630 in w32fns.c:
> 
> --8<---------------cut here---------------start------------->8---
> inputs[0].type = INPUT_KEYBOARD;
> inputs[0].ki.wVk = hs->vkCode;
> inputs[0].ki.wScan = hs->vkCode;
> inputs[0].ki.dwFlags = KEYEVENTF_EXTENDEDKEY;
> inputs[0].ki.time = 0;
> inputs[1].type = INPUT_KEYBOARD;
> inputs[1].ki.wVk = hs->vkCode;
> inputs[1].ki.wScan = hs->vkCode;
> inputs[1].ki.dwFlags
> = KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP;
> inputs[1].ki.time = 0;
> --8<---------------cut here---------------end--------------->8---
> 
> This sets both ki.wVk and ki.wScan to the virtual-key code (0x5B for
> VK_LWIN), but the ‘KEYEVENTF_EXTENDEDKEY’ flag is set, which IIUC would
> require adding ‘0xE0’ to the virtual-key code to obtain the scan code,
> e.g. 0xE05B for LWIN [1].  Can this cause any (additional) problems?

I'm not an expert, but this code was working for years.  However, you
could try making the change you propose and see if that solves the
problem (or causes new ones).

> And, BTW, why is the callback called ‘funhook’?  Using the Windows low
> level keyboard API doesn't seem to be much fun and I can't see anyone
> get hooked on this either.

I think this question is for the author of the code.  I'm not sure he
is reading this.  There's nothing wrong with the name from my POV.

Thanks.