the perfect workspace indicator

This commit is contained in:
end-4
2025-04-10 17:03:57 +02:00
parent 5c88c6a5a6
commit ff93725b28
5 changed files with 223 additions and 1 deletions
+11
View File
@@ -9,6 +9,7 @@ Scope {
model: Quickshell.screens
PanelWindow {
id: barRoot
property var modelData
screen: modelData
@@ -24,8 +25,10 @@ Scope {
RowLayout {
anchors.centerIn: parent
implicitWidth: 500
spacing: 8 // TODO: Why is this halved when rendered??
RowLayout {
spacing: 4
Layout.fillWidth: true
Layout.fillHeight: true
}
@@ -33,15 +36,23 @@ Scope {
RowLayout {
Layout.fillWidth: true
Layout.fillHeight: true
spacing: 4
Workspaces {
bar: barRoot
}
}
RowLayout {
Layout.fillWidth: true
Layout.fillHeight: true
spacing: 4
ClockWidget {
Layout.alignment: Qt.AlignVCenter
}
UtilButtons {
Layout.alignment: Qt.AlignVCenter
}
@@ -0,0 +1,198 @@
import "../common"
import "../common/widgets"
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell
import Quickshell.Hyprland
import Quickshell.Io
Rectangle {
required property var bar
readonly property HyprlandMonitor monitor: Hyprland.monitorFor(bar.screen)
readonly property list<bool> workspaceOccupied: []
readonly property int workspaceGroup: Math.floor((monitor.activeWorkspace?.id - 1) / ConfigOptions.bar.workspacesShown)
property int widgetPadding: 4
property int workspaceButtonWidth: 26
property int activeWorkspaceMargin: 1
property double animatedActiveWorkspaceIndex: (monitor.activeWorkspace?.id - 1) % ConfigOptions.bar.workspacesShown
Behavior on animatedActiveWorkspaceIndex {
NumberAnimation {
duration: Appearance.animation.menuDecel.duration
easing.type: Appearance.animation.menuDecel.type
}
}
// Function to update workspaceOccupied
function updateWorkspaceOccupied() {
workspaceOccupied = Array.from({ length: ConfigOptions.bar.workspacesShown }, (_, i) => {
return Hyprland.workspaces.values.some(ws => ws.id === workspaceGroup * ConfigOptions.bar.workspacesShown + i + 1);
});
}
// Initialize workspaceOccupied when the component is created
Component.onCompleted: updateWorkspaceOccupied()
// Listen for changes in Hyprland.workspaces.values
Connections {
target: Hyprland.workspaces
function onValuesChanged() {
updateWorkspaceOccupied();
}
}
Layout.fillHeight: true
implicitWidth: rowLayout.implicitWidth + rowLayout.spacing * 2
implicitHeight: 40
color: "transparent"
// Background
Rectangle {
z: 0
anchors.centerIn: parent
implicitHeight: 32
implicitWidth: rowLayout.implicitWidth + widgetPadding * 2
radius: Appearance.rounding.small
color: Appearance.colors.colLayer1
}
// Scroll to switch workspaces
WheelHandler {
onWheel: (event) => {
if (event.angleDelta.y < 0)
Hyprland.dispatch(`workspace r+1`);
else if (event.angleDelta.y > 0)
Hyprland.dispatch(`workspace r-1`);
}
acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad
}
// Workspaces - background
RowLayout {
id: rowLayout
z: 1
spacing: 0
anchors.fill: parent
implicitHeight: 40
Repeater {
model: ConfigOptions.bar.workspacesShown
Rectangle {
z: 1
implicitWidth: workspaceButtonWidth
implicitHeight: workspaceButtonWidth
radius: Appearance.rounding.full
property var radiusLeft: workspaceOccupied[index-1] ? 0 : Appearance.rounding.full
property var radiusRight: workspaceOccupied[index+1] ? 0 : Appearance.rounding.full
topLeftRadius: radiusLeft
bottomLeftRadius: radiusLeft
topRightRadius: radiusRight
bottomRightRadius: radiusRight
color: Appearance.colors.colLayer2
opacity: workspaceOccupied[index] ? 1 : 0
// color: workspaceOccupied[index] ? Appearance.colors.colLayer2 : "transparent"
Behavior on opacity {
NumberAnimation {
duration: Appearance.animation.elementDecel.duration
easing.type: Appearance.animation.elementDecel.type
easing.bezierCurve: Appearance.animation.elementDecel.bezierCurve
}
}
Behavior on radiusLeft {
NumberAnimation {
duration: Appearance.animation.elementDecel.duration
easing.type: Appearance.animation.elementDecel.type
easing.bezierCurve: Appearance.animation.elementDecel.bezierCurve
}
}
Behavior on radiusRight {
NumberAnimation {
duration: Appearance.animation.elementDecel.duration
easing.type: Appearance.animation.elementDecel.type
easing.bezierCurve: Appearance.animation.elementDecel.bezierCurve
}
}
}
}
}
// Active workspace
Rectangle {
z: 2
implicitWidth: workspaceButtonWidth - activeWorkspaceMargin * 2
implicitHeight: workspaceButtonWidth - activeWorkspaceMargin * 2
radius: Appearance.rounding.full
color: Appearance.m3colors.m3primary
anchors.verticalCenter: parent.verticalCenter
x: animatedActiveWorkspaceIndex * workspaceButtonWidth + activeWorkspaceMargin
}
// Workspaces - numbers
RowLayout {
id: rowLayoutNumbers
z: 3
spacing: 0
anchors.fill: parent
implicitHeight: 40
Repeater {
model: ConfigOptions.bar.workspacesShown
Button {
id: button
Layout.fillHeight: true
topInset: 7
bottomInset: 7
onPressed: Hyprland.dispath(`workspace ${index+1}`)
width: workspaceButtonWidth
contentItem: StyledText {
z: 3
property int workspaceValue: workspaceGroup * ConfigOptions.bar.workspacesShown + index + 1
anchors.fill: parent
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
font.pointSize: Appearance.font.pointSize.small
text: `${workspaceValue}`
elide: Text.ElideRight
color: (monitor.activeWorkspace?.id == workspaceValue) ? Appearance.m3colors.m3onPrimary : (workspaceOccupied[index] ? Appearance.colors.colOnLayer1 : Appearance.colors.colOnLayer1Inactive)
Behavior on color {
ColorAnimation {
duration: Appearance.animation.elementDecel.duration
easing.type: Appearance.animation.elementDecel.type
easing.bezierCurve: Appearance.animation.elementDecel.bezierCurve
}
}
}
background: Rectangle {
color: "transparent" // Transparent background
implicitWidth: workspaceButtonWidth
implicitHeight: workspaceButtonWidth
}
}
}
}
}
@@ -145,6 +145,10 @@ Singleton {
property int type: Easing.BezierSpline
property list<real> bezierCurve: [0, 0.55, 0.45, 1]
}
property QtObject menuDecel: QtObject {
property int duration: 250
property int type: Easing.OutCubic
}
}
}
@@ -0,0 +1,10 @@
import QtQuick
import Quickshell
pragma Singleton
Singleton {
property QtObject bar: QtObject {
property int workspacesShown: 10
}
}
@@ -4,7 +4,6 @@ import QtQuick.Controls
import QtQuick.Layouts
import Quickshell
import Quickshell.Io
import Quickshell.Wayland
Button {
id: button