shell: intent wins the settle window, and a swap is a request for a keyboard
Two gaps in the owner-change handling, both found on device. The push at adopt time can lose a race. osk-switch sleeps 0.3s before its deliberate SetVisible(true), and stevia self-shows once it has finished coming up - both land after the shell has spoken. Measured: adopt+hide 07:37:51, Visible=true 07:37:52, leaving oskOpen=false with a keyboard on the screen. Re-assert when the settle window closes so the last speaker is not the winner. And the oskSwap gesture never recorded that a swap means the user wants a keyboard, so osk-switch's re-show and the shell's stale false were racing with nothing to arbitrate them. Declare the intent first.
This commit is contained in:
parent
d7a04f27d5
commit
3aea8398a9
2 changed files with 29 additions and 4 deletions
|
|
@ -140,7 +140,23 @@ Scope {
|
|||
Timer {
|
||||
id: ownerSettleTimer
|
||||
interval: root.ownerSettleMs
|
||||
onTriggered: root.ownerSettling = false
|
||||
onTriggered: {
|
||||
root.ownerSettling = false;
|
||||
// Push once more on the way out. The first push (at adopt time)
|
||||
// can lose a race: osk-switch sleeps 0.3s and then deliberately
|
||||
// SetVisible(true), and a keyboard that self-shows on startup
|
||||
// does so after it has finished coming up — both land *after* we
|
||||
// spoke. Measured 2026-08-05: adopt+hide at 07:37:51, stevia
|
||||
// Visible=true at 07:37:52, leaving oskOpen=false while a
|
||||
// keyboard sat on the screen. Whoever spoke last during the
|
||||
// settle window does not get to be the winner; intent does.
|
||||
root.assertIntent();
|
||||
}
|
||||
}
|
||||
|
||||
function assertIntent(): void {
|
||||
if (GlobalStates.oskOpen) root.showOsk();
|
||||
else root.hideOsk();
|
||||
}
|
||||
|
||||
function adoptOwner(owner: string): void {
|
||||
|
|
@ -157,9 +173,9 @@ Scope {
|
|||
+ (previous === "" ? "" : " (was " + previous + ")")
|
||||
+ "; re-asserting oskOpen=" + GlobalStates.oskOpen);
|
||||
// Push our intent, not theirs. A fresh keyboard claiming Visible=true
|
||||
// when nobody asked for one gets closed here.
|
||||
if (GlobalStates.oskOpen) root.showOsk();
|
||||
else root.hideOsk();
|
||||
// when nobody asked for one gets closed here — and again when the
|
||||
// settle window closes, in case it spoke after we did.
|
||||
root.assertIntent();
|
||||
}
|
||||
|
||||
Connections {
|
||||
|
|
|
|||
|
|
@ -80,6 +80,15 @@ Singleton {
|
|||
// feel the same as crossing the line.
|
||||
"oskSwap": () => {
|
||||
Haptics.confirm();
|
||||
// Declare the intent before the swap, not after it. osk-switch
|
||||
// deliberately re-shows the keyboard on the new daemon ("so the
|
||||
// swap is visible immediately"), and OnScreenKeyboard re-asserts
|
||||
// oskOpen at whoever takes the sm.puri.OSK0 name. If the shell
|
||||
// did not record that a swap means "keyboard up", those two would
|
||||
// fight: osk-switch shows it, the shell pushes its stale false,
|
||||
// and which one the user gets is a race. A swap is a request for
|
||||
// a keyboard.
|
||||
GlobalStates.oskOpen = true;
|
||||
Quickshell.execDetached(["osk-switch"]);
|
||||
},
|
||||
"screenshot": () => {
|
||||
|
|
|
|||
Loading…
Reference in a new issue