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": " ", "label": " ",
"occupiedBg": false, "occupiedBg": false,
"occupiedLabel": "󰮯 ", "occupiedLabel": "󰮯 ",
"perMonitorWorkspaces": true,
"rounded": true, "rounded": true,
"showWindows": true, "showWindows": true,
"shown": 5 "shown": 5

View file

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

View file

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

View file

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

View file

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

View file

@ -3,18 +3,22 @@ pragma ComponentBehavior: Bound
import qs.services import qs.services
import qs.config import qs.config
import qs.components import qs.components
import Quickshell
import QtQuick import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
StyledRect { StyledRect {
id: root 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 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) => { readonly property var occupied: Hyprland.workspaces.values.reduce((acc, curr) => {
acc[curr.id] = curr.lastIpcObject.windows > 0; acc[curr.id] = curr.lastIpcObject.windows > 0;
return acc; 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 implicitWidth: layout.implicitWidth + Appearance.padding.small * 2
implicitHeight: layout.implicitHeight + Appearance.padding.small * 2 implicitHeight: layout.implicitHeight + Appearance.padding.small * 2
@ -31,13 +35,12 @@ StyledRect {
id: layout id: layout
spacing: 0 spacing: 0
layer.enabled: true
layer.smooth: true
Repeater { Repeater {
model: Config.bar.workspaces.shown model: Config.bar.workspaces.shown
Workspace { Workspace {
activeWsId: root.activeWsId
occupied: root.occupied occupied: root.occupied
groupOffset: root.groupOffset groupOffset: root.groupOffset
} }
@ -63,6 +66,7 @@ StyledRect {
asynchronous: true asynchronous: true
sourceComponent: ActiveIndicator { sourceComponent: ActiveIndicator {
activeWsId: root.activeWsId
workspaces: root.workspaces workspaces: root.workspaces
mask: layout mask: layout
maskWidth: inner.width maskWidth: inner.width

View file

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