workspace rework

This commit is contained in:
Zacharias-Brohn
2026-03-02 13:38:58 +01:00
parent cda00f91a3
commit 9040713231
3 changed files with 221 additions and 84 deletions
+24
View File
@@ -0,0 +1,24 @@
import QtQuick
QtObject {
id: root
property real idx1: index
property int idx1Duration: 100
property real idx2: index
property int idx2Duration: 300
required property int index
Behavior on idx1 {
NumberAnimation {
duration: root.idx1Duration
easing.type: Easing.OutSine
}
}
Behavior on idx2 {
NumberAnimation {
duration: root.idx2Duration
easing.type: Easing.OutSine
}
}
}
+128
View File
@@ -0,0 +1,128 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Effects
import Quickshell
import Quickshell.Hyprland
import qs.Config
import qs.Components
Item {
id: itemRoot
required property PanelWindow bar
anchors.bottom: parent.bottom
anchors.top: parent.top
implicitWidth: workspacesRow.implicitWidth + 10
Behavior on implicitWidth {
NumberAnimation {
duration: MaterialEasing.expressiveEffectsTime
easing.bezierCurve: MaterialEasing.expressiveEffects
}
}
Rectangle {
id: root
property HyprlandMonitor monitor: Hyprland.monitorFor(itemRoot.bar?.screen)
function shouldShow(monitor) {
Hyprland.refreshWorkspaces();
Hyprland.refreshMonitors();
if (monitor === root.monitor) {
return true;
} else {
return false;
}
}
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
color: DynamicColors.tPalette.m3surfaceContainer
implicitHeight: 22
radius: height / 2
Behavior on color {
CAnim {
}
}
RowLayout {
id: workspacesRow
anchors.left: parent.left
anchors.leftMargin: 6
anchors.verticalCenter: parent.verticalCenter
spacing: 8
Repeater {
model: Hyprland.workspaces
RowLayout {
id: workspaceIndicator
required property var modelData
visible: root.shouldShow(workspaceIndicator.modelData.monitor)
CustomText {
color: workspaceIndicator.modelData.id === Hyprland.focusedWorkspace.id ? DynamicColors.palette.m3primary : DynamicColors.palette.m3onSurfaceVariant
font.pointSize: 12
text: workspaceIndicator.modelData.name
visible: true
}
Rectangle {
border.color: workspaceIndicator.modelData.id === Hyprland.focusedWorkspace.id ? DynamicColors.palette.m3primary : DynamicColors.palette.m3onSurfaceVariant
border.width: 1
color: "transparent"
implicitHeight: 14
implicitWidth: 14
opacity: 1.0
radius: height / 2
scale: 1.0
Behavior on border.color {
ColorAnimation {
duration: 150
easing.type: Easing.InOutQuad
}
}
NumberAnimation on opacity {
duration: 200
from: 0.0
to: 1.0
}
NumberAnimation on scale {
duration: 300
easing.type: Easing.OutBack
from: 0.0
to: 1.0
}
CustomRect {
anchors.centerIn: parent
color: workspaceIndicator.modelData.id === Hyprland.focusedWorkspace.id ? DynamicColors.palette.m3primary : "transparent"
implicitHeight: 8
implicitWidth: 8
radius: implicitHeight / 2
}
MouseArea {
anchors.fill: parent
onClicked: {
workspaceIndicator.modelData.activate();
}
}
}
}
}
}
}
}
+75 -90
View File
@@ -2,124 +2,109 @@ pragma ComponentBehavior: Bound
import QtQuick import QtQuick
import QtQuick.Controls import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Effects
import Quickshell import Quickshell
import Quickshell.Hyprland import Quickshell.Hyprland
import qs.Config import qs.Config
import qs.Components import qs.Components
Item { Item {
id: itemRoot id: root
property real activeWorkspaceMargin: Math.ceil(Appearance.padding.small / 2)
required property PanelWindow bar required property PanelWindow bar
readonly property int effectiveActiveWorkspaceId: monitor?.activeWorkspace?.id ?? 1
readonly property HyprlandMonitor monitor: Hyprland.monitorFor(root.bar.screen)
property int workspaceButtonWidth: rect.implicitHeight - root.activeWorkspaceMargin * 2
property int workspaceIndexInGroup: (effectiveActiveWorkspaceId - 1) % root.workspacesShown
readonly property list<var> workspaces: Hyprland.workspaces.values.filter(w => w.monitor === root.monitor)
readonly property int workspacesShown: workspaces.length
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.top: parent.top anchors.top: parent.top
implicitWidth: workspacesRow.implicitWidth + 10 implicitWidth: (root.workspaceButtonWidth * root.workspacesShown) + root.activeWorkspaceMargin * 2
Behavior on implicitWidth { Behavior on implicitWidth {
NumberAnimation { Anim {
duration: MaterialEasing.expressiveEffectsTime
easing.bezierCurve: MaterialEasing.expressiveEffects
} }
} }
Rectangle { CustomRect {
id: root id: rect
property HyprlandMonitor monitor: Hyprland.monitorFor(itemRoot.bar?.screen)
function shouldShow(monitor) {
Hyprland.refreshWorkspaces();
Hyprland.refreshMonitors();
if (monitor === root.monitor) {
return true;
} else {
return false;
}
}
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
color: DynamicColors.tPalette.m3surfaceContainer color: DynamicColors.tPalette.m3surfaceContainer
implicitHeight: 22 implicitHeight: root.parent.height - ((Appearance.padding.small - 1) * 2)
radius: height / 2 radius: height / 2
Behavior on color {
CAnim {
}
}
RowLayout {
id: workspacesRow
anchors.left: parent.left
anchors.leftMargin: 6
anchors.verticalCenter: parent.verticalCenter
spacing: 8
Repeater {
model: Hyprland.workspaces
RowLayout {
id: workspaceIndicator
required property var modelData
visible: root.shouldShow(workspaceIndicator.modelData.monitor)
CustomText {
color: workspaceIndicator.modelData.id === Hyprland.focusedWorkspace.id ? DynamicColors.palette.m3primary : DynamicColors.palette.m3onSurfaceVariant
font.pointSize: 12
text: workspaceIndicator.modelData.name
visible: true
}
Rectangle {
border.color: workspaceIndicator.modelData.id === Hyprland.focusedWorkspace.id ? DynamicColors.palette.m3primary : DynamicColors.palette.m3onSurfaceVariant
border.width: 1
color: "transparent"
implicitHeight: 14
implicitWidth: 14
opacity: 1.0
radius: height / 2
scale: 1.0
Behavior on border.color {
ColorAnimation {
duration: 150
easing.type: Easing.InOutQuad
}
}
NumberAnimation on opacity {
duration: 200
from: 0.0
to: 1.0
}
NumberAnimation on scale {
duration: 300
easing.type: Easing.OutBack
from: 0.0
to: 1.0
}
CustomRect { CustomRect {
anchors.centerIn: parent id: indicator
color: workspaceIndicator.modelData.id === Hyprland.focusedWorkspace.id ? DynamicColors.palette.m3primary : "transparent"
implicitHeight: 8 property real indicatorLength: (Math.abs(idxPair.idx1 - idxPair.idx2) + 1) * root.workspaceButtonWidth
implicitWidth: 8 property real indicatorPosition: Math.min(idxPair.idx1, idxPair.idx2) * root.workspaceButtonWidth + root.activeWorkspaceMargin
radius: implicitHeight / 2 property real indicatorThickness: root.workspaceButtonWidth
anchors.verticalCenter: parent.verticalCenter
color: DynamicColors.palette.m3primary
implicitHeight: indicatorThickness
implicitWidth: indicatorLength
radius: Appearance.rounding.full
x: indicatorPosition
z: 2
AnimatedTabIndexPair {
id: idxPair
index: root.workspaces.findIndex(w => w.active)
onIndexChanged: {
console.log(indicator.indicatorPosition);
}
}
} }
MouseArea { Grid {
anchors.fill: parent anchors.fill: parent
anchors.margins: root.activeWorkspaceMargin
columnSpacing: 0
columns: root.workspacesShown
rowSpacing: 0
rows: 1
z: 3
onClicked: { Repeater {
workspaceIndicator.modelData.activate(); model: root.workspaces
}
} Button {
id: button
required property int index
required property HyprlandWorkspace modelData
implicitHeight: indicator.indicatorThickness
implicitWidth: indicator.indicatorThickness
width: workspaceButtonWidth
background: Item {
id: workspaceButtonBackground
implicitHeight: workspaceButtonWidth
implicitWidth: workspaceButtonWidth
CustomText {
anchors.centerIn: parent
color: (root.effectiveActiveWorkspaceId === button.modelData.id) ? DynamicColors.palette.m3onPrimary : DynamicColors.palette.m3onSecondaryContainer
elide: Text.ElideRight
horizontalAlignment: Text.AlignHCenter
text: button.modelData.name
verticalAlignment: Text.AlignVCenter
z: 3
}
}
onPressed: {
Hyprland.dispatch(`workspace ${button.modelData.name}`);
} }
} }
} }