aboutsummaryrefslogtreecommitdiffstats
path: root/desktop
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-10-13 09:54:18 +0200
committerDanilo M. <danix@danix.xyz>2026-10-13 09:54:18 +0200
commitc635798c7e782af84ba1cf592e93619376a93d8a (patch)
tree82d3e30426a1ce199fc9566de3c01f11947de85c /desktop
parent934fdbeb44ff96d86840e20f5d69497556539aa9 (diff)
downloadquickshell-c635798c7e782af84ba1cf592e93619376a93d8a.tar.gz
quickshell-c635798c7e782af84ba1cf592e93619376a93d8a.zip
feat(island): controls panel in the status pill, island IPC
A settings icon in the status pill opens the controls panel in the same capsule the sound panel uses. Right-click on a tile closes the panel and opens its drawer page. The island IPC target reveals the island and toggles the panel, for the SUPER release bind. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'desktop')
-rw-r--r--desktop/island/Island.qml13
-rw-r--r--desktop/island/StatusPill.qml42
-rw-r--r--desktop/shell.qml8
3 files changed, 56 insertions, 7 deletions
diff --git a/desktop/island/Island.qml b/desktop/island/Island.qml
index 9cee3d5..43422dc 100644
--- a/desktop/island/Island.qml
+++ b/desktop/island/Island.qml
@@ -36,7 +36,7 @@ PanelWindow {
WlrLayershell.namespace: "quickshell-island"
WlrLayershell.keyboardFocus: panel !== "" ? WlrKeyboardFocus.OnDemand : WlrKeyboardFocus.None
- // "" or "sound".
+ // "", "sound" or "controls".
property string panel: ""
// --- reveal and hide -------------------------------------------------
@@ -61,6 +61,15 @@ PanelWindow {
else if (!hovered) hideTimer.restart();
}
+ // The keybind's way in: reveal, and open or close the controls panel.
+ // Closing goes through onPanelChanged, which starts the hide timer when
+ // the pointer is elsewhere.
+ function toggleControls() {
+ hideTimer.stop();
+ shown = true;
+ panel = panel === "controls" ? "" : "controls";
+ }
+
Timer {
id: hideTimer
interval: 400
@@ -206,5 +215,7 @@ PanelWindow {
onMenuShown: win.menuHeld = true
onOpenSound: win.panel = win.panel === "sound" ? "" : "sound"
onOpenDrawer: { win.panel = ""; win.drawer.show("sound"); }
+ onOpenControls: win.toggleControls()
+ onOpenPage: page => { win.panel = ""; win.drawer.show(page); }
}
}
diff --git a/desktop/island/StatusPill.qml b/desktop/island/StatusPill.qml
index 5ab8f95..1b84ec1 100644
--- a/desktop/island/StatusPill.qml
+++ b/desktop/island/StatusPill.qml
@@ -16,9 +16,9 @@ import QtQuick
import ".."
import "Logic.js" as Logic
-// Volume icon, tray, layout flag. The volume icon is the only way into the
-// sound panel and has no other gesture; the tray is a plain tray; the flag
-// switches layout on scroll and ignores clicks.
+// Controls icon, volume icon, tray, layout flag. The controls and volume
+// icons open their panels in this capsule; the tray is a plain tray; the
+// flag switches layout on scroll and ignores clicks.
Capsule {
id: pill
@@ -28,14 +28,20 @@ Capsule {
property string panel: ""
signal openSound()
+ signal openControls()
signal openDrawer()
+ // A drawer page, from a control tile's right-click.
+ signal openPage(string page)
// Emitted just before a tray menu opens; the menu cannot report its close.
signal menuShown()
- expanded: panel === "sound"
+ expanded: panel !== ""
restWidth: restRow.implicitWidth + 24
panelWidth: 320
- panelHeight: soundPanel.implicitHeight + 28
+ panelHeight: (panel === "controls" ? controlsPanel.implicitHeight : soundPanel.implicitHeight) + 28
+
+ // Edit mode never outlives its panel.
+ onPanelChanged: controlsPanel.editing = false
Row {
id: restRow
@@ -48,6 +54,18 @@ Capsule {
IconImage {
anchors.verticalCenter: parent.verticalCenter
implicitSize: 18
+ source: Quickshell.iconPath("preferences-system", true)
+
+ MouseArea {
+ anchors.fill: parent
+ cursorShape: Qt.PointingHandCursor
+ onClicked: pill.openControls()
+ }
+ }
+
+ IconImage {
+ anchors.verticalCenter: parent.verticalCenter
+ implicitSize: 18
source: Quickshell.iconPath(Logic.volumeIcon(pill.sound.volume, pill.sound.muted), true)
MouseArea {
@@ -116,9 +134,21 @@ Capsule {
y: 14
width: pill.panelWidth - 28
sound: pill.sound
- opacity: pill.expanded ? 1 : 0
+ opacity: pill.panel === "sound" ? 1 : 0
visible: opacity > 0
Behavior on opacity { NumberAnimation { duration: 160 } }
onOpenDrawer: pill.openDrawer()
}
+
+ ControlsPanel {
+ id: controlsPanel
+ x: 14
+ y: 14
+ width: pill.panelWidth - 28
+ sound: pill.sound
+ opacity: pill.panel === "controls" ? 1 : 0
+ visible: opacity > 0
+ Behavior on opacity { NumberAnimation { duration: 160 } }
+ onOpenDrawer: page => pill.openPage(page)
+ }
}
diff --git a/desktop/shell.qml b/desktop/shell.qml
index eac0ddd..d70b338 100644
--- a/desktop/shell.qml
+++ b/desktop/shell.qml
@@ -67,6 +67,7 @@ ShellRoot {
// The island on DP-1. It reads the sound module's service rather than
// binding PipeWire a second time.
Island {
+ id: island
sound: soundModule.service
drawer: drawer
}
@@ -85,4 +86,11 @@ ShellRoot {
function toggle() { drawer.toggle(""); }
function close() { drawer.close(); }
}
+
+ // The bare SUPER release bind reaches this:
+ // qs -p <this dir> ipc call island controls
+ IpcHandler {
+ target: "island"
+ function controls() { island.toggleControls(); }
+ }
}