bar/workspaces: refactor
This commit is contained in:
parent
2be46ff65a
commit
d8f7bac960
9 changed files with 98 additions and 111 deletions
|
|
@ -254,13 +254,12 @@ All configuration options are in `~/.config/caelestia/shell.json`.
|
||||||
},
|
},
|
||||||
"workspaces": {
|
"workspaces": {
|
||||||
"activeIndicator": true,
|
"activeIndicator": true,
|
||||||
"activeLabel": " ",
|
"activeLabel": "",
|
||||||
"activeTrail": false,
|
"activeTrail": false,
|
||||||
"label": " ",
|
"label": " ",
|
||||||
"occupiedBg": false,
|
"occupiedBg": false,
|
||||||
"occupiedLabel": " ",
|
"occupiedLabel": "",
|
||||||
"perMonitorWorkspaces": true,
|
"perMonitorWorkspaces": true,
|
||||||
"rounded": true,
|
|
||||||
"showWindows": true,
|
"showWindows": true,
|
||||||
"shown": 5
|
"shown": 5
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -50,15 +50,14 @@ JsonObject {
|
||||||
|
|
||||||
component Workspaces: JsonObject {
|
component Workspaces: JsonObject {
|
||||||
property int shown: 5
|
property int shown: 5
|
||||||
property bool rounded: true
|
|
||||||
property bool activeIndicator: true
|
property bool activeIndicator: true
|
||||||
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 bool perMonitorWorkspaces: true
|
||||||
property string label: " "
|
property string label: " "
|
||||||
property string occupiedLabel: " "
|
property string occupiedLabel: ""
|
||||||
property string activeLabel: " "
|
property string activeLabel: ""
|
||||||
}
|
}
|
||||||
|
|
||||||
component Tray: JsonObject {
|
component Tray: JsonObject {
|
||||||
|
|
|
||||||
|
|
@ -177,6 +177,5 @@ ColumnLayout {
|
||||||
|
|
||||||
visible: enabled
|
visible: enabled
|
||||||
active: enabled
|
active: enabled
|
||||||
asynchronous: true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,6 @@ Item {
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
|
|
||||||
active: root.shouldBeVisible || root.visible
|
active: root.shouldBeVisible || root.visible
|
||||||
asynchronous: true
|
|
||||||
|
|
||||||
sourceComponent: Bar {
|
sourceComponent: Bar {
|
||||||
width: root.contentWidth
|
width: root.contentWidth
|
||||||
|
|
|
||||||
|
|
@ -8,45 +8,38 @@ StyledRect {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
required property int activeWsId
|
required property int activeWsId
|
||||||
required property list<Workspace> workspaces
|
required property Repeater workspaces
|
||||||
required property Item mask
|
required property Item mask
|
||||||
required property real maskWidth
|
|
||||||
required property real maskHeight
|
|
||||||
required property int groupOffset
|
|
||||||
|
|
||||||
readonly property int currentWsIdx: activeWsId - 1 - groupOffset
|
readonly property int currentWsIdx: (activeWsId - 1) % Config.bar.workspaces.shown
|
||||||
property real leading: getWsY(currentWsIdx)
|
|
||||||
property real trailing: getWsY(currentWsIdx)
|
property real leading: workspaces.itemAt(currentWsIdx)?.y ?? 0
|
||||||
property real currentSize: workspaces[currentWsIdx]?.size ?? 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 offset: Math.min(leading, trailing)
|
||||||
property real size: {
|
property real size: {
|
||||||
const s = Math.abs(leading - trailing) + currentSize;
|
const s = Math.abs(leading - trailing) + currentSize;
|
||||||
if (Config.bar.workspaces.activeTrail && lastWs > currentWsIdx)
|
if (Config.bar.workspaces.activeTrail && lastWs > currentWsIdx) {
|
||||||
return Math.min(getWsY(lastWs) + (workspaces[lastWs]?.size ?? 0) - offset, s);
|
const ws = workspaces.itemAt(lastWs);
|
||||||
|
// console.log(ws, lastWs);
|
||||||
|
return ws ? Math.min(ws.y + ws.size - offset, s) : 0;
|
||||||
|
}
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
property int cWs
|
property int cWs
|
||||||
property int lastWs
|
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: {
|
onCurrentWsIdxChanged: {
|
||||||
lastWs = cWs;
|
lastWs = cWs;
|
||||||
cWs = currentWsIdx;
|
cWs = currentWsIdx;
|
||||||
}
|
}
|
||||||
|
|
||||||
clip: true
|
clip: true
|
||||||
x: 1
|
y: offset + mask.y
|
||||||
y: offset + 1
|
implicitWidth: Config.bar.sizes.innerWidth - Appearance.padding.small * 2
|
||||||
implicitWidth: Config.bar.sizes.innerHeight - 2
|
implicitHeight: size
|
||||||
implicitHeight: size - 2
|
radius: Appearance.rounding.full
|
||||||
radius: Config.bar.workspaces.rounded ? Appearance.rounding.full : 0
|
|
||||||
color: Colours.palette.m3primary
|
color: Colours.palette.m3primary
|
||||||
|
|
||||||
Colouriser {
|
Colouriser {
|
||||||
|
|
@ -56,8 +49,8 @@ StyledRect {
|
||||||
|
|
||||||
x: 0
|
x: 0
|
||||||
y: -parent.offset
|
y: -parent.offset
|
||||||
implicitWidth: root.maskWidth
|
implicitWidth: root.mask.implicitWidth
|
||||||
implicitHeight: root.maskHeight
|
implicitHeight: root.mask.implicitHeight
|
||||||
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ import QtQuick
|
||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
required property list<Workspace> workspaces
|
required property Repeater workspaces
|
||||||
required property var occupied
|
required property var occupied
|
||||||
required property int groupOffset
|
required property int groupOffset
|
||||||
|
|
||||||
|
|
@ -48,18 +48,17 @@ Item {
|
||||||
|
|
||||||
required property var modelData
|
required property var modelData
|
||||||
|
|
||||||
readonly property Workspace start: root.workspaces[modelData.start - 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[modelData.end - 1 - root.groupOffset] ?? null
|
readonly property Workspace end: root.workspaces.itemAt((modelData.end - 1) % Config.bar.workspaces.shown) ?? null
|
||||||
|
|
||||||
color: Colours.tPalette.m3surfaceContainerHigh
|
anchors.horizontalCenter: root.horizontalCenter
|
||||||
radius: Config.bar.workspaces.rounded ? Appearance.rounding.full : 0
|
|
||||||
|
|
||||||
x: start?.x ?? 0
|
y: (start?.y ?? 0) - 1
|
||||||
y: start?.y ?? 0
|
implicitWidth: Config.bar.sizes.innerWidth - Appearance.padding.small * 2 + 2
|
||||||
implicitWidth: Config.bar.sizes.innerHeight
|
implicitHeight: start && end ? end.y + end.size - start.y + 2 : 0
|
||||||
implicitHeight: end?.y + end?.height - start?.y
|
|
||||||
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
color: Colours.layer(Colours.palette.m3surfaceContainerHigh, 2)
|
||||||
|
radius: Appearance.rounding.full
|
||||||
|
|
||||||
scale: 0
|
scale: 0
|
||||||
Component.onCompleted: scale = 1
|
Component.onCompleted: scale = 1
|
||||||
|
|
@ -70,11 +69,11 @@ Item {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Behavior on x {
|
Behavior on y {
|
||||||
Anim {}
|
Anim {}
|
||||||
}
|
}
|
||||||
|
|
||||||
Behavior on y {
|
Behavior on implicitHeight {
|
||||||
Anim {}
|
Anim {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import Quickshell
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
|
|
||||||
Item {
|
ColumnLayout {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
required property int index
|
required property int index
|
||||||
|
|
@ -16,41 +16,44 @@ Item {
|
||||||
|
|
||||||
readonly property bool isWorkspace: true // Flag for finding workspace children
|
readonly property bool isWorkspace: true // Flag for finding workspace children
|
||||||
// Unanimated prop for others to use as reference
|
// 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 int ws: groupOffset + index + 1
|
||||||
readonly property bool isOccupied: occupied[ws] ?? false
|
readonly property bool isOccupied: occupied[ws] ?? false
|
||||||
readonly property bool hasWindows: isOccupied && Config.bar.workspaces.showWindows
|
readonly property bool hasWindows: isOccupied && Config.bar.workspaces.showWindows
|
||||||
|
|
||||||
Layout.preferredWidth: childrenRect.width
|
Layout.alignment: Qt.AlignHCenter
|
||||||
Layout.preferredHeight: size
|
Layout.preferredHeight: size
|
||||||
|
|
||||||
|
spacing: 0
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
id: indicator
|
id: indicator
|
||||||
|
|
||||||
readonly property string label: Config.bar.workspaces.label || root.ws
|
Layout.alignment: Qt.AlignHCenter | Qt.AlignTop
|
||||||
readonly property string occupiedLabel: Config.bar.workspaces.occupiedLabel || label
|
Layout.preferredHeight: Config.bar.sizes.innerWidth - Appearance.padding.small * 2
|
||||||
readonly property string activeLabel: Config.bar.workspaces.activeLabel || (root.isOccupied ? occupiedLabel : label)
|
|
||||||
|
|
||||||
animate: true
|
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)
|
color: Config.bar.workspaces.occupiedBg || root.isOccupied || root.activeWsId === root.ws ? Colours.palette.m3onSurface : Colours.layer(Colours.palette.m3outlineVariant, 2)
|
||||||
horizontalAlignment: StyledText.AlignHCenter
|
verticalAlignment: Qt.AlignVCenter
|
||||||
verticalAlignment: StyledText.AlignVCenter
|
|
||||||
|
|
||||||
width: Config.bar.sizes.innerHeight
|
|
||||||
height: Config.bar.sizes.innerHeight
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Loader {
|
Loader {
|
||||||
id: windows
|
id: windows
|
||||||
|
|
||||||
active: Config.bar.workspaces.showWindows
|
Layout.alignment: Qt.AlignHCenter
|
||||||
asynchronous: true
|
Layout.fillHeight: true
|
||||||
|
Layout.topMargin: -Config.bar.sizes.innerWidth / 10
|
||||||
|
|
||||||
anchors.horizontalCenter: indicator.horizontalCenter
|
visible: active
|
||||||
anchors.top: indicator.bottom
|
active: root.hasWindows
|
||||||
anchors.topMargin: -Config.bar.sizes.innerHeight / 10
|
asynchronous: true
|
||||||
|
|
||||||
sourceComponent: Column {
|
sourceComponent: Column {
|
||||||
spacing: 0
|
spacing: 0
|
||||||
|
|
@ -91,10 +94,6 @@ Item {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Behavior on Layout.preferredWidth {
|
|
||||||
Anim {}
|
|
||||||
}
|
|
||||||
|
|
||||||
Behavior on Layout.preferredHeight {
|
Behavior on Layout.preferredHeight {
|
||||||
Anim {}
|
Anim {}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,76 +13,61 @@ StyledRect {
|
||||||
required property ShellScreen screen
|
required property ShellScreen screen
|
||||||
|
|
||||||
readonly property int activeWsId: Config.bar.workspaces.perMonitorWorkspaces ? (Hyprland.monitorFor(screen).activeWorkspace?.id ?? 1) : Hyprland.activeWsId
|
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) => {
|
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((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
|
implicitHeight: layout.implicitHeight + Appearance.padding.small * 2
|
||||||
|
implicitWidth: Config.bar.sizes.innerWidth
|
||||||
|
|
||||||
color: Colours.tPalette.m3surfaceContainer
|
color: Colours.tPalette.m3surfaceContainer
|
||||||
radius: Appearance.rounding.full
|
radius: Appearance.rounding.full
|
||||||
|
|
||||||
Item {
|
Loader {
|
||||||
id: inner
|
active: Config.bar.workspaces.occupiedBg
|
||||||
|
asynchronous: true
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.margins: Appearance.padding.small
|
anchors.margins: Appearance.padding.small
|
||||||
|
|
||||||
ColumnLayout {
|
sourceComponent: OccupiedBg {
|
||||||
id: layout
|
workspaces: workspaces
|
||||||
|
occupied: root.occupied
|
||||||
spacing: 0
|
groupOffset: root.groupOffset
|
||||||
|
|
||||||
Repeater {
|
|
||||||
model: Config.bar.workspaces.shown
|
|
||||||
|
|
||||||
Workspace {
|
|
||||||
activeWsId: root.activeWsId
|
|
||||||
occupied: root.occupied
|
|
||||||
groupOffset: root.groupOffset
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Loader {
|
ColumnLayout {
|
||||||
active: Config.bar.workspaces.occupiedBg
|
id: layout
|
||||||
asynchronous: true
|
|
||||||
|
|
||||||
z: -1
|
anchors.centerIn: parent
|
||||||
anchors.fill: parent
|
spacing: Math.floor(Appearance.spacing.small / 2)
|
||||||
|
|
||||||
sourceComponent: OccupiedBg {
|
Repeater {
|
||||||
workspaces: root.workspaces
|
id: workspaces
|
||||||
|
|
||||||
|
model: Config.bar.workspaces.shown
|
||||||
|
|
||||||
|
Workspace {
|
||||||
|
activeWsId: root.activeWsId
|
||||||
occupied: root.occupied
|
occupied: root.occupied
|
||||||
groupOffset: root.groupOffset
|
groupOffset: root.groupOffset
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Loader {
|
Loader {
|
||||||
active: Config.bar.workspaces.activeIndicator
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
asynchronous: true
|
active: Config.bar.workspaces.activeIndicator
|
||||||
|
asynchronous: true
|
||||||
|
|
||||||
sourceComponent: ActiveIndicator {
|
sourceComponent: ActiveIndicator {
|
||||||
activeWsId: root.activeWsId
|
activeWsId: root.activeWsId
|
||||||
workspaces: root.workspaces
|
workspaces: workspaces
|
||||||
mask: layout
|
mask: layout
|
||||||
maskWidth: inner.width
|
|
||||||
maskHeight: inner.height
|
|
||||||
groupOffset: root.groupOffset
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: parent
|
|
||||||
|
|
||||||
onPressed: event => {
|
|
||||||
const ws = layout.childAt(event.x, event.y).index + root.groupOffset + 1;
|
|
||||||
if (Hyprland.activeWsId !== ws)
|
|
||||||
Hyprland.dispatch(`workspace ${ws}`);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -183,4 +183,19 @@ Singleton {
|
||||||
return "volume_down";
|
return "volume_down";
|
||||||
return "volume_mute";
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue