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 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 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 onPressed: Hyprland.dispatch(`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 } } } } }