From ae9a80c1f012686c1f65fce7ce76fdd1b77b0b71 Mon Sep 17 00:00:00 2001 From: Gregor Kleen Date: Wed, 23 Sep 2026 21:08:35 +0200 Subject: ... --- .../shell/quickshell/WorkspaceSwitcher.qml | 204 +++++++++++++++++++++ 1 file changed, 204 insertions(+) create mode 100644 accounts/gkleen@skadhi/shell/quickshell/WorkspaceSwitcher.qml (limited to 'accounts/gkleen@skadhi/shell/quickshell/WorkspaceSwitcher.qml') diff --git a/accounts/gkleen@skadhi/shell/quickshell/WorkspaceSwitcher.qml b/accounts/gkleen@skadhi/shell/quickshell/WorkspaceSwitcher.qml new file mode 100644 index 00000000..a893937a --- /dev/null +++ b/accounts/gkleen@skadhi/shell/quickshell/WorkspaceSwitcher.qml @@ -0,0 +1,204 @@ +import Quickshell +import QtQuick +import qs.Services +import Quickshell.Widgets +import QtQuick.Layouts + +Row { + id: workspaces + + required property var screen + + property var ignoreWorkspaces: @ignore_workspaces@ + + height: parent.height + anchors.verticalCenter: parent.verticalCenter + spacing: 0 + + Repeater { + model: ScriptModel { + values: { + let currWorkspaces = NiriService.workspaces; + const ignoreWorkspaces = Array.from(workspaces.ignoreWorkspaces); + currWorkspaces = currWorkspaces.filter(ws => ws.output == workspaces.screen?.name).filter(ws => ws.is_active || ignoreWorkspaces.every(iws => iws !== ws.name)); + currWorkspaces.sort((a, b) => { + if (NiriService.outputs?.[a.output]?.logical?.x !== NiriService.outputs?.[b.output]?.logical?.x) + return NiriService.outputs?.[a.output]?.logical?.x - NiriService.outputs?.[b.output]?.logical?.x + if (NiriService.outputs?.[a.output]?.logical?.y !== NiriService.outputs?.[b.output]?.logical?.y) + return NiriService.outputs?.[a.output]?.logical?.y - NiriService.outputs?.[b.output]?.logical?.y + return a.idx - b.idx; + }); + return currWorkspaces.map(o => Object.assign({}, o)); + } + } + + Item { + id: wsItem + + property var workspaceData: modelData + + width: wsLabel.contentWidth + 8 + height: parent.height + anchors.verticalCenter: parent.verticalCenter + + WrapperMouseArea { + id: mouseArea + + anchors.fill: parent + + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + enabled: true + onClicked: { + NiriService.sendCommand({ "Action": { "FocusWorkspace": { "reference": { "Id": workspaceData.id } } } }, _ => {}); + } + + Rectangle { + anchors.fill: parent + + color: { + if (mouseArea.containsMouse) { + return "#33808080"; + } + return "transparent"; + } + + Text { + id: wsLabel + + anchors.centerIn: parent + + font.pointSize: 10 + font.family: "Fira Sans" + color: { + if (workspaceData.is_active) + return "#23fd00"; + if (workspaceData.active_window_id === null) + return "#555"; + return "white"; + } + + text: workspaceData.name ? workspaceData.name : workspaceData.idx + } + } + } + + PopupWindow { + id: tooltip + + property bool nextVisible: (mouseArea.containsMouse || tooltipMouseArea.containsMouse) && [...windowsModel.values].length > 0 + + anchor { + item: mouseArea + edges: Edges.Bottom | Edges.Left + } + visible: false + + onNextVisibleChanged: hangTimer.restart() + + Timer { + id: hangTimer + interval: 100 + onTriggered: tooltip.visible = tooltip.nextVisible + } + + implicitWidth: tooltipContent.implicitWidth + implicitHeight: tooltipContent.implicitHeight + color: "black" + + WrapperMouseArea { + id: tooltipMouseArea + + hoverEnabled: true + enabled: true + + anchors.fill: parent + + WrapperItem { + id: tooltipContent + + margin: 0 + + ColumnLayout { + spacing: 0 + + Repeater { + model: ScriptModel { + id: windowsModel + + values: { + let currWindows = NiriService.windows.filter(win => win.workspace_id == wsItem.workspaceData.id); + currWindows.sort((a, b) => { + if (a.is_floating !== b.is_floating) + return b.is_floating - a.is_floating; + if (a.layout.tile_pos_in_workspace_view?.[0] !== b.layout.tile_pos_in_workspace_view?.[0]) + return a.layout.tile_pos_in_workspace_view?.[0] - b.layout.tile_pos_in_workspace_view?.[0] + if (a.layout.tile_pos_in_workspace_view?.[1] !== b.layout.tile_pos_in_workspace_view?.[1]) + return a.layout.tile_pos_in_workspace_view?.[1] - b.layout.tile_pos_in_workspace_view?.[1] + if (a.layout.pos_in_scrolling_layout?.[0] !== b.layout.pos_in_scrolling_layout?.[0]) + return a.layout.pos_in_scrolling_layout?.[0] - b.layout.pos_in_scrolling_layout?.[0] + if (a.layout.pos_in_scrolling_layout?.[1] !== b.layout.pos_in_scrolling_layout?.[1]) + return a.layout.pos_in_scrolling_layout?.[1] - b.layout.pos_in_scrolling_layout?.[1] + if (a.app_id !== b.app_id) + return a.app_id?.localeCompare(b.app_id); + + return a.title.localeCompare(b.title); + }); + return currWindows.map(o => Object.assign({}, o)); + } + } + + WrapperMouseArea { + id: windowMouseArea + + required property int index + required property var modelData + property var windowData: modelData + + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + enabled: true + + Layout.fillWidth: true + + onClicked: { + NiriService.sendCommand({ "Action": { "FocusWindow": { "id": windowData.id } } }, _ => {}) + } + + WrapperRectangle { + color: windowMouseArea.containsMouse ? "#33808080" : "transparent"; + + WrapperItem { + rightMargin: 8 + leftMargin: 8 + topMargin: windowMouseArea.index == 0 ? 8 : 4 + bottomMargin: windowMouseArea.index == windowsModel.values.length - 1 ? 8 : 4 + + Text { + id: windowLabel + + font.pointSize: 10 + font.family: "Fira Sans" + color: { + if (windowData.is_focused) + return "#23fd00"; + if (NiriService.workspaces.find(ws => ws.id == windowData.workspace_id)?.active_window_id == windowData.id) + return "white"; + return "#555"; + } + + text: windowData.title + + horizontalAlignment: Text.AlignLeft + } + } + } + } + } + } + } + } + } + } + } +} -- cgit v1.2.3