From 2b492113153c512a3c7a30889975a7285605a9d7 Mon Sep 17 00:00:00 2001 From: voidarc Date: Tue, 23 Jun 2026 15:33:25 +0100 Subject: [PATCH] finished workspaces --- Bar/Left.qml | 47 +++++++++++++++++++- Bar/Left/WorkspaceContainer.qml | 61 +++++++++++++++++++++++++- Bar/Left/WorkspaceSelector.qml | 77 ++++++++++++++++++++++++++++++++- Services/WorkspaceManager.qml | 43 +++++++++++++++++- 4 files changed, 222 insertions(+), 6 deletions(-) diff --git a/Bar/Left.qml b/Bar/Left.qml index 8fa7d0d..99ff888 100644 --- a/Bar/Left.qml +++ b/Bar/Left.qml @@ -13,13 +13,58 @@ import "./Left/" Container { id: root + property double extraHoveredWidth: 0 required property HyprlandMonitor monitor + property double rowLeftMargin: 4 + property double rowSpacing: 3 + property double rowYmargin: 3 + property double selectorFocusedExtra: 15 + property double selectorHeight: 20 + property double selectorWidth: 20 + property double spacing: 3 + property double workspaceNumber: WorkspaceManager.getNumberOfWorkspaces(monitor) boxHeight: 25 - boxWidth: 200 + boxWidth: (selectorWidth * workspaceNumber) + ((2 * rowLeftMargin) + (rowSpacing * ( + workspaceNumber - 1))) + extraHoveredWidth + (hoverHandler.hovered == true + ? selectorFocusedExtra : 0) exclusiveMonitor: monitor defaultItem: WorkspaceContainer { + extraHoveredWidth: root.extraHoveredWidth monitor: root.monitor + rowLeftMargin: root.rowLeftMargin + rowSpacing: root.rowSpacing + rowYmargin: root.rowYmargin + selectorFocusedExtra: root.selectorFocusedExtra + selectorHeight: root.selectorHeight + selectorWidth: root.selectorWidth + } + Behavior on rowYmargin { + SpringAnimation { + damping: 0.3 + spring: 4 + } + } + states: [ + State { + name: "" + when: !hoverHandler.hovered + }, + State { + name: "hovered" + when: hoverHandler.hovered + + PropertyChanges { + root.boxHeight: 40 + root.extraHoveredWidth: 25 + root.rowYmargin: 5 + root.selectorWidth: 40 + } + } + ] + + HoverHandler { + id: hoverHandler } } diff --git a/Bar/Left/WorkspaceContainer.qml b/Bar/Left/WorkspaceContainer.qml index 6f46877..5f5f0ef 100644 --- a/Bar/Left/WorkspaceContainer.qml +++ b/Bar/Left/WorkspaceContainer.qml @@ -2,17 +2,70 @@ import QtQuick import QtQuick.Layouts import Quickshell import Quickshell.Hyprland +import "../../Color.js" as Colors import "../../Components/" import "../../Services/" Item { id: root + required property double extraHoveredWidth required property HyprlandMonitor monitor + required property double rowLeftMargin + required property double rowSpacing + required property double rowYmargin + required property double selectorFocusedExtra + required property double selectorHeight + required property double selectorWidth - RowLayout { - anchors.fill: parent + Item { + implicitWidth: 20 + opacity: root.extraHoveredWidth > 0 ? 1 : 0 + Behavior on opacity { + NumberAnimation { + duration: 100 + } + } + + TapHandler { + id: tapHandler + + onTapped: WorkspaceManager.activateNextFreeWorkspace() + } + + anchors { + bottom: parent.bottom + bottomMargin: 5 + root.rowYmargin + right: parent.right + rightMargin: 4 + top: parent.top + topMargin: 5 + root.rowYmargin + } + + Rectangle { + anchors.fill: parent + color: Colors.red + radius: 4 + + StyledText { + anchors.centerIn: parent + text: "+" + } + } + } + + Row { + spacing: root.rowSpacing + + anchors { + bottom: parent.bottom + bottomMargin: root.rowYmargin + left: parent.left + leftMargin: root.rowLeftMargin + top: parent.top + topMargin: root.rowYmargin + } Repeater { model: WorkspaceManager.getWorkspacesForMonitor(root.monitor) @@ -20,6 +73,10 @@ Item { WorkspaceSelector { required property HyprlandWorkspace modelData + extraHoveredWidth: root.extraHoveredWidth + selectorFocusedExtra: root.selectorFocusedExtra + selectorHeight: root.selectorHeight + selectorWidth: root.selectorWidth workspace: modelData } } diff --git a/Bar/Left/WorkspaceSelector.qml b/Bar/Left/WorkspaceSelector.qml index ad8ab27..abc556f 100644 --- a/Bar/Left/WorkspaceSelector.qml +++ b/Bar/Left/WorkspaceSelector.qml @@ -1,15 +1,88 @@ import QtQuick +import QtQuick.Controls import Quickshell import Quickshell.Hyprland +import "../../Color.js" as Colors import "../../Components/" import "../../Services/" Item { id: root + required property double extraHoveredWidth + property bool hovered: extraHoveredWidth > 0 ? true : false + property color selectorColor: Colors.surface2 + required property double selectorFocusedExtra + required property double selectorHeight + required property double selectorWidth required property HyprlandWorkspace workspace + property string workspaceState: WorkspaceManager.getWorkspaceState(workspace) - StyledText { - text: root.workspace.id + implicitWidth: selectorWidth + (root.hovered == true ? (root.workspaceState == "focused" + ? selectorFocusedExtra : 0) : 0) + + Behavior on implicitWidth { + SpringAnimation { + damping: 0.3 + spring: 4 + } + } + states: [ + State { + name: "" + when: root.workspaceState == "inactive" + + PropertyChanges { + root.selectorColor: Colors.surface2 + } + }, + State { + name: "active" + when: root.workspaceState == "active" + + PropertyChanges { + root.selectorColor: Colors.overlay2 + } + }, + State { + name: "focused" + when: root.workspaceState == "focused" + + PropertyChanges { + root.selectorColor: Colors.lavender + } + } + ] + + TapHandler { + id: tapHandler + + onTapped: root.workspace.activate() + } + + anchors { + bottom: parent.bottom + top: parent.top + } + + Rectangle { + color: root.selectorColor + radius: 6 + + Behavior on color { + ColorAnimation { + duration: 100 + } + } + + anchors { + fill: parent + } + + StyledText { + anchors.centerIn: parent + font.pointSize: 10.5 + text: root.workspace.id + } } } diff --git a/Services/WorkspaceManager.qml b/Services/WorkspaceManager.qml index 22acc3b..d238bc9 100644 --- a/Services/WorkspaceManager.qml +++ b/Services/WorkspaceManager.qml @@ -6,6 +6,15 @@ import Quickshell.Hyprland Singleton { id: root + function activateNextFreeWorkspace() { + let nextFree = getNextFreeWorkspace(); + activateWorkspaceById(nextFree); + } + + function activateWorkspaceById(id) { + Hyprland.dispatch(`hl.dsp.focus({workspace = ${id}})`); + } + function getAllNumberedWorkspaces() { let allWorkspaces = Hyprland.workspaces.values; let filteredWorkspaces = []; @@ -20,6 +29,39 @@ Singleton { return filteredWorkspaces; } + function getNextFreeWorkspace() { + let workspaceList = getAllNumberedWorkspaces(); + + if (workspaceList[workspaceList.length - 1].id == workspaceList.length) { + return workspaceList.length + 1; + } else { + let prevWorkspace = 0; + for (let workspace in workspaceList) { + let currentWorkspace = workspaceList[workspace]; + if (currentWorkspace.id != (prevWorkspace + 1)) { + return currentWorkspace.id - 1; + } else { + prevWorkspace = currentWorkspace.id; + } + } + } + } + + function getNumberOfWorkspaces(monitor) { + let workspaceList = getWorkspacesForMonitor(monitor); + return workspaceList.length; + } + + function getWorkspaceState(workspace) { + if (workspace.focused == true) { + return "focused"; + } else if (workspace.active == true) { + return "active"; + } else { + return "inactive"; + } + } + function getWorkspacesForMonitor(monitor) { let allWorkspaces = getAllNumberedWorkspaces(); let monitorWorkspaces = []; @@ -27,7 +69,6 @@ Singleton { for (let workspace in allWorkspaces) { let currentWorkspace = allWorkspaces[workspace]; if (currentWorkspace.monitor == monitor) { - console.log(currentWorkspace.id); if (currentWorkspace) { monitorWorkspaces.push(currentWorkspace); }