diff --git a/modules/nsbar/panels/NsNotifications.qml b/modules/nsbar/panels/NsNotifications.qml index 9764dd5a..ebbc434b 100644 --- a/modules/nsbar/panels/NsNotifications.qml +++ b/modules/nsbar/panels/NsNotifications.qml @@ -71,8 +71,16 @@ NsPanel { hoverEnabled: true cursorShape: Qt.PointingHandCursor onClicked: { - for (const n of Notifs.notClosed) - n.notification?.dismiss(); + // Mirror the service's own clear() / clearNotifs shortcut: + // NotifData.close() sets `closed` (drops it from notClosed so the + // card disappears), removes it from Notifs.list, dismisses the + // server notification and destroys it. Calling + // `notification?.dismiss()` directly cleared nothing — it never + // touched the list, and is a no-op for notifications restored from + // disk (their `notification` is null). Iterate a slice() copy so + // mutating the list mid-loop is safe. + for (const n of Notifs.list.slice()) + n.close(); } } } diff --git a/modules/utilities/cards/Toggles.qml b/modules/utilities/cards/Toggles.qml index d145700a..f90c8c7b 100644 --- a/modules/utilities/cards/Toggles.qml +++ b/modules/utilities/cards/Toggles.qml @@ -2,6 +2,8 @@ pragma ComponentBehavior: Bound import QtQuick import QtQuick.Layouts +import Quickshell +import Quickshell.Io import Quickshell.Bluetooth import Caelestia.Components import Caelestia.Config @@ -17,6 +19,18 @@ StyledRect { required property DrawerVisibilities visibilities required property BarPopouts.Wrapper popouts + // NoSignal: the gamepad "Game Mode" toggle launches DeckShift gaming. Hide it + // entirely when DeckShift isn't installed (no gamescope session file) — checked + // once at load by deckshiftProbe below. + property bool deckshiftInstalled: false + + Process { + id: deckshiftProbe + running: true + command: ["test", "-f", "/usr/share/wayland-sessions/gamescope-session-steam-nm.desktop"] + onExited: (exitCode, exitStatus) => root.deckshiftInstalled = exitCode === 0 + } + readonly property var quickToggles: { const seenIds = new Set(); @@ -32,6 +46,11 @@ StyledRect { return GlobalConfig.utilities.vpn.provider.some(p => typeof p === "object" ? (p.enabled === true) : false); } + // NoSignal: drop the Game Mode tile unless DeckShift is installed. + if (item.id === "gameMode") { + return root.deckshiftInstalled; + } + seenIds.add(item.id); return true; }); @@ -126,9 +145,33 @@ StyledRect { DelegateChoice { roleValue: "gameMode" delegate: Toggle { + id: gmTog + // NoSignal: launch the DeckShift gaming session if installed; + // otherwise do nothing. (Was caelestia's cosmetic Game Mode.) + // Kept styled as an off-toggle (muted, outline icon) — the + // gamepad is a momentary LAUNCHER, not a stateful toggle. + // DEBOUNCED: a fast double-click must not fire two + // `switch-to-gaming` runs — two SDDM restarts race the + // one-shot autologin and drop you at the password greeter. + // Guard mirrors the Super+Shift+S bind + the deckshift-login + // install-check, so it no-ops if DeckShift is absent. + property bool launching: false icon: "gamepad" - checked: GameMode.enabled - onClicked: GameMode.enabled = !GameMode.enabled + disabled: launching + onClicked: { + if (gmTog.launching) + return; + gmTog.launching = true; + gmTog.internalChecked = false; // don't latch "on" + relockTimer.start(); + Quickshell.execDetached(["sh", "-c", "[ -x /usr/local/bin/switch-to-gaming ] && [ -f /usr/share/wayland-sessions/gamescope-session-steam-nm.desktop ] && exec /usr/local/bin/switch-to-gaming"]); + } + + Timer { + id: relockTimer + interval: 5000 + onTriggered: gmTog.launching = false + } } } DelegateChoice {