summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author2 * r + 2 * t <61896496+soramanew@users.noreply.github.com>2025-08-16 00:10:48 +1000
committer2 * r + 2 * t <61896496+soramanew@users.noreply.github.com>2025-08-16 00:10:48 +1000
commitd8f7bac960e07504153c5d6123e4a50b4802343e (patch)
treeef6b037ed68b8475f1080a08cb480363bfe150dc
parentinternal: static bar width (diff)
downloadcaelestia-shell-d8f7bac960e07504153c5d6123e4a50b4802343e.tar.gz
caelestia-shell-d8f7bac960e07504153c5d6123e4a50b4802343e.tar.bz2
caelestia-shell-d8f7bac960e07504153c5d6123e4a50b4802343e.zip
bar/workspaces: refactor
-rw-r--r--README.md5
-rw-r--r--config/BarConfig.qml5
-rw-r--r--modules/bar/Bar.qml1
-rw-r--r--modules/bar/BarWrapper.qml1
-rw-r--r--modules/bar/components/workspaces/ActiveIndicator.qml41
-rw-r--r--modules/bar/components/workspaces/OccupiedBg.qml23
-rw-r--r--modules/bar/components/workspaces/Workspace.qml41
-rw-r--r--modules/bar/components/workspaces/Workspaces.qml73
-rw-r--r--utils/Icons.qml15
9 files changed, 96 insertions, 109 deletions
diff --git a/README.md b/README.md
index ab3f306..816a627 100644
--- a/README.md
+++ b/README.md
@@ -254,13 +254,12 @@ All configuration options are in `~/.config/caelestia/shell.json`.
},
"workspaces": {
"activeIndicator": true,
- "activeLabel": "󰮯 ",
+ "activeLabel": "󰮯",
"activeTrail": false,
"label": " ",
"occupiedBg": false,
- "occupiedLabel": "󰮯 ",
+ "occupiedLabel": "󰮯",
"perMonitorWorkspaces": true,
- "rounded": true,
"showWindows": true,
"shown": 5
}
diff --git a/config/BarConfig.qml b/config/BarConfig.qml
index bbe061b..4aaff8c 100644
--- a/config/BarConfig.qml
+++ b/config/BarConfig.qml
@@ -50,15 +50,14 @@ JsonObject {
component Workspaces: JsonObject {
property int shown: 5
- property bool rounded: true
property bool activeIndicator: true
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: "󰮯 "
+ property string occupiedLabel: "󰮯"
+ property string activeLabel: "󰮯"
}
component Tray: JsonObject {
diff --git a/modules/bar/Bar.qml b/modules/bar/Bar.qml
index ec2cae9..58a30d1 100644
--- a/modules/bar/Bar.qml
+++ b/modules/bar/Bar.qml
@@ -177,6 +177,5 @@ ColumnLayout {
visible: enabled
active: enabled
- asynchronous: true
}
}
diff --git a/modules/bar/BarWrapper.qml b/modules/bar/BarWrapper.qml
index 83ff1c3..c4ba52c 100644
--- a/modules/bar/BarWrapper.qml
+++ b/modules/bar/BarWrapper.qml
@@ -73,7 +73,6 @@ Item {
anchors.right: parent.right
active: root.shouldBeVisible || root.visible
- asynchronous: true
sourceComponent: Bar {
width: root.contentWidth
diff --git a/modules/bar/components/workspaces/ActiveIndicator.qml b/modules/bar/components/workspaces/ActiveIndicator.qml
index 3167d6e..99d6275 100644
--- a/modules/bar/components/workspaces/ActiveIndicator.qml
+++ b/modules/bar/components/workspaces/ActiveIndicator.qml
@@ -8,45 +8,38 @@ StyledRect {
id: root
required property int activeWsId
- required property list<Workspace> workspaces
+ required property Repeater workspaces
required property Item mask
- required property real maskWidth
- required property real maskHeight
- required property int 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
+ readonly property int currentWsIdx: (activeWsId - 1) % Config.bar.workspaces.shown
+
+ property real leading: workspaces.itemAt(currentWsIdx)?.y ?? 0
+ property real trailing: workspaces.itemAt(currentWsIdx)?.y ?? 0
+ property real currentSize: workspaces.itemAt(currentWsIdx)?.size ?? 0
property real offset: Math.min(leading, trailing)
property real size: {
const s = Math.abs(leading - trailing) + currentSize;
- if (Config.bar.workspaces.activeTrail && lastWs > currentWsIdx)
- return Math.min(getWsY(lastWs) + (workspaces[lastWs]?.size ?? 0) - offset, s);
+ if (Config.bar.workspaces.activeTrail && lastWs > currentWsIdx) {
+ const ws = workspaces.itemAt(lastWs);
+ // console.log(ws, lastWs);
+ return ws ? Math.min(ws.y + ws.size - offset, s) : 0;
+ }
return s;
}
property int cWs
property int lastWs
- function getWsY(idx: int): real {
- let y = 0;
- for (let i = 0; i < idx; i++)
- y += workspaces[i]?.size ?? 0;
- return y;
- }
-
onCurrentWsIdxChanged: {
lastWs = cWs;
cWs = currentWsIdx;
}
clip: true
- x: 1
- y: offset + 1
- implicitWidth: Config.bar.sizes.innerHeight - 2
- implicitHeight: size - 2
- radius: Config.bar.workspaces.rounded ? Appearance.rounding.full : 0
+ y: offset + mask.y
+ implicitWidth: Config.bar.sizes.innerWidth - Appearance.padding.small * 2
+ implicitHeight: size
+ radius: Appearance.rounding.full
color: Colours.palette.m3primary
Colouriser {
@@ -56,8 +49,8 @@ StyledRect {
x: 0
y: -parent.offset
- implicitWidth: root.maskWidth
- implicitHeight: root.maskHeight
+ implicitWidth: root.mask.implicitWidth
+ implicitHeight: root.mask.implicitHeight
anchors.horizontalCenter: parent.horizontalCenter
}
diff --git a/modules/bar/components/workspaces/OccupiedBg.qml b/modules/bar/components/workspaces/OccupiedBg.qml
index bfdbbbd..37fe4c1 100644
--- a/modules/bar/components/workspaces/OccupiedBg.qml
+++ b/modules/bar/components/workspaces/OccupiedBg.qml
@@ -9,7 +9,7 @@ import QtQuick
Item {
id: root
- required property list<Workspace> workspaces
+ required property Repeater workspaces
required property var occupied
required property int groupOffset
@@ -48,18 +48,17 @@ Item {
required property var modelData
- readonly property Workspace start: root.workspaces[modelData.start - 1 - root.groupOffset] ?? null
- readonly property Workspace end: root.workspaces[modelData.end - 1 - root.groupOffset] ?? null
+ readonly property Workspace start: root.workspaces.itemAt((modelData.start - 1) % Config.bar.workspaces.shown) ?? null
+ readonly property Workspace end: root.workspaces.itemAt((modelData.end - 1) % Config.bar.workspaces.shown) ?? null
- color: Colours.tPalette.m3surfaceContainerHigh
- radius: Config.bar.workspaces.rounded ? Appearance.rounding.full : 0
+ anchors.horizontalCenter: root.horizontalCenter
- x: start?.x ?? 0
- y: start?.y ?? 0
- implicitWidth: Config.bar.sizes.innerHeight
- implicitHeight: end?.y + end?.height - start?.y
+ y: (start?.y ?? 0) - 1
+ implicitWidth: Config.bar.sizes.innerWidth - Appearance.padding.small * 2 + 2
+ implicitHeight: start && end ? end.y + end.size - start.y + 2 : 0
- anchors.horizontalCenter: parent.horizontalCenter
+ color: Colours.layer(Colours.palette.m3surfaceContainerHigh, 2)
+ radius: Appearance.rounding.full
scale: 0
Component.onCompleted: scale = 1
@@ -70,11 +69,11 @@ Item {
}
}
- Behavior on x {
+ Behavior on y {
Anim {}
}
- Behavior on y {
+ Behavior on implicitHeight {
Anim {}
}
}
diff --git a/modules/bar/components/workspaces/Workspace.qml b/modules/bar/components/workspaces/Workspace.qml
index acfb216..6bd230b 100644
--- a/modules/bar/components/workspaces/Workspace.qml
+++ b/modules/bar/components/workspaces/Workspace.qml
@@ -6,7 +6,7 @@ import Quickshell
import QtQuick
import QtQuick.Layouts
-Item {
+ColumnLayout {
id: root
required property int index
@@ -16,41 +16,44 @@ Item {
readonly property bool isWorkspace: true // Flag for finding workspace children
// Unanimated prop for others to use as reference
- readonly property real size: childrenRect.height + (hasWindows ? Appearance.padding.smaller : 0)
+ readonly property int size: implicitHeight + (hasWindows ? Appearance.padding.small : 0)
readonly property int ws: groupOffset + index + 1
readonly property bool isOccupied: occupied[ws] ?? false
readonly property bool hasWindows: isOccupied && Config.bar.workspaces.showWindows
- Layout.preferredWidth: childrenRect.width
+ Layout.alignment: Qt.AlignHCenter
Layout.preferredHeight: size
+ spacing: 0
+
StyledText {
id: indicator
- readonly property string label: Config.bar.workspaces.label || root.ws
- readonly property string occupiedLabel: Config.bar.workspaces.occupiedLabel || label
- readonly property string activeLabel: Config.bar.workspaces.activeLabel || (root.isOccupied ? occupiedLabel : label)
+ Layout.alignment: Qt.AlignHCenter | Qt.AlignTop
+ Layout.preferredHeight: Config.bar.sizes.innerWidth - Appearance.padding.small * 2
animate: true
- text: root.activeWsId === root.ws ? activeLabel : root.isOccupied ? occupiedLabel : label
+ text: {
+ const label = Config.bar.workspaces.label || root.ws;
+ const occupiedLabel = Config.bar.workspaces.occupiedLabel || label;
+ const activeLabel = Config.bar.workspaces.activeLabel || (root.isOccupied ? occupiedLabel : label);
+ return 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
-
- width: Config.bar.sizes.innerHeight
- height: Config.bar.sizes.innerHeight
+ verticalAlignment: Qt.AlignVCenter
}
Loader {
id: windows
- active: Config.bar.workspaces.showWindows
- asynchronous: true
+ Layout.alignment: Qt.AlignHCenter
+ Layout.fillHeight: true
+ Layout.topMargin: -Config.bar.sizes.innerWidth / 10
- anchors.horizontalCenter: indicator.horizontalCenter
- anchors.top: indicator.bottom
- anchors.topMargin: -Config.bar.sizes.innerHeight / 10
+ visible: active
+ active: root.hasWindows
+ asynchronous: true
sourceComponent: Column {
spacing: 0
@@ -91,10 +94,6 @@ Item {
}
}
- Behavior on Layout.preferredWidth {
- Anim {}
- }
-
Behavior on Layout.preferredHeight {
Anim {}
}
diff --git a/modules/bar/components/workspaces/Workspaces.qml b/modules/bar/components/workspaces/Workspaces.qml
index 68e9ac1..1acc111 100644
--- a/modules/bar/components/workspaces/Workspaces.qml
+++ b/modules/bar/components/workspaces/Workspaces.qml
@@ -13,76 +13,61 @@ StyledRect {
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((activeWsId - 1) / Config.bar.workspaces.shown) * Config.bar.workspaces.shown
- implicitWidth: layout.implicitWidth + Appearance.padding.small * 2
implicitHeight: layout.implicitHeight + Appearance.padding.small * 2
+ implicitWidth: Config.bar.sizes.innerWidth
+
color: Colours.tPalette.m3surfaceContainer
radius: Appearance.rounding.full
- Item {
- id: inner
+ Loader {
+ active: Config.bar.workspaces.occupiedBg
+ asynchronous: true
anchors.fill: parent
anchors.margins: Appearance.padding.small
- ColumnLayout {
- id: layout
-
- spacing: 0
-
- Repeater {
- model: Config.bar.workspaces.shown
-
- Workspace {
- activeWsId: root.activeWsId
- occupied: root.occupied
- groupOffset: root.groupOffset
- }
- }
+ sourceComponent: OccupiedBg {
+ workspaces: workspaces
+ occupied: root.occupied
+ groupOffset: root.groupOffset
}
+ }
- Loader {
- active: Config.bar.workspaces.occupiedBg
- asynchronous: true
+ ColumnLayout {
+ id: layout
- z: -1
- anchors.fill: parent
+ anchors.centerIn: parent
+ spacing: Math.floor(Appearance.spacing.small / 2)
- sourceComponent: OccupiedBg {
- workspaces: root.workspaces
- occupied: root.occupied
- groupOffset: root.groupOffset
- }
- }
+ Repeater {
+ id: workspaces
- Loader {
- active: Config.bar.workspaces.activeIndicator
- asynchronous: true
+ model: Config.bar.workspaces.shown
- sourceComponent: ActiveIndicator {
+ Workspace {
activeWsId: root.activeWsId
- workspaces: root.workspaces
- mask: layout
- maskWidth: inner.width
- maskHeight: inner.height
+ occupied: root.occupied
groupOffset: root.groupOffset
}
}
+ }
- MouseArea {
- anchors.fill: parent
+ Loader {
+ anchors.horizontalCenter: parent.horizontalCenter
+ active: Config.bar.workspaces.activeIndicator
+ asynchronous: true
- onPressed: event => {
- const ws = layout.childAt(event.x, event.y).index + root.groupOffset + 1;
- if (Hyprland.activeWsId !== ws)
- Hyprland.dispatch(`workspace ${ws}`);
- }
+ sourceComponent: ActiveIndicator {
+ activeWsId: root.activeWsId
+ workspaces: workspaces
+ mask: layout
}
}
}
diff --git a/utils/Icons.qml b/utils/Icons.qml
index 7551eac..3363e55 100644
--- a/utils/Icons.qml
+++ b/utils/Icons.qml
@@ -183,4 +183,19 @@ Singleton {
return "volume_down";
return "volume_mute";
}
+
+ function getSpecialWsIcon(name: string): string {
+ name = name.toLowerCase().slice("special:".length);
+ if (name === "special")
+ return "star";
+ if (name === "communication")
+ return "forum";
+ if (name === "music")
+ return "music_note";
+ if (name === "todo")
+ return "checklist";
+ if (name === "sysmon")
+ return "monitor_heart";
+ return name[0].toUpperCase();
+ }
}