Subject: bug#73559: [PATCH] fix NS build focus-in event processing

From: Daniel Colascione <[email-masked]>
Date: Mon, 30 Sep 2024 10:05:09 -0700

On September 30, 2024 9:29:09 AM PDT, Eli Zaretskii <[email-masked]> wrote:
>> Date: Mon, 30 Sep 2024 08:51:27 -0700
>> From: Daniel Colascione <[email-masked]>
>> CC: [email-masked], [email-masked]
>> 
>> >That's not what I meant.  kbd_buffer_store_event doesn't trigger
>> >reading from the queue, AFAIU.  Emacs does that itself, when it
>> >becomes idle: it calls read_char as part of its main loop, and that
>> >reads from the input queue.
>> 
>> Yes. So now imagine that Emacs is idle and not the focused window. I command-tab to it. Now Emacs is the focused window. I would expect Emacs to have run the functions in focus-in-hook by now, but it didn't, because when we got focus, we queued the focus event but didn't wake up the main thread to process it. Now I hit a key. Emacs wakes up, drains its event loop (firing off focus-in-hook functions), and processes my keystroke. Isn't it correct for Emacs to run that hook immediately when it gets focus, not some time after?
>
>Yes, of course it is.
>
>What happens on MS-Windows in this case is that when the Emacs frame
>gets focus, we are sent the WM_SETFOCUS message.  That causes us to
>add to the input queue (by using kbd_buffer_store_event) an input
>event whose event->kind is FOCUS_IN_EVENT.  Immediately after that, I
>see read_char call kbd_buffer_get_event (via several intermediate
>calls), and the FOCUS_IN_EVENT is read and processed
>
>I wonder why this doesn't happen for NS.  (But I know that the NS port
>uses some tricky code to process events, so I'm hardly surprised.)
>
>> In general, I don't see why we'd wire it up such that the event queue can be non-empty and the main thread asleep indefinitely. If we have an event to process, then in all circumstances, we should process it, yes?
>
>Yes, definitely.  And AFAIU that should happen because we call
>read_char whenever we are idle.  Maybe the NS version of pselect
>sleeps indefinitely or for too long if no keyboard keys are pressed?
>On other systems, any message from the window-system exits pselect,
>but maybe that doesn't happen on NS?

It's not that the NS pselect waits too long. It's that it doesn't know to wake up. The focus event is delivered to Emacs by NS as a callback. Unless that callback, one way or another, takes some action to wake up the event loop, nothing gets processed. On Windows, we drain the event queue as a side effect of the message pump, whereas on NS there doesn't seem to be a separate pump that works this way -- just a callback.

>Does having a frequently-expiring timer cause the focus-in events to
>be processed more timely, without your patch?

I'd imagine so, but haven't been able to test yet.