add attwm support
This commit is contained in:
+62
-35
@@ -4,59 +4,86 @@ import Quickshell
|
||||
import Quickshell.I3
|
||||
import Quickshell.Hyprland
|
||||
import "../config"
|
||||
import "../services"
|
||||
|
||||
// Workspace switcher for a single monitor. Works on both Sway/i3 and Hyprland:
|
||||
// the compositor is detected once from its instance env var, and the matching
|
||||
// Quickshell backend model is used. The two backends expose the same item shape
|
||||
// (name / active / focused / urgent / monitor.name / activate()), so a single
|
||||
// chip renderer covers both. The `?:` on `model` only evaluates the taken
|
||||
// branch, so the unused backend singleton is never instantiated (no stray IPC).
|
||||
// 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
|
||||
|
||||
// Which compositor are we under? Hyprland always exports this signature.
|
||||
readonly property bool isHyprland: !!Quickshell.env("HYPRLAND_INSTANCE_SIGNATURE")
|
||||
|
||||
// Name of the output this bar is on, used to filter workspaces.
|
||||
readonly property string monitorName: screen ? screen.name : ""
|
||||
|
||||
Repeater {
|
||||
model: root.isHyprland ? Hyprland.workspaces : I3.workspaces
|
||||
// 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
|
||||
|
||||
Rectangle {
|
||||
id: chip
|
||||
// ── 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
|
||||
width: visible ? Math.max(height, label.implicitWidth + 16) : 0
|
||||
height: Theme.barHeight - Theme.gap * 2
|
||||
radius: Theme.radius
|
||||
|
||||
readonly property bool isFocused: modelData.focused
|
||||
readonly property bool isUrgent: modelData.urgent
|
||||
label: modelData.name
|
||||
active: modelData.active
|
||||
focused: modelData.focused
|
||||
urgent: modelData.urgent
|
||||
|
||||
color: isUrgent ? Theme.red
|
||||
: isFocused ? Theme.blue
|
||||
: modelData.active ? Theme.surface1
|
||||
: Theme.surface0
|
||||
onClicked: modelData.activate()
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
id: label
|
||||
anchors.centerIn: parent
|
||||
text: chip.modelData.name
|
||||
font.family: Theme.font
|
||||
font.pixelSize: Theme.fontSize
|
||||
font.bold: chip.isFocused || chip.isUrgent
|
||||
color: (chip.isFocused || chip.isUrgent) ? Theme.mantle : Theme.text
|
||||
}
|
||||
// ── 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
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: chip.modelData.activate()
|
||||
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}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user