mirror of
https://github.com/end-4/dots-hyprland.git
synced 2026-06-05 23:09:26 -05:00
the perfect workspace indicator
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user