diff --git a/.config/quickshell/ii/modules/bar/Workspaces.qml b/.config/quickshell/ii/modules/bar/Workspaces.qml index a426ce71b..775df18d7 100644 --- a/.config/quickshell/ii/modules/bar/Workspaces.qml +++ b/.config/quickshell/ii/modules/bar/Workspaces.qml @@ -14,6 +14,7 @@ import Qt5Compat.GraphicalEffects Item { id: root + property bool vertical: false property bool borderless: Config.options.bar.borderless readonly property HyprlandMonitor monitor: Hyprland.monitorFor(root.QsWindow.window?.screen) readonly property Toplevel activeWindow: ToplevelManager.activeToplevel @@ -22,6 +23,7 @@ Item { property list workspaceOccupied: [] property int widgetPadding: 4 property int workspaceButtonWidth: 26 + property real activeWorkspaceMargin: 2 property real workspaceIconSize: workspaceButtonWidth * 0.69 property real workspaceIconSizeShrinked: workspaceButtonWidth * 0.55 property real workspaceIconOpacityShrinked: 1 @@ -77,8 +79,8 @@ Item { updateWorkspaceOccupied(); } - implicitWidth: rowLayout.implicitWidth + rowLayout.spacing * 2 - implicitHeight: Appearance.sizes.barHeight + implicitWidth: root.vertical ? Appearance.sizes.verticalBarWidth : backgroundLayout.implicitWidth + implicitHeight: root.vertical ? backgroundLayout.implicitHeight : Appearance.sizes.barHeight // Scroll to switch workspaces WheelHandler { @@ -102,31 +104,36 @@ Item { } // Workspaces - background - RowLayout { - id: rowLayout + GridLayout { + id: backgroundLayout z: 1 - - spacing: 0 anchors.fill: parent - implicitHeight: Appearance.sizes.barHeight + implicitHeight: root.vertical ? root.workspaceButtonWidth : Appearance.sizes.barHeight + implicitWidth: root.vertical ? Appearance.sizes.verticalBarWidth : root.workspaceButtonWidth + + rowSpacing: 0 + columnSpacing: 0 + columns: root.vertical ? 1 : -1 Repeater { model: Config.options.bar.workspaces.shown Rectangle { z: 1 + Layout.alignment: root.vertical ? Qt.AlignHCenter : Qt.AlignVCenter + implicitWidth: workspaceButtonWidth implicitHeight: workspaceButtonWidth radius: (width / 2) property var previousOccupied: (workspaceOccupied[index-1] && !(!activeWindow?.activated && monitor?.activeWorkspace?.id === index)) property var rightOccupied: (workspaceOccupied[index+1] && !(!activeWindow?.activated && monitor?.activeWorkspace?.id === index+2)) - property var radiusLeft: previousOccupied ? 0 : (width / 2) - property var radiusRight: rightOccupied ? 0 : (width / 2) + property var radiusPrev: previousOccupied ? 0 : (width / 2) + property var radiusNext: rightOccupied ? 0 : (width / 2) - topLeftRadius: radiusLeft - bottomLeftRadius: radiusLeft - topRightRadius: radiusRight - bottomRightRadius: radiusRight + topLeftRadius: radiusPrev + bottomLeftRadius: root.vertical ? radiusNext : radiusPrev + topRightRadius: root.vertical ? radiusPrev : radiusNext + bottomRightRadius: radiusNext color: ColorUtils.transparentize(Appearance.m3colors.m3secondaryContainer, 0.4) opacity: (workspaceOccupied[index] && !(!activeWindow?.activated && monitor?.activeWorkspace?.id === index+1)) ? 1 : 0 @@ -134,11 +141,11 @@ Item { Behavior on opacity { animation: Appearance.animation.elementMove.numberAnimation.createObject(this) } - Behavior on radiusLeft { + Behavior on radiusPrev { animation: Appearance.animation.elementMove.numberAnimation.createObject(this) } - Behavior on radiusRight { + Behavior on radiusNext { animation: Appearance.animation.elementMove.numberAnimation.createObject(this) } @@ -152,27 +159,34 @@ Item { Rectangle { z: 2 // Make active ws indicator, which has a brighter color, smaller to look like it is of the same size as ws occupied highlight - property real activeWorkspaceMargin: 2 - implicitHeight: workspaceButtonWidth - activeWorkspaceMargin * 2 radius: Appearance.rounding.full color: Appearance.colors.colPrimary - anchors.verticalCenter: parent.verticalCenter + anchors { + verticalCenter: vertical ? undefined : parent.verticalCenter + horizontalCenter: vertical ? parent.horizontalCenter : undefined + } + + // idx1 is the "leading" indicator position, idx2 is the "following" one + // The former animates faster than the latter, see the NumberAnimations below property real idx1: workspaceIndexInGroup property real idx2: workspaceIndexInGroup - x: Math.min(idx1, idx2) * workspaceButtonWidth + activeWorkspaceMargin - implicitWidth: Math.abs(idx1 - idx2) * workspaceButtonWidth + workspaceButtonWidth - activeWorkspaceMargin * 2 + property real indicatorPosition: Math.min(idx1, idx2) * workspaceButtonWidth + root.activeWorkspaceMargin + property real indicatorLength: Math.abs(idx1 - idx2) * workspaceButtonWidth + workspaceButtonWidth - root.activeWorkspaceMargin * 2 + property real indicatorThickness: workspaceButtonWidth - root.activeWorkspaceMargin * 2 - Behavior on activeWorkspaceMargin { - animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this) - } - Behavior on idx1 { // Leading anim + x: root.vertical ? null : indicatorPosition + implicitWidth: root.vertical ? indicatorThickness : indicatorLength + y: root.vertical ? indicatorPosition : null + implicitHeight: root.vertical ? indicatorLength : indicatorThickness + + Behavior on idx1 { NumberAnimation { duration: 100 easing.type: Easing.OutSine } } - Behavior on idx2 { // Following anim + Behavior on idx2 { NumberAnimation { duration: 300 easing.type: Easing.OutSine @@ -181,13 +195,17 @@ Item { } // Workspaces - numbers - RowLayout { + GridLayout { id: rowLayoutNumbers z: 3 - spacing: 0 + columns: vertical ? 1 : -1 + columnSpacing: 0 + rowSpacing: 0 + anchors.fill: parent - implicitHeight: Appearance.sizes.barHeight + implicitHeight: vertical ? Appearance.sizes.barWidth : Appearance.sizes.barHeight + implicitWidth: vertical ? Appearance.sizes.verticalBarWidth : Appearance.sizes.verticalBarWidth Repeater { model: Config.options.bar.workspaces.shown @@ -195,10 +213,12 @@ Item { Button { id: button property int workspaceValue: workspaceGroup * Config.options.bar.workspaces.shown + index + 1 - Layout.fillHeight: true + Layout.fillHeight: !root.vertical + Layout.fillWidth: root.vertical onPressed: Hyprland.dispatch(`workspace ${workspaceValue}`) - width: workspaceButtonWidth - + width: vertical ? undefined : workspaceButtonWidth + height: vertical ? workspaceButtonWidth : undefined + background: Item { id: workspaceButtonBackground implicitWidth: workspaceButtonWidth diff --git a/.config/quickshell/ii/modules/verticalBar/VerticalBarContent.qml b/.config/quickshell/ii/modules/verticalBar/VerticalBarContent.qml index 170fe1f43..bfcd0c6fb 100644 --- a/.config/quickshell/ii/modules/verticalBar/VerticalBarContent.qml +++ b/.config/quickshell/ii/modules/verticalBar/VerticalBarContent.qml @@ -110,8 +110,9 @@ Item { // Bar content region vertical: true padding: 6 - Workspaces { + Bar.Workspaces { id: workspacesWidget + vertical: true MouseArea { // Right-click to toggle overview anchors.fill: parent diff --git a/.config/quickshell/ii/modules/verticalBar/Workspaces.qml b/.config/quickshell/ii/modules/verticalBar/Workspaces.qml deleted file mode 100644 index 1c1f64661..000000000 --- a/.config/quickshell/ii/modules/verticalBar/Workspaces.qml +++ /dev/null @@ -1,308 +0,0 @@ -import qs -import qs.services -import qs.modules.common -import qs.modules.common.widgets -import qs.modules.common.functions -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import Quickshell -import Quickshell.Wayland -import Quickshell.Hyprland -import Quickshell.Widgets -import Qt5Compat.GraphicalEffects - -Item { - id: root - property bool borderless: Config.options.bar.borderless - readonly property HyprlandMonitor monitor: Hyprland.monitorFor(root.QsWindow.window?.screen) - readonly property Toplevel activeWindow: ToplevelManager.activeToplevel - - readonly property int workspaceGroup: Math.floor((monitor?.activeWorkspace?.id - 1) / Config.options.bar.workspaces.shown) - property list workspaceOccupied: [] - property real workspaceButtonWidth: 26 - property real activeWorkspaceMargin: 2 - property real workspaceIconSize: workspaceButtonWidth * 0.69 - property real workspaceIconSizeShrinked: workspaceButtonWidth * 0.55 - property real workspaceIconOpacityShrinked: 1 - property real workspaceIconMarginShrinked: -4 - property int workspaceIndexInGroup: (monitor?.activeWorkspace?.id - 1) % Config.options.bar.workspaces.shown - - implicitHeight: columnLayout.implicitHeight + columnLayout.spacing * 2 - implicitWidth: Appearance.sizes.verticalBarWidth - - property bool showNumbers: false - Timer { - id: showNumbersTimer - interval: (Config?.options.bar.autoHide.showWhenPressingSuper.delay ?? 100) - repeat: false - onTriggered: { - root.showNumbers = true - } - } - Connections { - target: GlobalStates - function onSuperDownChanged() { - if (!Config?.options.bar.autoHide.showWhenPressingSuper.enable) return; - if (GlobalStates.superDown) showNumbersTimer.restart(); - else { - showNumbersTimer.stop(); - root.showNumbers = false; - } - } - function onSuperReleaseMightTriggerChanged() { - showNumbersTimer.stop() - } - } - - // Function to update workspaceOccupied - function updateWorkspaceOccupied() { - workspaceOccupied = Array.from({ length: Config.options.bar.workspaces.shown }, (_, i) => { - return Hyprland.workspaces.values.some(ws => ws.id === workspaceGroup * Config.options.bar.workspaces.shown + i + 1); - }) - } - - // Occupied workspace updates - Component.onCompleted: updateWorkspaceOccupied() - Connections { - target: Hyprland.workspaces - function onValuesChanged() { - updateWorkspaceOccupied(); - } - } - Connections { - target: Hyprland - function onFocusedWorkspaceChanged() { - updateWorkspaceOccupied(); - } - } - onWorkspaceGroupChanged: { - updateWorkspaceOccupied(); - } - - // 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 - } - - MouseArea { - anchors.fill: parent - acceptedButtons: Qt.BackButton - onPressed: (event) => { - if (event.button === Qt.BackButton) { - Hyprland.dispatch(`togglespecialworkspace`); - } - } - } - - // Workspaces - background - ColumnLayout { - id: columnLayout - z: 1 - - spacing: 0 - anchors.fill: parent - implicitWidth: Appearance.sizes.verticalBarWidth - - Repeater { - model: Config.options.bar.workspaces.shown - - Rectangle { - z: 1 - implicitWidth: workspaceButtonWidth - implicitHeight: workspaceButtonWidth - radius: (width / 2) - property var previousOccupied: (workspaceOccupied[index-1] && !(!activeWindow?.activated && monitor?.activeWorkspace?.id === index)) - property var nextOccupied: (workspaceOccupied[index+1] && !(!activeWindow?.activated && monitor?.activeWorkspace?.id === index+2)) - property var radiusTop: previousOccupied ? 0 : (width / 2) - property var radiusBottom: nextOccupied ? 0 : (width / 2) - - Layout.alignment: Qt.AlignHCenter - - topLeftRadius: radiusTop - topRightRadius: radiusTop - bottomLeftRadius: radiusBottom - bottomRightRadius: radiusBottom - - color: ColorUtils.transparentize(Appearance.m3colors.m3secondaryContainer, 0.4) - opacity: (workspaceOccupied[index] && !(!activeWindow?.activated && monitor?.activeWorkspace?.id === index+1)) ? 1 : 0 - - Behavior on opacity { - animation: Appearance.animation.elementMove.numberAnimation.createObject(this) - } - Behavior on radiusTop { - animation: Appearance.animation.elementMove.numberAnimation.createObject(this) - } - Behavior on radiusBottom { - animation: Appearance.animation.elementMove.numberAnimation.createObject(this) - } - - } - } - } - - // Active workspace - Rectangle { - z: 2 - // Make active ws indicator, which has a brighter color, smaller to look like it is of the same size as ws occupied highlight - implicitWidth: workspaceButtonWidth - root.activeWorkspaceMargin * 2 - radius: Appearance.rounding.full - color: Appearance.colors.colPrimary - anchors.horizontalCenter: parent.horizontalCenter - - property real idx1: workspaceIndexInGroup - property real idx2: workspaceIndexInGroup - y: Math.min(idx1, idx2) * workspaceButtonWidth + root.activeWorkspaceMargin - implicitHeight: Math.abs(idx1 - idx2) * workspaceButtonWidth + workspaceButtonWidth - root.activeWorkspaceMargin * 2 - - Behavior on idx1 { // Leading anim - NumberAnimation { - duration: 100 - easing.type: Easing.OutSine - } - } - Behavior on idx2 { // Following anim - NumberAnimation { - duration: 300 - easing.type: Easing.OutSine - } - } - } - - // Workspaces - numbers - ColumnLayout { - id: columnLayoutNumbers - z: 3 - - spacing: 0 - anchors.fill: parent - implicitWidth: Appearance.sizes.verticalBarWidth - - Repeater { - model: Config.options.bar.workspaces.shown - - Button { - id: button - property int workspaceValue: workspaceGroup * Config.options.bar.workspaces.shown + index + 1 - Layout.fillWidth: true - onPressed: Hyprland.dispatch(`workspace ${workspaceValue}`) - height: workspaceButtonWidth - - background: Item { - id: workspaceButtonBackground - implicitWidth: workspaceButtonWidth - implicitHeight: workspaceButtonWidth - property var biggestWindow: HyprlandData.biggestWindowForWorkspace(button.workspaceValue) - property var mainAppIconSource: Quickshell.iconPath(AppSearch.guessIcon(biggestWindow?.class), "image-missing") - - StyledText { // Workspace number text - opacity: root.showNumbers - || ((Config.options?.bar.workspaces.alwaysShowNumbers && (!Config.options?.bar.workspaces.showAppIcons || !workspaceButtonBackground.biggestWindow || root.showNumbers)) - || (root.showNumbers && !Config.options?.bar.workspaces.showAppIcons) - ) ? 1 : 0 - z: 3 - - anchors.centerIn: parent - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - font.pixelSize: Appearance.font.pixelSize.small - ((text.length - 1) * (text !== "10") * 2) - text: `${button.workspaceValue}` - elide: Text.ElideRight - color: (monitor?.activeWorkspace?.id == button.workspaceValue) ? - Appearance.m3colors.m3onPrimary : - (workspaceOccupied[index] ? Appearance.m3colors.m3onSecondaryContainer : - Appearance.colors.colOnLayer1Inactive) - - Behavior on opacity { - animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this) - } - } - Rectangle { // Dot instead of ws number - id: wsDot - opacity: (Config.options?.bar.workspaces.alwaysShowNumbers - || root.showNumbers - || (Config.options?.bar.workspaces.showAppIcons && workspaceButtonBackground.biggestWindow) - ) ? 0 : 1 - visible: opacity > 0 - anchors.centerIn: parent - width: workspaceButtonWidth * 0.18 - height: width - radius: width / 2 - color: (monitor?.activeWorkspace?.id == button.workspaceValue) ? - Appearance.m3colors.m3onPrimary : - (workspaceOccupied[index] ? Appearance.m3colors.m3onSecondaryContainer : - Appearance.colors.colOnLayer1Inactive) - - Behavior on opacity { - animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this) - } - } - Item { // Main app icon - anchors.centerIn: parent - width: workspaceButtonWidth - height: workspaceButtonWidth - opacity: !Config.options?.bar.workspaces.showAppIcons ? 0 : - (workspaceButtonBackground.biggestWindow && !root.showNumbers && Config.options?.bar.workspaces.showAppIcons) ? - 1 : workspaceButtonBackground.biggestWindow ? workspaceIconOpacityShrinked : 0 - visible: opacity > 0 - IconImage { - id: mainAppIcon - anchors.bottom: parent.bottom - anchors.right: parent.right - anchors.bottomMargin: (!root.showNumbers && Config.options?.bar.workspaces.showAppIcons) ? - (workspaceButtonWidth - workspaceIconSize) / 2 : workspaceIconMarginShrinked - anchors.rightMargin: (!root.showNumbers && Config.options?.bar.workspaces.showAppIcons) ? - (workspaceButtonWidth - workspaceIconSize) / 2 : workspaceIconMarginShrinked - - source: workspaceButtonBackground.mainAppIconSource - implicitSize: (!root.showNumbers && Config.options?.bar.workspaces.showAppIcons) ? workspaceIconSize : workspaceIconSizeShrinked - - Behavior on opacity { - animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this) - } - Behavior on anchors.bottomMargin { - animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this) - } - Behavior on anchors.rightMargin { - animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this) - } - Behavior on implicitSize { - animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this) - } - } - - Loader { - active: Config.options.bar.workspaces.monochromeIcons - anchors.fill: mainAppIcon - sourceComponent: Item { - Desaturate { - id: desaturatedIcon - visible: false // There's already color overlay - anchors.fill: parent - source: mainAppIcon - desaturation: 0.8 - } - ColorOverlay { - anchors.fill: desaturatedIcon - source: desaturatedIcon - color: ColorUtils.transparentize(wsDot.color, 0.9) - } - } - } - } - } - - - } - - } - - } - -}