import QtQuick import Quickshell import Quickshell.Io import "." as M Row { id: root spacing: 4 required property var bar property var _allWorkspaces: [] property int _activeId: -1 readonly property string _output: bar.screen?.name ?? "" readonly property var _workspaces: _allWorkspaces.filter(w => w.output === root._output) // Initial state Process { id: initProc running: true command: ["niri", "msg", "--json", "workspaces"] stdout: StdioCollector { onStreamFinished: { try { const ws = JSON.parse(text); root._allWorkspaces = ws.sort((a, b) => a.idx - b.idx); for (const w of ws) { if (w.is_focused) root._activeId = w.id; } } catch (e) {} } } } // Live updates Process { id: eventStream running: true command: ["niri", "msg", "--json", "event-stream"] stdout: SplitParser { splitMarker: "\n" onRead: line => { try { const ev = JSON.parse(line); if (ev.WorkspacesChanged !== undefined) { root._allWorkspaces = ev.WorkspacesChanged.workspaces.sort((a, b) => a.idx - b.idx); } else if (ev.WorkspaceActivated !== undefined) { if (ev.WorkspaceActivated.focused) root._activeId = ev.WorkspaceActivated.id; } } catch (e) {} } } } Process { id: switchProc property int wsId: -1 command: ["niri", "msg", "action", "focus-workspace", String(wsId)] } Repeater { model: root._workspaces delegate: Rectangle { id: pill required property var modelData readonly property bool active: modelData.id === root._activeId HoverHandler { onHoveredChanged: { const name = pill.modelData.name || ("Workspace " + pill.modelData.idx); if (hovered) { M.FlyoutState.text = name; M.FlyoutState.itemX = pill.mapToGlobal(pill.width / 2, 0).x - (QsWindow.window?.screen?.x ?? 0); M.FlyoutState.screen = QsWindow.window?.screen ?? null; M.FlyoutState.visible = true; } else { M.FlyoutState.visible = false; } } } width: 20 height: 20 radius: M.Theme.radius color: pill.active ? M.Theme.base0D : M.Theme.base02 Behavior on color { ColorAnimation { duration: 150 } } Text { anchors.centerIn: parent text: pill.modelData.idx color: pill.active ? M.Theme.base00 : M.Theme.base04 font.pixelSize: M.Theme.fontSize - 2 font.family: M.Theme.fontFamily font.bold: pill.active } MouseArea { anchors.fill: parent cursorShape: Qt.PointingHandCursor onClicked: { switchProc.wsId = pill.modelData.id; switchProc.running = true; } } } } }