diff options
| -rw-r--r-- | vm-manager/README.md | 14 | ||||
| -rw-r--r-- | vm-manager/VmPanel.qml | 35 |
2 files changed, 48 insertions, 1 deletions
diff --git a/vm-manager/README.md b/vm-manager/README.md index 1bc20ef..8d817f9 100644 --- a/vm-manager/README.md +++ b/vm-manager/README.md @@ -69,6 +69,20 @@ Statistics do need sampling, on a 2 second timer, but only while the drawer is open: `Virsh.sampling` follows the panel's `open`. A closed panel costs one idle process waiting on an event socket. +## Two things that bite + +**A config with no visible window exits.** The drawer is closed most of the +time, so the shell holds itself open with a 1x1 transparent window with an +empty mask, which is click-through and draws nothing. Without it the shell +loads, reports no error and quits, and since `SUPER+v` reaches it over IPC, +the key then has nothing to talk to and silently does nothing. + +**Key events reach an item, not a window.** Setting `keyboardFocus` on the +layer shell is necessary but not sufficient: `Keys.onEscapePressed` on the +PanelWindow itself never fires, because no item inside holds focus. A filled +`Item` with `focus: true` catches it, and takes focus back when the TextInput +in a delete confirmation gives it up. + ## Destructive actions `Reset`, `Force stop`, snapshot `Revert` and snapshot `Delete` each take one diff --git a/vm-manager/VmPanel.qml b/vm-manager/VmPanel.qml index 7aecaab..cf224d6 100644 --- a/vm-manager/VmPanel.qml +++ b/vm-manager/VmPanel.qml @@ -78,6 +78,20 @@ Scope { else Virsh.act(vm, action); } + // Quickshell exits once no window is visible, and the drawer is closed + // most of the time, so a 1x1 transparent window holds the process open. + // Without it the shell quits and the keybind, which reaches it over IPC, + // has nothing left to talk to. + PanelWindow { + visible: true + implicitWidth: 1 + implicitHeight: 1 + color: "transparent" + exclusionMode: ExclusionMode.Ignore + mask: Region {} + WlrLayershell.keyboardFocus: WlrKeyboardFocus.None + } + LazyLoader { active: root.open @@ -102,7 +116,26 @@ Scope { MouseArea { anchors.fill: parent; onClicked: root.close() } } - Keys.onEscapePressed: root.confirming ? root.confirming = null : root.close() + // Keys reach an item, not the window, so something inside has to + // hold focus. The TextInput in a delete confirmation takes it when + // it appears; this takes it back whenever that is gone. + Item { + id: keyCatcher + anchors.fill: parent + focus: true + + Keys.onEscapePressed: { + if (root.confirming) root.confirming = null; + else root.close(); + } + + Connections { + target: root + function onConfirmingChanged() { + if (!root.confirming) keyCatcher.forceActiveFocus(); + } + } + } Rectangle { id: drawer |
