From 6eb216475658dda3f921b176ffd6740fc65784ce Mon Sep 17 00:00:00 2001 From: 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com> Date: Thu, 10 Jul 2025 12:59:10 +1000 Subject: internal: add utilities panel base --- modules/Shortcuts.qml | 2 +- modules/drawers/Backgrounds.qml | 8 ++++++ modules/drawers/Drawers.qml | 1 + modules/drawers/Interactions.qml | 41 ++++++++++++++++++++++++++-- modules/drawers/Panels.qml | 11 ++++++++ modules/utilities/Background.qml | 58 ++++++++++++++++++++++++++++++++++++++++ modules/utilities/Content.qml | 31 +++++++++++++++++++++ modules/utilities/Wrapper.qml | 52 +++++++++++++++++++++++++++++++++++ 8 files changed, 201 insertions(+), 3 deletions(-) create mode 100644 modules/utilities/Background.qml create mode 100644 modules/utilities/Content.qml create mode 100644 modules/utilities/Wrapper.qml diff --git a/modules/Shortcuts.qml b/modules/Shortcuts.qml index 3d665ff..fe211bd 100644 --- a/modules/Shortcuts.qml +++ b/modules/Shortcuts.qml @@ -13,7 +13,7 @@ Scope { description: "Toggle launcher, dashboard and osd" onPressed: { const v = Visibilities.getForActive(); - v.launcher = v.dashboard = v.osd = !(v.launcher || v.dashboard || v.osd); + v.launcher = v.dashboard = v.osd = v.utilities = !(v.launcher || v.dashboard || v.osd || v.utilities); } } diff --git a/modules/drawers/Backgrounds.qml b/modules/drawers/Backgrounds.qml index b7e3d39..30f8c9f 100644 --- a/modules/drawers/Backgrounds.qml +++ b/modules/drawers/Backgrounds.qml @@ -6,6 +6,7 @@ import "root:/modules/session" as Session import "root:/modules/launcher" as Launcher import "root:/modules/dashboard" as Dashboard import "root:/modules/bar/popouts" as BarPopouts +import "root:/modules/utilities" as Utilities import QtQuick import QtQuick.Shapes @@ -63,4 +64,11 @@ Shape { startX: wrapper.x startY: wrapper.y - rounding * sideRounding } + + Utilities.Background { + wrapper: panels.utilities + + startX: root.width + startY: root.height + } } diff --git a/modules/drawers/Drawers.qml b/modules/drawers/Drawers.qml index 27088a4..72d8446 100644 --- a/modules/drawers/Drawers.qml +++ b/modules/drawers/Drawers.qml @@ -111,6 +111,7 @@ Variants { property bool session property bool launcher property bool dashboard + property bool utilities Component.onCompleted: Visibilities.screens[scope.modelData] = this } diff --git a/modules/drawers/Interactions.qml b/modules/drawers/Interactions.qml index 54cb24c..b3e717a 100644 --- a/modules/drawers/Interactions.qml +++ b/modules/drawers/Interactions.qml @@ -18,19 +18,28 @@ MouseArea { property point dragStart property bool dashboardShortcutActive property bool osdShortcutActive + property bool utilitiesShortcutActive function withinPanelHeight(panel: Item, x: real, y: real): bool { const panelY = Config.border.thickness + panel.y; return y >= panelY - Config.border.rounding && y <= panelY + panel.height + Config.border.rounding; } + function withinPanelWidth(panel: Item, x: real, y: real): bool { + const panelX = bar.implicitWidth + panel.x; + return x >= panelX - Config.border.rounding && x <= panelX + panel.width + Config.border.rounding; + } + function inRightPanel(panel: Item, x: real, y: real): bool { return x > bar.implicitWidth + panel.x && withinPanelHeight(panel, x, y); } function inTopPanel(panel: Item, x: real, y: real): bool { - const panelX = bar.implicitWidth + panel.x; - return y < Config.border.thickness + panel.y + panel.height && x >= panelX - Config.border.rounding && x <= panelX + panel.width + Config.border.rounding; + return y < Config.border.thickness + panel.y + panel.height && withinPanelWidth(panel, x, y); + } + + function inBottomPanel(panel: Item, x: real, y: real): bool { + return y > root.height - Config.border.thickness - panel.height - Config.border.rounding && withinPanelWidth(panel, x, y); } anchors.fill: parent @@ -47,6 +56,9 @@ MouseArea { if (!dashboardShortcutActive) { visibilities.dashboard = false; } + if (!utilitiesShortcutActive) { + visibilities.utilities = false; + } popouts.hasCurrent = false; } } @@ -88,6 +100,17 @@ MouseArea { dashboardShortcutActive = false; } + // Show utilities on hover + const showUtilities = inBottomPanel(panels.utilities, x, y); + + // Always update visibility based on hover if not in shortcut mode + if (!utilitiesShortcutActive) { + visibilities.utilities = showUtilities; + } else if (showUtilities) { + // If hovering over utilities area while in shortcut mode, transition to hover control + utilitiesShortcutActive = false; + } + // Show popouts on hover const popout = panels.popouts; if (x < bar.implicitWidth + popout.width) { @@ -110,6 +133,7 @@ MouseArea { if (!root.visibilities.launcher) { root.dashboardShortcutActive = false; root.osdShortcutActive = false; + root.utilitiesShortcutActive = false; // Also hide dashboard and OSD if they're not being hovered const inDashboardArea = root.inTopPanel(root.panels.dashboard, root.mouseX, root.mouseY); @@ -150,6 +174,19 @@ MouseArea { root.osdShortcutActive = false; } } + + function onUtilitiesChanged() { + if (root.visibilities.utilities) { + // Utilities became visible, immediately check if this should be shortcut mode + const inUtilitiesArea = root.inBottomPanel(root.panels.utilities, root.mouseX, root.mouseY); + if (!inUtilitiesArea) { + root.utilitiesShortcutActive = true; + } + } else { + // Utilities hidden, clear shortcut flag + root.utilitiesShortcutActive = false; + } + } } Osd.Interactions { diff --git a/modules/drawers/Panels.qml b/modules/drawers/Panels.qml index 909fc9f..b3fe82c 100644 --- a/modules/drawers/Panels.qml +++ b/modules/drawers/Panels.qml @@ -6,6 +6,7 @@ import "root:/modules/session" as Session import "root:/modules/launcher" as Launcher import "root:/modules/dashboard" as Dashboard import "root:/modules/bar/popouts" as BarPopouts +import "root:/modules/utilities" as Utilities import Quickshell import QtQuick @@ -22,6 +23,7 @@ Item { readonly property Launcher.Wrapper launcher: launcher readonly property Dashboard.Wrapper dashboard: dashboard readonly property BarPopouts.Wrapper popouts: popouts + readonly property Utilities.Wrapper utilities: utilities anchors.fill: parent anchors.margins: Config.border.thickness @@ -93,4 +95,13 @@ Item { return off; } } + + Utilities.Wrapper { + id: utilities + + visibility: root.visibilities.utilities + + anchors.bottom: parent.bottom + anchors.right: parent.right + } } diff --git a/modules/utilities/Background.qml b/modules/utilities/Background.qml new file mode 100644 index 0000000..77fd2e5 --- /dev/null +++ b/modules/utilities/Background.qml @@ -0,0 +1,58 @@ +import "root:/services" +import "root:/config" +import Quickshell +import QtQuick +import QtQuick.Shapes + +ShapePath { + id: root + + required property Wrapper wrapper + readonly property real rounding: Config.border.rounding + readonly property bool flatten: wrapper.height < rounding * 2 + readonly property real roundingY: flatten ? wrapper.height / 2 : rounding + + strokeWidth: -1 + fillColor: Colours.palette.m3surface + + PathLine { + relativeX: -(root.wrapper.width + root.rounding) + relativeY: 0 + } + PathArc { + relativeX: root.rounding + relativeY: -root.roundingY + radiusX: root.rounding + radiusY: Math.min(root.rounding, root.wrapper.height) + direction: PathArc.Counterclockwise + } + PathLine { + relativeX: 0 + relativeY: -(root.wrapper.height - root.roundingY * 2) + } + PathArc { + relativeX: root.rounding + relativeY: -root.roundingY + radiusX: root.rounding + radiusY: Math.min(root.rounding, root.wrapper.height) + } + PathLine { + relativeX: root.wrapper.height > 0 ? root.wrapper.width - root.rounding * 2 : root.wrapper.width + relativeY: 0 + } + PathArc { + relativeX: root.rounding + relativeY: -root.rounding + radiusX: root.rounding + radiusY: root.rounding + direction: PathArc.Counterclockwise + } + + Behavior on fillColor { + ColorAnimation { + duration: Appearance.anim.durations.normal + easing.type: Easing.BezierSpline + easing.bezierCurve: Appearance.anim.curves.standard + } + } +} diff --git a/modules/utilities/Content.qml b/modules/utilities/Content.qml new file mode 100644 index 0000000..9b26d1e --- /dev/null +++ b/modules/utilities/Content.qml @@ -0,0 +1,31 @@ +import "root:/widgets" +import "root:/services" +import "root:/config" +import Quickshell +import Quickshell.Widgets +import QtQuick + +Item { + id: root + + anchors.top: parent.top + anchors.bottom: parent.bottom + anchors.right: parent.right + + implicitWidth: 300 + implicitHeight: 100 + + // Rectangle { + // anchors.fill: parent + // } + + Behavior on implicitHeight { + Anim {} + } + + component Anim: NumberAnimation { + duration: Appearance.anim.durations.expressiveDefaultSpatial + easing.type: Easing.BezierSpline + easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial + } +} diff --git a/modules/utilities/Wrapper.qml b/modules/utilities/Wrapper.qml new file mode 100644 index 0000000..3d1d50a --- /dev/null +++ b/modules/utilities/Wrapper.qml @@ -0,0 +1,52 @@ +import "root:/config" +import QtQuick + +Item { + id: root + + required property bool visibility + + visible: height > 0 + implicitHeight: 0 + implicitWidth: content.implicitWidth + + states: State { + name: "visible" + when: root.visibility + + PropertyChanges { + root.implicitHeight: content.implicitHeight + } + } + + transitions: [ + Transition { + from: "" + to: "visible" + + NumberAnimation { + target: root + property: "implicitHeight" + duration: Appearance.anim.durations.expressiveDefaultSpatial + easing.type: Easing.BezierSpline + easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial + } + }, + Transition { + from: "visible" + to: "" + + NumberAnimation { + target: root + property: "implicitHeight" + duration: Appearance.anim.durations.normal + easing.type: Easing.BezierSpline + easing.bezierCurve: Appearance.anim.curves.emphasized + } + } + ] + + Content { + id: content + } +} -- cgit v1.2.3-freya