diff options
| author | Danilo M. <danix@danix.xyz> | 2026-10-07 18:52:19 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-10-07 18:52:19 +0200 |
| commit | 744802e1ecb44ddb4714f8922b8ee0e9e5def811 (patch) | |
| tree | 8d66ec6f99a58420038c56c1dcf27a148e008671 | |
| parent | 42feb6f8e3f088eb5707f4129eb994df7110a3e5 (diff) | |
| download | quickshell-744802e1ecb44ddb4714f8922b8ee0e9e5def811.tar.gz quickshell-744802e1ecb44ddb4714f8922b8ee0e9e5def811.zip | |
feat(island): status pill with volume, tray and layout flag
The tray makes the island the session's StatusNotifier host, which waybar
was until now.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
| -rw-r--r-- | desktop/island/StatusPill.qml | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/desktop/island/StatusPill.qml b/desktop/island/StatusPill.qml new file mode 100644 index 0000000..faf24dd --- /dev/null +++ b/desktop/island/StatusPill.qml @@ -0,0 +1,108 @@ +// Copyright (C) 2026 Danilo M. <danix@danix.xyz> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as +// published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +import Quickshell +import Quickshell.Widgets +import Quickshell.Services.SystemTray +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. +Capsule { + id: pill + + required property QtObject sound + // The island window, which tray menus are positioned against. + required property QtObject window + property string panel: "" + + signal openSound() + signal openDrawer() + + expanded: panel === "sound" + restWidth: restRow.implicitWidth + 24 + panelWidth: 320 + panelHeight: soundPanel.implicitHeight + 28 + + Row { + id: restRow + anchors.centerIn: parent + spacing: 12 + opacity: pill.expanded ? 0 : 1 + visible: opacity > 0 + Behavior on opacity { NumberAnimation { duration: 120 } } + + IconImage { + anchors.verticalCenter: parent.verticalCenter + implicitSize: 18 + source: Quickshell.iconPath(Logic.volumeIcon(pill.sound.volume, pill.sound.muted), true) + + MouseArea { + anchors.fill: parent + cursorShape: Qt.PointingHandCursor + onClicked: pill.openSound() + } + } + + Repeater { + model: SystemTray.items.values + + delegate: IconImage { + id: trayIcon + required property SystemTrayItem modelData + anchors.verticalCenter: parent.verticalCenter + implicitSize: 16 + source: modelData.icon + + MouseArea { + anchors.fill: parent + acceptedButtons: Qt.LeftButton | Qt.RightButton + cursorShape: Qt.PointingHandCursor + onClicked: mouse => { + const item = trayIcon.modelData; + const wantsMenu = mouse.button === Qt.RightButton || item.onlyMenu; + if (!wantsMenu) { item.activate(); return; } + if (!item.hasMenu) return; + const p = trayIcon.mapToItem(null, 0, trayIcon.height + 6); + item.display(pill.window, p.x, p.y); + } + } + } + } + + Image { + anchors.verticalCenter: parent.verticalCenter + width: 18 + height: 18 + sourceSize: Qt.size(18, 18) + source: Qt.resolvedUrl("assets/" + Keyboard.flag) + + WheelHandler { + onWheel: event => Keyboard.cycle(event.angleDelta.y > 0 ? "prev" : "next") + } + } + } + + SoundPanel { + id: soundPanel + x: 14 + y: 14 + width: pill.panelWidth - 28 + sound: pill.sound + opacity: pill.expanded ? 1 : 0 + visible: opacity > 0 + Behavior on opacity { NumberAnimation { duration: 160 } } + onOpenDrawer: pill.openDrawer() + } +} |
