bar: per-monitor workspaces option (#394)

NOTE: option is true by default, which is a breaking change

* feat(bar): add per-monitor workspace state

* fix(bar): correct active workspace indicator

* feat(bar): make per-monitor workspaces toggleable

* fixes

* more fixes

* perMonitorWorkspaces default true + add to readme

---------

Co-authored-by: 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com>
This commit is contained in:
anders130 2025-08-13 06:53:40 +02:00 committed by GitHub
parent 3710df29f5
commit 775410393e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 21 additions and 7 deletions

View file

@ -252,6 +252,7 @@ All configuration options are in `~/.config/caelestia/shell.json`.
"label": " ",
"occupiedBg": false,
"occupiedLabel": "󰮯 ",
"perMonitorWorkspaces": true,
"rounded": true,
"showWindows": true,
"shown": 5

View file

@ -54,6 +54,7 @@ JsonObject {
property bool occupiedBg: false
property bool showWindows: true
property bool activeTrail: false
property bool perMonitorWorkspaces: true
property string label: " "
property string occupiedLabel: "󰮯 "
property string activeLabel: "󰮯 "

View file

@ -103,7 +103,9 @@ ColumnLayout {
DelegateChoice {
roleValue: "workspaces"
delegate: WrappedLoader {
sourceComponent: Workspaces {}
sourceComponent: Workspaces {
screen: root.screen
}
}
}
DelegateChoice {

View file

@ -7,13 +7,14 @@ import QtQuick
StyledRect {
id: root
required property int activeWsId
required property list<Workspace> workspaces
required property Item mask
required property real maskWidth
required property real maskHeight
required property int groupOffset
readonly property int currentWsIdx: Hyprland.activeWsId - 1 - groupOffset
readonly property int currentWsIdx: activeWsId - 1 - groupOffset
property real leading: getWsY(currentWsIdx)
property real trailing: getWsY(currentWsIdx)
property real currentSize: workspaces[currentWsIdx]?.size ?? 0

View file

@ -10,6 +10,7 @@ Item {
id: root
required property int index
required property int activeWsId
required property var occupied
required property int groupOffset
@ -32,8 +33,8 @@ Item {
readonly property string activeLabel: Config.bar.workspaces.activeLabel || (root.isOccupied ? occupiedLabel : label)
animate: true
text: Hyprland.activeWsId === root.ws ? activeLabel : root.isOccupied ? occupiedLabel : label
color: Config.bar.workspaces.occupiedBg || root.isOccupied || Hyprland.activeWsId === root.ws ? Colours.palette.m3onSurface : Colours.layer(Colours.palette.m3outlineVariant, 2)
text: root.activeWsId === root.ws ? activeLabel : root.isOccupied ? occupiedLabel : label
color: Config.bar.workspaces.occupiedBg || root.isOccupied || root.activeWsId === root.ws ? Colours.palette.m3onSurface : Colours.layer(Colours.palette.m3outlineVariant, 2)
horizontalAlignment: StyledText.AlignHCenter
verticalAlignment: StyledText.AlignVCenter

View file

@ -3,18 +3,22 @@ pragma ComponentBehavior: Bound
import qs.services
import qs.config
import qs.components
import Quickshell
import QtQuick
import QtQuick.Layouts
StyledRect {
id: root
required property ShellScreen screen
readonly property int activeWsId: Config.bar.workspaces.perMonitorWorkspaces ? (Hyprland.monitorFor(screen).activeWorkspace?.id ?? 1) : Hyprland.activeWsId
readonly property list<Workspace> workspaces: layout.children.filter(c => c.isWorkspace).sort((w1, w2) => w1.ws - w2.ws)
readonly property var occupied: Hyprland.workspaces.values.reduce((acc, curr) => {
acc[curr.id] = curr.lastIpcObject.windows > 0;
return acc;
}, {})
readonly property int groupOffset: Math.floor((Hyprland.activeWsId - 1) / Config.bar.workspaces.shown) * Config.bar.workspaces.shown
readonly property int groupOffset: Math.floor((activeWsId - 1) / Config.bar.workspaces.shown) * Config.bar.workspaces.shown
implicitWidth: layout.implicitWidth + Appearance.padding.small * 2
implicitHeight: layout.implicitHeight + Appearance.padding.small * 2
@ -31,13 +35,12 @@ StyledRect {
id: layout
spacing: 0
layer.enabled: true
layer.smooth: true
Repeater {
model: Config.bar.workspaces.shown
Workspace {
activeWsId: root.activeWsId
occupied: root.occupied
groupOffset: root.groupOffset
}
@ -63,6 +66,7 @@ StyledRect {
asynchronous: true
sourceComponent: ActiveIndicator {
activeWsId: root.activeWsId
workspaces: root.workspaces
mask: layout
maskWidth: inner.width

View file

@ -21,6 +21,10 @@ Singleton {
Hyprland.dispatch(request);
}
function monitorFor(screen: ShellScreen): HyprlandMonitor {
return Hyprland.monitorFor(screen);
}
Connections {
target: Hyprland