Files
quickshell_bar/widgets/Workspaces.qml
T
2026-07-26 13:48:27 +02:00

91 lines
3.6 KiB
QML

import QtQuick
import QtQuick.Layouts
import Quickshell
import Quickshell.I3
import Quickshell.Hyprland
import "../config"
import "../services"
// Workspace switcher for a single monitor. Three backends, one chip renderer
// (WorkspaceChip):
//
// * Sway/i3 and Hyprland expose the same item shape (name / active / focused
// / urgent / monitor.name / activate()), so both feed the same Repeater.
// * attwm is a different model entirely -- nine fixed tags addressed by
// bitmask, several of which can be viewed at once -- so it gets its own
// Repeater over an index range.
//
// Exactly one of the two Repeaters is ever non-empty. The `?:` and `&&` guards
// only evaluate the taken branch, which is what keeps the unused backend
// singletons from being instantiated (no stray IPC) -- see Compositor.
Row {
id: root
required property var screen // ShellScreen this bar lives on
spacing: Theme.gap
// Name of the output this bar is on, used to filter workspaces.
readonly property string monitorName: screen ? screen.name : ""
// attwm keeps tags, layout and geometry per output, so the tag row on this
// bar reflects this monitor rather than whichever one has focus.
readonly property var attwmOutput: Compositor.isAttwm
? Attwm.outputFor(monitorName)
: null
// ── Sway/i3 and Hyprland ────────────────────────────────────────────────
Repeater {
model: Compositor.isAttwm ? 0
: Compositor.isHyprland ? Hyprland.workspaces
: I3.workspaces
WorkspaceChip {
required property var modelData
// only show workspaces belonging to this monitor. Both I3Workspace
// and HyprlandWorkspace expose .monitor as an object with a .name.
visible: modelData.monitor && modelData.monitor.name === root.monitorName
label: modelData.name
active: modelData.active
focused: modelData.focused
urgent: modelData.urgent
onClicked: modelData.activate()
}
}
// ── attwm ───────────────────────────────────────────────────────────────
Repeater {
// 0 until the socket has produced a state object, so nothing is drawn
// if we guessed the window manager wrong.
model: Compositor.isAttwm ? Attwm.tagCount : 0
WorkspaceChip {
id: tag
required property int index
readonly property bool viewing: Attwm.tagActive(root.attwmOutput, index)
readonly property bool occupied: Attwm.tagOccupied(root.attwmOutput, index)
label: Attwm.tagNames[index] ?? (index + 1)
active: viewing
// Tags are per output and several outputs can view a tag at once;
// only the focused output's get the focused colour.
focused: viewing && !!root.attwmOutput && root.attwmOutput.focused
dimmed: !viewing && !occupied
dot: occupied && !viewing
// dwm's mouse bindings: view / toggle into view / send window there.
onClicked: button => {
const n = index + 1;
if (button === Qt.RightButton)
Attwm.send(`toggle-view ${n}`);
else if (button === Qt.MiddleButton)
Attwm.send(`tag ${n}`);
else
Attwm.send(`view ${n}`);
}
}
}
}