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. |
|
I also often have the same issue with stuck commandinsert, and tried to solve it once. I arrived to a slightly more specific diagnosis: I too identified it as a lost release event and found the engine side: SpringApp.cpp focus loss handler. Then I added a debug print to the widget's release handler and tested on Windows:
The reason as I understand it: the focus loss handler clears the modifier state at I almost made an issue with these findings but then I realized that clearing the modifiers is obviously needed. It's just impossible to release I actually started working on a fix in the widgethandler to dispatch the release to the unmodified keys actions too but I got distracted with other stuff and it's just sitting on my todo list. Importantly, this also means that my personal issue is not actually a focus loss issue at all, I just simply accidentally release the shift first and then the n, which leaves the widget in insert mode. There's some chance all the above is irrelevant and for some players the focus loss is the actual cause, maybe on Wayland or Linux, but for me on Windows it's just the order of key releases. |
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.