summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author2 * r + 2 * t <61896496+soramanew@users.noreply.github.com>2025-04-30 13:49:05 +1000
committer2 * r + 2 * t <61896496+soramanew@users.noreply.github.com>2025-04-30 13:49:05 +1000
commite8fe4ef673ebb3bc89f192ad5dba0b6d54149f34 (patch)
treee82697134093d7b025c3257a3c6aa49abce483b7
parentbar: custom workspace labels (diff)
downloadcaelestia-shell-e8fe4ef673ebb3bc89f192ad5dba0b6d54149f34.tar.gz
caelestia-shell-e8fe4ef673ebb3bc89f192ad5dba0b6d54149f34.tar.bz2
caelestia-shell-e8fe4ef673ebb3bc89f192ad5dba0b6d54149f34.zip
feat: bar workspaces show windows
Better hyprland clients (update existing instead of resetting every time) Option for ws trail Custom label for occupied ws as well
-rw-r--r--config/BarConfig.qml5
-rw-r--r--modules/bar/components/workspaces/ActiveIndicator.qml18
-rw-r--r--modules/bar/components/workspaces/Workspace.qml83
-rw-r--r--services/Hyprland.qml26
4 files changed, 117 insertions, 15 deletions
diff --git a/config/BarConfig.qml b/config/BarConfig.qml
index fe0dab3..e5c0711 100644
--- a/config/BarConfig.qml
+++ b/config/BarConfig.qml
@@ -26,7 +26,10 @@ Singleton {
readonly property int shown: 10
readonly property string style: ""
readonly property bool occupiedBg: true
- readonly property string label: " "
+ readonly property bool showWindows: true
+ readonly property bool activeTrail: !showWindows // Doesn't work well with variable sized workspaces
+ readonly property string label: " "
+ readonly property string occupiedLabel: "󰮯 "
readonly property string activeLabel: "󰮯 "
}
diff --git a/modules/bar/components/workspaces/ActiveIndicator.qml b/modules/bar/components/workspaces/ActiveIndicator.qml
index 027b575..f8b0deb 100644
--- a/modules/bar/components/workspaces/ActiveIndicator.qml
+++ b/modules/bar/components/workspaces/ActiveIndicator.qml
@@ -71,16 +71,34 @@ Rectangle {
}
Behavior on leading {
+ enabled: BarConfig.workspaces.activeTrail
+
Anim {}
}
Behavior on trailing {
+ enabled: BarConfig.workspaces.activeTrail
+
Anim {
duration: Appearance.anim.durations.normal * 2
}
}
Behavior on currentSize {
+ enabled: BarConfig.workspaces.activeTrail
+
+ Anim {}
+ }
+
+ Behavior on offset {
+ enabled: !BarConfig.workspaces.activeTrail
+
+ Anim {}
+ }
+
+ Behavior on size {
+ enabled: !BarConfig.workspaces.activeTrail
+
Anim {}
}
diff --git a/modules/bar/components/workspaces/Workspace.qml b/modules/bar/components/workspaces/Workspace.qml
index a6e2b43..c5d7475 100644
--- a/modules/bar/components/workspaces/Workspace.qml
+++ b/modules/bar/components/workspaces/Workspace.qml
@@ -1,9 +1,14 @@
import "root:/widgets"
import "root:/services"
+import "root:/utils"
import "root:/config"
+import Quickshell
+import QtQuick
import QtQuick.Layouts
-StyledText {
+Item {
+ id: root
+
required property int index
required property bool vertical
required property var occupied
@@ -12,15 +17,73 @@ StyledText {
readonly property bool isWorkspace: true // Flag for finding workspace children
readonly property int ws: groupOffset + index + 1
- readonly property string label: BarConfig.workspaces.label || ws
- readonly property string activeLabel: BarConfig.workspaces.activeLabel || label
+ readonly property bool isOccupied: occupied[ws] ?? false
+
+ Layout.preferredWidth: childrenRect.width + (isOccupied && !vertical ? Appearance.padding.normal : 0)
+ Layout.preferredHeight: childrenRect.height + (isOccupied && vertical ? Appearance.padding.normal : 0)
+
+ StyledText {
+ id: indicator
+
+ readonly property string label: BarConfig.workspaces.label || root.ws
+ readonly property string occupiedLabel: BarConfig.workspaces.occupiedLabel || label
+ readonly property string activeLabel: BarConfig.workspaces.activeLabel || (root.isOccupied ? occupiedLabel : label)
+
+ animate: true
+ animateProp: "scale"
+ text: Hyprland.activeWsId === root.ws ? activeLabel : root.isOccupied ? occupiedLabel : label
+ color: BarConfig.workspaces.occupiedBg || root.isOccupied ? Appearance.colours.text : Appearance.colours.subtext0
+ horizontalAlignment: StyledText.AlignHCenter
+ verticalAlignment: StyledText.AlignVCenter
+
+ width: BarConfig.sizes.innerHeight
+ height: BarConfig.sizes.innerHeight
+ }
+
+ Grid {
+ flow: root.vertical ? GridLayout.TopToBottom : GridLayout.LeftToRight
+ rows: root.vertical ? -1 : 1
+ columns: root.vertical ? 1 : -1
+ spacing: Appearance.padding.small
+
+ anchors.left: vertical ? undefined : indicator.right
+ anchors.top: vertical ? indicator.bottom : undefined
+ anchors.verticalCenter: vertical ? undefined : indicator.verticalCenter
+ anchors.horizontalCenter: vertical ? indicator.horizontalCenter : undefined
+
+ add: Transition {
+ Anim {
+ properties: "scale"
+ from: 0
+ to: 1
+ duration: Appearance.anim.durations.small
+ }
+ }
+
+ Repeater {
+ model: ScriptModel {
+ values: Hyprland.clients.filter(c => c.workspace.id === root.ws)
+ }
+
+ MaterialIcon {
+ required property Hyprland.Client modelData
+
+ text: Icons.getAppCategoryIcon(modelData.wmClass, "terminal")
+ }
+ }
+ }
+
+ Behavior on Layout.preferredWidth {
+ Anim {}
+ }
- animate: true
- animateProp: "scale"
- text: (Hyprland.activeWorkspace?.id ?? 1) === ws ? activeLabel : label
- color: BarConfig.workspaces.occupiedBg || occupied[ws] ? Appearance.colours.text : Appearance.colours.subtext0
- horizontalAlignment: StyledText.AlignHCenter
+ Behavior on Layout.preferredHeight {
+ Anim {}
+ }
- Layout.minimumWidth: vertical ? -1 : BarConfig.sizes.innerHeight
- Layout.minimumHeight: vertical ? BarConfig.sizes.innerHeight : -1
+ component Anim: NumberAnimation {
+ duration: Appearance.anim.durations.normal
+ easing.type: Easing.BezierSpline
+ easing.bezierCurve: Appearance.anim.curves.standard
+ }
}
diff --git a/services/Hyprland.qml b/services/Hyprland.qml
index 336be73..f47c0cb 100644
--- a/services/Hyprland.qml
+++ b/services/Hyprland.qml
@@ -8,12 +8,13 @@ import QtQuick
Singleton {
id: root
- property list<Client> clients: []
+ readonly property list<Client> clients: []
readonly property var workspaces: Hyprland.workspaces
readonly property var monitors: Hyprland.monitors
property Client activeClient: null
readonly property HyprlandWorkspace activeWorkspace: focusedMonitor?.activeWorkspace ?? null
readonly property HyprlandMonitor focusedMonitor: Hyprland.monitors.values.find(m => m.lastIpcObject.focused) ?? null
+ readonly property int activeWsId: activeWorkspace?.id ?? 1
function reload() {
Hyprland.refreshWorkspaces();
@@ -43,9 +44,25 @@ Singleton {
stdout: SplitParser {
onRead: data => {
const clients = JSON.parse(data);
- root.clients = clients.map(c => clientComp.createObject(root, {
- lastIpcObject: c
- })).filter(c => c);
+ const rClients = root.clients;
+
+ const len = rClients.length;
+ for (let i = 0; i < len; i++) {
+ const client = rClients[i];
+ if (!clients.find(c => c.address === client.address))
+ rClients.splice(i, 1);
+ }
+
+ for (const client of clients) {
+ const match = rClients.find(c => c.address === client.address);
+ if (match) {
+ match.lastIpcObject = client;
+ } else {
+ rClients.push(clientComp.createObject(root, {
+ lastIpcObject: client
+ }));
+ }
+ }
}
}
}
@@ -78,6 +95,7 @@ Singleton {
property bool floating: lastIpcObject.floating
property bool fullscreen: lastIpcObject.fullscreen
property int pid: lastIpcObject.pid
+ property int focusHistoryId: lastIpcObject.focusHistoryID
}
Component {