AppKit: Synthesize per-key modifier events on focus changes#4552
AppKit: Synthesize per-key modifier events on focus changes#4552OlivierJG wants to merge 1 commit intorust-windowing:masterfrom
Conversation
On focus loss, emit synthetic KeyboardInput releases for every tracked modifier key before clearing state — previously only ModifiersChanged was emitted, leaving downstream consumers with stale per-key state. On focus gain, query CGEventSourceFlagsState for hardware truth and emit differential press/release events to synchronize. This brings macOS in line with the Windows (WM_SETFOCUS/WM_KILLFOCUS) and X11 (XI_FocusIn/XI_FocusOut) backends. See rust-windowing#1272
|
To be honest with you, I want this API to be removed from the keyboard events in a form that we use it now. This is just too error prone, you should never act on the keys that were pressed before focusing your application, and most folks don't distinguish synthetic and not synthetic + they are not cross platform in a sense we use. If you really need such API, I'd advocate to move this to a separate Event all together, and not spread into each backend. Generally, on focus lost, clients must assume that all the keys are lifted, on re-focus, some may have been latched, but they shouldn't start any repeat, etc or action, it's just bad UX all along, unless you specifically need tracking for some reason, and for such case dedicated event is better. |
|
Ok, it looks like bevy (the intended target of the fix) moved away from synthetic events anyhow: I do have a case where bevy mods get stuck on OSX, but it (currently) looks solvable without winit changes |
|
Update on findings: I think this isn't solvable within Bevy on OSX with the current winit state. The key constraint that Bevy has is that it wants to provide the user with a consistent ButtonInput that allows any window to query whether any key (modifier or not) is pressed. Bevy maintains this state by updating on events from winit (currently, ignoring synthetic). There are two types of event dropping that occur on OSX when closing a window:
The first issue can be fixed in Bevy, but the only way to resolve the second issue is to expose API to query key state or to query key state inside winit and forge some type of event that would allow Bevy to update the key state table. Note that, for Bevy, a key constraint is that switching focus between bevy windows should not affect the key table validity, so clearing the key state as it might do when the whole app loses/gains focus isn't an option. Do you have any opinion on whether winit wants to expose the necessary API/Event for this? Preferences for how it should be exposed if so? |
On focus loss, emit synthetic KeyboardInput releases for every tracked modifier key before clearing state — previously only ModifiersChanged was emitted, leaving downstream consumers with stale per-key state.
On focus gain, query CGEventSourceFlagsState for hardware truth and emit differential press/release events to synchronize. This brings macOS in line with the Windows (WM_SETFOCUS/WM_KILLFOCUS) and X11 (XI_FocusIn/XI_FocusOut) backends.
See #1272
changelogmodule if knowledge of this change could be valuable to users