From 0be9ac4097783f3a156109259e876a9a5a484c3e Mon Sep 17 00:00:00 2001 From: bbedward Date: Tue, 9 Dec 2025 00:03:39 -0500 Subject: [PATCH] keybinds: fix cheatsheet on non niri - separate read only logic from writeread --- quickshell/Modals/KeybindsModal.qml | 10 +++-- quickshell/Services/KeybindsService.qml | 56 +++++++++++++++++++++---- 2 files changed, 56 insertions(+), 10 deletions(-) diff --git a/quickshell/Modals/KeybindsModal.qml b/quickshell/Modals/KeybindsModal.qml index 30d47c4b..a723931f 100644 --- a/quickshell/Modals/KeybindsModal.qml +++ b/quickshell/Modals/KeybindsModal.qml @@ -17,7 +17,11 @@ DankModal { modalWidth: _maxW modalHeight: _maxH onBackgroundClicked: close() - onOpened: () => Qt.callLater(() => modalFocusScope.forceActiveFocus()) + onOpened: { + Qt.callLater(() => modalFocusScope.forceActiveFocus()); + if (KeybindsService.cheatsheetAvailable) + KeybindsService.loadCheatsheet(); + } HyprlandFocusGrab { windows: [root.contentWindow] @@ -66,7 +70,7 @@ DankModal { spacing: Theme.spacingL StyledText { - text: KeybindsService.keybinds.title || "Keybinds" + text: KeybindsService.cheatsheet.title || "Keybinds" font.pixelSize: Theme.fontSizeLarge font.weight: Font.Bold color: Theme.primary @@ -82,7 +86,7 @@ DankModal { Component.onCompleted: root.activeFlickable = mainFlickable - property var rawBinds: KeybindsService.keybinds.binds || {} + property var rawBinds: KeybindsService.cheatsheet.binds || {} property var categories: { const processed = {}; for (const cat in rawBinds) { diff --git a/quickshell/Services/KeybindsService.qml b/quickshell/Services/KeybindsService.qml index 43421fc0..b21a0744 100644 --- a/quickshell/Services/KeybindsService.qml +++ b/quickshell/Services/KeybindsService.qml @@ -22,6 +22,18 @@ Singleton { property bool available: CompositorService.isNiri && shortcutInhibitorAvailable property string currentProvider: "niri" + + readonly property string cheatsheetProvider: { + if (CompositorService.isNiri) + return "niri"; + if (CompositorService.isHyprland) + return "hyprland"; + return ""; + } + property bool cheatsheetAvailable: cheatsheetProvider !== "" + property bool cheatsheetLoading: false + property var cheatsheet: ({}) + property bool loading: false property bool saving: false property bool fixing: false @@ -58,17 +70,14 @@ Singleton { signal bindSaveCompleted(bool success) signal bindRemoved(string key) signal dmsBindsFixed - - Component.onCompleted: { - if (available) - Qt.callLater(loadBinds); - } + signal cheatsheetLoaded Connections { target: CompositorService function onCompositorChanged() { - if (CompositorService.isNiri) - Qt.callLater(root.loadBinds); + if (!CompositorService.isNiri) + return; + Qt.callLater(root.loadBinds); } } @@ -80,6 +89,31 @@ Singleton { } } + Process { + id: cheatsheetProcess + running: false + + stdout: StdioCollector { + onStreamFinished: { + try { + root.cheatsheet = JSON.parse(text); + } catch (e) { + console.error("[KeybindsService] Failed to parse cheatsheet:", e); + root.cheatsheet = {}; + } + root.cheatsheetLoading = false; + root.cheatsheetLoaded(); + } + } + + onExited: exitCode => { + if (exitCode === 0) + return; + console.warn("[KeybindsService] Cheatsheet load failed with code:", exitCode); + root.cheatsheetLoading = false; + } + } + Process { id: loadProcess running: false @@ -199,6 +233,14 @@ Singleton { loadBinds(true); } + function loadCheatsheet() { + if (cheatsheetProcess.running || !cheatsheetAvailable) + return; + cheatsheetLoading = true; + cheatsheetProcess.command = ["dms", "keybinds", "show", cheatsheetProvider]; + cheatsheetProcess.running = true; + } + function loadBinds(showLoading) { if (loadProcess.running || !available) return;