From 43af16801fcbb7056a51ed5fd6539c74ff5c0379 Mon Sep 17 00:00:00 2001 From: Gregor Kleen Date: Fri, 12 Sep 2025 14:21:21 +0200 Subject: ... --- .../shell/quickshell/ActiveWindowDisplay.qml | 20 ++-- accounts/gkleen@sif/shell/quickshell/Bar.qml | 7 ++ .../gkleen@sif/shell/quickshell/BatteryWidget.qml | 72 +++++++------ .../shell/quickshell/BrightnessWidget.qml | 20 ++-- accounts/gkleen@sif/shell/quickshell/Clock.qml | 17 ++- .../gkleen@sif/shell/quickshell/KeyboardLayout.qml | 24 +++-- .../shell/quickshell/LidSwitchInhibitorWidget.qml | 1 + .../gkleen@sif/shell/quickshell/Lockscreen.qml | 7 +- .../gkleen@sif/shell/quickshell/PipewireWidget.qml | 40 ++++--- .../shell/quickshell/Services/MprisProxy.qml | 8 ++ .../gkleen@sif/shell/quickshell/SystemTray.qml | 43 ++++---- accounts/gkleen@sif/shell/quickshell/UnixIPC.qml | 18 ++++ .../shell/quickshell/WaylandInhibitorWidget.qml | 1 + .../shell/quickshell/WorkspaceSwitcher.qml | 11 +- .../gkleen@sif/shell/quickshell/WorktimeWidget.qml | 120 +++++++++++++++++++++ accounts/gkleen@sif/shell/quickshell/shell.qml | 3 +- 16 files changed, 307 insertions(+), 105 deletions(-) create mode 100644 accounts/gkleen@sif/shell/quickshell/Services/MprisProxy.qml create mode 100644 accounts/gkleen@sif/shell/quickshell/WorktimeWidget.qml (limited to 'accounts/gkleen@sif/shell/quickshell') diff --git a/accounts/gkleen@sif/shell/quickshell/ActiveWindowDisplay.qml b/accounts/gkleen@sif/shell/quickshell/ActiveWindowDisplay.qml index 883f9001..dcc23279 100644 --- a/accounts/gkleen@sif/shell/quickshell/ActiveWindowDisplay.qml +++ b/accounts/gkleen@sif/shell/quickshell/ActiveWindowDisplay.qml @@ -149,16 +149,22 @@ Item { hoverEnabled: true enabled: true - anchors.centerIn: parent + anchors.fill: parent - Text { - id: widgetTooltipText + Item { + anchors.fill: parent - font.pointSize: 10 - font.family: "Fira Mono" - color: "white" + Text { + id: widgetTooltipText + + anchors.centerIn: parent - text: JSON.stringify(Object.assign({}, activeWindowDisplay.activeWindow), null, 2) + font.pointSize: 10 + font.family: "Fira Mono" + color: "white" + + text: JSON.stringify(Object.assign({}, activeWindowDisplay.activeWindow), null, 2) + } } } } diff --git a/accounts/gkleen@sif/shell/quickshell/Bar.qml b/accounts/gkleen@sif/shell/quickshell/Bar.qml index f8092604..7f97bd75 100644 --- a/accounts/gkleen@sif/shell/quickshell/Bar.qml +++ b/accounts/gkleen@sif/shell/quickshell/Bar.qml @@ -1,4 +1,5 @@ import Quickshell +import Quickshell.Wayland import QtQuick PanelWindow { @@ -6,6 +7,8 @@ PanelWindow { required property var screen + WlrLayershell.namespace: "bar" + anchors { top: true left: true @@ -63,6 +66,10 @@ PanelWindow { anchors.verticalCenter: parent.verticalCenter spacing: 0 + WorktimeWidget { command: "time"; } + + WorktimeWidget { command: "today"; } + KeyboardLayout {} Item { diff --git a/accounts/gkleen@sif/shell/quickshell/BatteryWidget.qml b/accounts/gkleen@sif/shell/quickshell/BatteryWidget.qml index fd031627..da17df2a 100644 --- a/accounts/gkleen@sif/shell/quickshell/BatteryWidget.qml +++ b/accounts/gkleen@sif/shell/quickshell/BatteryWidget.qml @@ -87,42 +87,48 @@ Item { hoverEnabled: true enabled: true - anchors.centerIn: parent - - Text { - id: widgetTooltipText - - font.pointSize: 10 - font.family: "Fira Sans" - color: "white" + anchors.fill: parent - text: { - const stateStr = UPowerDeviceState.toString(root.batteryDevice.state); - var outStr = stateStr; - if (root.batteryDevice.state != UPowerDeviceState.FullyCharged) - outStr += ` ${Math.round(root.batteryDevice.percentage * 100)}%`; - - function formatTime(t) { - var res = ""; - for (const unit of [{ "s": "h", "v": 3600 }, { "s": "m", "v": 60 }, { "s": "s", "v": 1 }]) { - if (t < unit.v) - continue; - res += Math.floor(t / unit.v) + unit.s; - t %= unit.v; + Item { + anchors.fill: parent + + Text { + id: widgetTooltipText + + anchors.centerIn: parent + + font.pointSize: 10 + font.family: "Fira Sans" + color: "white" + + text: { + const stateStr = UPowerDeviceState.toString(root.batteryDevice.state); + var outStr = stateStr; + if (root.batteryDevice.state != UPowerDeviceState.FullyCharged) + outStr += ` ${Math.round(root.batteryDevice.percentage * 100)}%`; + + function formatTime(t) { + var res = ""; + for (const unit of [{ "s": "h", "v": 3600 }, { "s": "m", "v": 60 }, { "s": "s", "v": 1 }]) { + if (t < unit.v) + continue; + res += Math.floor(t / unit.v) + unit.s; + t %= unit.v; + } + return res; + } + if (root.batteryDevice.timeToEmpty != 0) { + const tStr = formatTime(Math.floor(root.batteryDevice.timeToEmpty / 60) * 60); + if (tStr) + outStr += " " + tStr; + } else if (root.batteryDevice.timeToFull != 0) { + const tStr = formatTime(Math.ceil(root.batteryDevice.timeToFull / 60) * 60); + if (tStr) + outStr += " " + tStr; } - return res; - } - if (root.batteryDevice.timeToEmpty != 0) { - const tStr = formatTime(Math.floor(root.batteryDevice.timeToEmpty / 60) * 60); - if (tStr) - outStr += " " + tStr; - } else if (root.batteryDevice.timeToFull != 0) { - const tStr = formatTime(Math.ceil(root.batteryDevice.timeToFull / 60) * 60); - if (tStr) - outStr += " " + tStr; - } - return outStr; + return outStr; + } } } } diff --git a/accounts/gkleen@sif/shell/quickshell/BrightnessWidget.qml b/accounts/gkleen@sif/shell/quickshell/BrightnessWidget.qml index 7f9c1ad0..3bb5a80e 100644 --- a/accounts/gkleen@sif/shell/quickshell/BrightnessWidget.qml +++ b/accounts/gkleen@sif/shell/quickshell/BrightnessWidget.qml @@ -62,16 +62,22 @@ Item { hoverEnabled: true enabled: true - anchors.centerIn: parent + anchors.fill: parent + + Item { + anchors.fill: parent + + Text { + id: widgetTooltipText - Text { - id: widgetTooltipText + anchors.centerIn: parent - font.pointSize: 10 - font.family: "Fira Sans" - color: "white" + font.pointSize: 10 + font.family: "Fira Sans" + color: "white" - text: `${Math.round(Brightness.currBrightness * 100)}%` + text: `${Math.round(Brightness.currBrightness * 100)}%` + } } } } diff --git a/accounts/gkleen@sif/shell/quickshell/Clock.qml b/accounts/gkleen@sif/shell/quickshell/Clock.qml index bb618f6a..b7004528 100644 --- a/accounts/gkleen@sif/shell/quickshell/Clock.qml +++ b/accounts/gkleen@sif/shell/quickshell/Clock.qml @@ -80,8 +80,8 @@ Item { } } - implicitWidth: clockTooltipContent.width - implicitHeight: clockTooltipContent.height + implicitWidth: tooltipLayout.childrenRect.width + 16 + implicitHeight: tooltipLayout.childrenRect.height + 16 color: "black" onVisibleChanged: { @@ -99,13 +99,20 @@ Item { anchors.fill: parent - WrapperItem { + Item { id: clockTooltipContent - margin: 8 + anchors.fill: parent ColumnLayout { - anchors.centerIn: parent + id: tooltipLayout + + anchors { + left: parent.left + top: parent.top + leftMargin: 8 + topMargin: 8 + } Text { id: yearLabel diff --git a/accounts/gkleen@sif/shell/quickshell/KeyboardLayout.qml b/accounts/gkleen@sif/shell/quickshell/KeyboardLayout.qml index bc3750f9..46302e54 100644 --- a/accounts/gkleen@sif/shell/quickshell/KeyboardLayout.qml +++ b/accounts/gkleen@sif/shell/quickshell/KeyboardLayout.qml @@ -87,18 +87,24 @@ Item { hoverEnabled: true enabled: true - anchors.centerIn: parent + anchors.fill: parent - Text { - id: kbdTooltipText + Item { + anchors.fill: parent - font.pointSize: 10 - font.family: "Fira Sans" - color: "white" + Text { + id: kbdTooltipText - text: { - const currentLayout = NiriService.keyboardLayouts?.names?.[NiriService.keyboardLayouts.current_idx]; - return currentLayout || ""; + anchors.centerIn: parent + + font.pointSize: 10 + font.family: "Fira Sans" + color: "white" + + text: { + const currentLayout = NiriService.keyboardLayouts?.names?.[NiriService.keyboardLayouts.current_idx]; + return currentLayout || ""; + } } } } diff --git a/accounts/gkleen@sif/shell/quickshell/LidSwitchInhibitorWidget.qml b/accounts/gkleen@sif/shell/quickshell/LidSwitchInhibitorWidget.qml index 2be0692a..8410dcda 100644 --- a/accounts/gkleen@sif/shell/quickshell/LidSwitchInhibitorWidget.qml +++ b/accounts/gkleen@sif/shell/quickshell/LidSwitchInhibitorWidget.qml @@ -16,6 +16,7 @@ Item { anchors.fill: parent hoverEnabled: true + cursorShape: Qt.PointingHandCursor onClicked: InhibitorState.lidSwitchInhibited = !InhibitorState.lidSwitchInhibited diff --git a/accounts/gkleen@sif/shell/quickshell/Lockscreen.qml b/accounts/gkleen@sif/shell/quickshell/Lockscreen.qml index 456baa98..f983388c 100644 --- a/accounts/gkleen@sif/shell/quickshell/Lockscreen.qml +++ b/accounts/gkleen@sif/shell/quickshell/Lockscreen.qml @@ -70,11 +70,6 @@ Scope { mode: Custom.SystemdInhibitorParams.Delay } - Scope { - id: mprisProxy - property list players: Mpris.players.values - } - WlSessionLock { id: lock @@ -85,7 +80,7 @@ Scope { if (locked) { NiriService.sendCommand({ "Action": { "PowerOffMonitors": {} } }); Custom.KeePassXC.lockAllDatabases(); - Array.from(mprisProxy.players).forEach(player => { + Array.from(MprisProxy.players).forEach(player => { if (player.canPause && player.isPlaying) player.pause(); }); diff --git a/accounts/gkleen@sif/shell/quickshell/PipewireWidget.qml b/accounts/gkleen@sif/shell/quickshell/PipewireWidget.qml index 3e0b8fd9..9c6b65a4 100644 --- a/accounts/gkleen@sif/shell/quickshell/PipewireWidget.qml +++ b/accounts/gkleen@sif/shell/quickshell/PipewireWidget.qml @@ -272,16 +272,22 @@ Item { onWheel: event => defaultSinkMouseArea.scrollVolume(event); - anchors.centerIn: parent + anchors.fill: parent + + Item { + anchors.fill: parent - Text { - id: volumeTooltipText + Text { + id: volumeTooltipText - font.pointSize: 10 - font.family: "Fira Sans" - color: "white" + anchors.centerIn: parent - text: `${Math.round(defaultSinkItem.modelData?.audio?.volume * 100)}%` + font.pointSize: 10 + font.family: "Fira Sans" + color: "white" + + text: `${Math.round(defaultSinkItem.modelData?.audio?.volume * 100)}%` + } } } } @@ -391,16 +397,22 @@ Item { onWheel: event => defaultSourceMouseArea.scrollVolume(event); - anchors.centerIn: parent + anchors.fill: parent + + Item { + anchors.fill: parent - Text { - id: volumeTooltipText + Text { + id: volumeTooltipText - font.pointSize: 10 - font.family: "Fira Sans" - color: "white" + anchors.centerIn: parent - text: `${Math.round(defaultSourceItem.modelData?.audio?.volume * 100)}%` + font.pointSize: 10 + font.family: "Fira Sans" + color: "white" + + text: `${Math.round(defaultSourceItem.modelData?.audio?.volume * 100)}%` + } } } } diff --git a/accounts/gkleen@sif/shell/quickshell/Services/MprisProxy.qml b/accounts/gkleen@sif/shell/quickshell/Services/MprisProxy.qml new file mode 100644 index 00000000..e3ab9755 --- /dev/null +++ b/accounts/gkleen@sif/shell/quickshell/Services/MprisProxy.qml @@ -0,0 +1,8 @@ +pragma Singleton + +import Quickshell +import Quickshell.Services.Mpris + +Scope { + property list players: Mpris.players.values +} diff --git a/accounts/gkleen@sif/shell/quickshell/SystemTray.qml b/accounts/gkleen@sif/shell/quickshell/SystemTray.qml index 351e74ee..f7b4ed96 100644 --- a/accounts/gkleen@sif/shell/quickshell/SystemTray.qml +++ b/accounts/gkleen@sif/shell/quickshell/SystemTray.qml @@ -155,32 +155,39 @@ Item { hoverEnabled: true enabled: true - margin: 8 + margin: 4 - Column { - Text { - id: tooltipTitle + anchors.fill: parent - enabled: trayItem.tooltipTitle + Item { + anchors.fill: parent - font.pointSize: 10 - font.family: "Fira Sans" - font.bold: true - color: "white" + Column { + anchors.centerIn: parent + Text { + id: tooltipTitle - text: trayItem.tooltipTitle - } + enabled: trayItem.tooltipTitle - Text { - id: tooltipDescription + font.pointSize: 10 + font.family: "Fira Sans" + font.bold: true + color: "white" - enabled: trayItem.tooltipDescription + text: trayItem.tooltipTitle + } + + Text { + id: tooltipDescription - font.pointSize: 10 - font.family: "Fira Sans" - color: "white" + enabled: trayItem.tooltipDescription - text: trayItem.tooltipDescription + font.pointSize: 10 + font.family: "Fira Sans" + color: "white" + + text: trayItem.tooltipDescription + } } } } diff --git a/accounts/gkleen@sif/shell/quickshell/UnixIPC.qml b/accounts/gkleen@sif/shell/quickshell/UnixIPC.qml index 742ef4f5..e7b7b673 100644 --- a/accounts/gkleen@sif/shell/quickshell/UnixIPC.qml +++ b/accounts/gkleen@sif/shell/quickshell/UnixIPC.qml @@ -1,7 +1,9 @@ import Quickshell import Quickshell.Io import Quickshell.Services.Pipewire +import Quickshell.Services.Mpris import qs.Services +import Custom as Custom Scope { id: root @@ -19,6 +21,14 @@ Scope { root.onCommandVolume(command.Volume); else if (command.Brightness) root.onCommandBrightness(command.Brightness); + else if (command.LockSession) + Custom.Systemd.lockSession(); + else if (command.Suspend) + Custom.Systemd.suspend(); + else if (command.Hibernate) + Custom.Systemd.hibernate(); + else if (command.Mpris) + root.onCommandMpris(command.Mpris); else console.warn("UnixIPC: Command not handled:", JSON.stringify(command)); } catch (e) { @@ -56,4 +66,12 @@ Scope { if (command === "down") Brightness.currBrightness -= 0.02 } + + function onCommandMpris(command) { + if (command.PauseAll) + Array.from(MprisProxy.players).forEach(player => { + if (player.canPause && player.isPlaying) + player.pause(); + }); + } } diff --git a/accounts/gkleen@sif/shell/quickshell/WaylandInhibitorWidget.qml b/accounts/gkleen@sif/shell/quickshell/WaylandInhibitorWidget.qml index 0633f350..0512ff51 100644 --- a/accounts/gkleen@sif/shell/quickshell/WaylandInhibitorWidget.qml +++ b/accounts/gkleen@sif/shell/quickshell/WaylandInhibitorWidget.qml @@ -25,6 +25,7 @@ Item { anchors.fill: parent hoverEnabled: true + cursorShape: Qt.PointingHandCursor onClicked: InhibitorState.waylandIdleInhibited = !InhibitorState.waylandIdleInhibited diff --git a/accounts/gkleen@sif/shell/quickshell/WorkspaceSwitcher.qml b/accounts/gkleen@sif/shell/quickshell/WorkspaceSwitcher.qml index 4cbebcc9..2d3aca1b 100644 --- a/accounts/gkleen@sif/shell/quickshell/WorkspaceSwitcher.qml +++ b/accounts/gkleen@sif/shell/quickshell/WorkspaceSwitcher.qml @@ -149,6 +149,8 @@ Row { WrapperMouseArea { id: windowMouseArea + required property int index + required property var modelData property var windowData: modelData hoverEnabled: true @@ -164,12 +166,11 @@ Row { WrapperRectangle { color: windowMouseArea.containsMouse ? "#33808080" : "transparent"; - anchors.fill: parent - WrapperItem { - anchors.fill: parent - - margin: 4 + rightMargin: 8 + leftMargin: 8 + topMargin: windowMouseArea.index == 0 ? 8 : 4 + bottomMargin: windowMouseArea.index == windowsModel.values.length - 1 ? 8 : 4 Text { id: windowLabel diff --git a/accounts/gkleen@sif/shell/quickshell/WorktimeWidget.qml b/accounts/gkleen@sif/shell/quickshell/WorktimeWidget.qml new file mode 100644 index 00000000..04bcc581 --- /dev/null +++ b/accounts/gkleen@sif/shell/quickshell/WorktimeWidget.qml @@ -0,0 +1,120 @@ +import QtQml +import Quickshell +import Quickshell.Io +import QtQuick +import Quickshell.Widgets + +Item { + id: root + + required property string command + property var state: null + + height: parent.height + width: label.contentWidth + 8 + anchors.verticalCenter: parent.verticalCenter + + Process { + id: process + running: true + command: [ @worktime@, root.command, "--waybar" ] + stdout: StdioCollector { + id: processCollector + onStreamFinished: { + try { + root.state = JSON.parse(processCollector.text); + } catch (e) { + console.warn("Worktime: Failed to parse output:", processCollector.text, e); + } + } + } + } + + Timer { + running: true + interval: 60 + repeat: true + onTriggered: process.running = true + } + + WrapperMouseArea { + id: mouseArea + + anchors.fill: parent + + enabled: true + hoverEnabled: true + + Item { + anchors.fill: parent + + Text { + id: label + + anchors.centerIn: parent + + visible: root.state?.text ?? false + text: root.state?.text ?? "" + + font.pointSize: 10 + font.family: "Fira Sans" + color: { + if (root.state?.class == "running") + return "white"; + if (root.state?.class == "over") + return "#f28a21"; + return "#555"; + } + } + } + } + + PopupWindow { + id: tooltip + + property bool nextVisible: Boolean(root.state?.tooltip ?? false) && (mouseArea.containsMouse || tooltipMouseArea.containsMouse) + + anchor { + item: mouseArea + edges: Edges.Bottom | Edges.Left + } + visible: false + + onNextVisibleChanged: hangTimer.restart() + + Timer { + id: hangTimer + interval: 100 + onTriggered: tooltip.visible = tooltip.nextVisible + } + + implicitWidth: tooltipText.contentWidth + 16 + implicitHeight: tooltipText.contentHeight + 16 + color: "black" + + WrapperMouseArea { + id: tooltipMouseArea + + enabled: true + hoverEnabled: true + + anchors.fill: parent + + Item { + anchors.fill: parent + + Text { + id: tooltipText + + anchors.centerIn: parent + + font.pointSize: 10 + font.family: "Fira Sans" + color: "white" + + text: root.state?.tooltip ?? "" + } + } + } + } +} diff --git a/accounts/gkleen@sif/shell/quickshell/shell.qml b/accounts/gkleen@sif/shell/quickshell/shell.qml index 693d741f..10c2eff6 100644 --- a/accounts/gkleen@sif/shell/quickshell/shell.qml +++ b/accounts/gkleen@sif/shell/quickshell/shell.qml @@ -20,7 +20,8 @@ ShellRoot { screen: screenScope.modelData WlrLayershell.layer: WlrLayer.Background - WlrLayershell.exclusionMode: ExclusionMode.Ignore + WlrLayershell.namespace: "background" + exclusionMode: ExclusionMode.Ignore anchors.top: true anchors.bottom: true -- cgit v1.2.3