fix: commandInsert getting stuck in insert-mode after a missed key-release#7994
fix: commandInsert getting stuck in insert-mode after a missed key-release#7994DrRaider wants to merge 2 commits into
Conversation
|
We should not do spot-fixes for broader issues like mishandling general inputs. So I do not want to proceed with this change. The diagnosis seems like a likely id for several issues, though. |
|
Agreed, this is a symptom of the broader problem: key-release events getting lost when the window loses focus while a key is held (alt-tab / compositor key-grab; happens readily on Wayland). Any widget that latches key state on press/release can stick the same way, CommandInsert is just where I caught it. It is quite impactful while playing tho, having to Happy to write this up as a general issue. If the right fix is the engine treating held keys as released (or re-syncing key state) on focus loss, that'd cover all such widgets at once rather than patching each. |
|
I think this is the starting point for general discussion: beyond-all-reason/RecoilEngine#2192 If we wanted to step outside of that discussion, then imo window control is an engine responsibility. Maybe the engine team would accept a WindowFocus callin with a similar code footprint to ViewResize. Input events and handling might move away from the engine and towards being a game responsibility, though. See linked comments. |
Work done
cmd_commandinsert.luaturns insert-mode on while its action key is held: the key-press setsmodifiers.prepend_between/modifiers.prepend_queue, and the key-release clears them. If that release is never delivered to the widget — which happens when the window loses focus while the key is still held (alt-tab, or a compositor key-grab; common on Wayland) — the flag stays set. From then onCommandNotifyconverts every order into aCMD.INSERTand returnstrue, so right-clicks stop issuing direct orders and box-select misbehaves, until a/luaui reload.This adds a
widget:Updatefailsafe that re-validates insert-mode against the real held state of the bound key(s) and clears it when none are held. Bound keys are resolved viaGetActionHotKeysfor the action+arg combinations (commandinsert prepend_between/commandinsert prepend_queue), so it works for any binding — modifier keys viaGetModKeyState, regular keys (e.g. the defaultspace) viaGetKeyState.Efficiency: the per-frame check early-outs unless a flag is set (two table reads, no engine call, no allocation). Engine state is polled only while insert-mode is actually active; the bound keys are resolved once and cached; there is no per-frame heap allocation. If the binding can't be resolved yet it fails safe (treats the key as held, so the feature is never broken, and retries).
versionbumped to 2.Test steps
space), alt-tab to another window, release the key there, return to the game → right-clicks issue direct orders. (Before: every order is inserted/queued until/luaui reload.)Testing done
Verified in live games on Linux/Wayland with an instrumented build of this exact logic (a gated log line on each auto-clear). It correctly resolved the bound key (
space) and, over a single ~3.5 h session, auto-cleared 17 genuine stuck-insert-mode occurrences — each of which would previously have required a manual/luaui reload. It did not fire during normal insert use (it only triggers while the bound key reads released), so the insert feature is unaffected. (An earlier build that polled the wrong key was discarded.)AI / LLM usage statement
Root cause was diagnosed and the fix drafted with the assistance of Claude Code (Anthropic). All code was reviewed, edited, and verified in-game by me; the testing described above is from my own play sessions.