From 99f71f858dbc15e8105af89485dd50e293c683d3 Mon Sep 17 00:00:00 2001 From: Damocles Date: Sun, 12 Apr 2026 10:37:29 +0200 Subject: [PATCH] flyout tooltips --- modules/BarIcon.qml | 19 +++++++++++----- modules/BarLabel.qml | 19 +++++++++++----- modules/BarSection.qml | 18 +++++++++++---- modules/BarTooltip.qml | 22 ------------------ modules/Flyout.qml | 50 +++++++++++++++++++++++++++++++++++++++++ modules/FlyoutState.qml | 9 ++++++++ modules/qmldir | 3 ++- shell.qml | 12 ++++++++-- 8 files changed, 113 insertions(+), 39 deletions(-) delete mode 100644 modules/BarTooltip.qml create mode 100644 modules/Flyout.qml create mode 100644 modules/FlyoutState.qml diff --git a/modules/BarIcon.qml b/modules/BarIcon.qml index 17c11e3..87c8204 100644 --- a/modules/BarIcon.qml +++ b/modules/BarIcon.qml @@ -1,8 +1,9 @@ import QtQuick -import QtQuick.Controls +import Quickshell import "." as M Text { + id: root property string icon: "" property string tooltip: "" @@ -12,9 +13,17 @@ Text { font.family: M.Theme.iconFontFamily verticalAlignment: Text.AlignVCenter - HoverHandler { id: _hover } - M.BarTooltip { - visible: _hover.hovered && parent.tooltip !== "" - text: parent.tooltip + HoverHandler { + onHoveredChanged: { + if (hovered && root.tooltip !== "") { + const win = QsWindow.window + M.FlyoutState.text = root.tooltip + M.FlyoutState.itemX = root.mapToItem(win, root.width / 2, 0).x + M.FlyoutState.screen = win?.screen ?? null + M.FlyoutState.visible = true + } else if (!hovered && root.tooltip !== "") { + M.FlyoutState.visible = false + } + } } } diff --git a/modules/BarLabel.qml b/modules/BarLabel.qml index 4f5bc89..4d9d202 100644 --- a/modules/BarLabel.qml +++ b/modules/BarLabel.qml @@ -1,8 +1,9 @@ import QtQuick -import QtQuick.Controls +import Quickshell import "." as M Text { + id: root property string label: "" property string tooltip: "" @@ -12,9 +13,17 @@ Text { font.family: M.Theme.fontFamily verticalAlignment: Text.AlignVCenter - HoverHandler { id: _hover } - M.BarTooltip { - visible: _hover.hovered && parent.tooltip !== "" - text: parent.tooltip + HoverHandler { + onHoveredChanged: { + if (hovered && root.tooltip !== "") { + const win = QsWindow.window + M.FlyoutState.text = root.tooltip + M.FlyoutState.itemX = root.mapToItem(win, root.width / 2, 0).x + M.FlyoutState.screen = win?.screen ?? null + M.FlyoutState.visible = true + } else if (!hovered && root.tooltip !== "") { + M.FlyoutState.visible = false + } + } } } diff --git a/modules/BarSection.qml b/modules/BarSection.qml index 16f5cec..071660e 100644 --- a/modules/BarSection.qml +++ b/modules/BarSection.qml @@ -1,12 +1,22 @@ import QtQuick +import Quickshell import "." as M Row { + id: root property string tooltip: "" - HoverHandler { id: _hover } - M.BarTooltip { - visible: _hover.hovered && parent.tooltip !== "" - text: parent.tooltip + HoverHandler { + onHoveredChanged: { + if (hovered && root.tooltip !== "") { + const win = QsWindow.window + M.FlyoutState.text = root.tooltip + M.FlyoutState.itemX = root.mapToItem(win, root.width / 2, 0).x + M.FlyoutState.screen = win?.screen ?? null + M.FlyoutState.visible = true + } else if (!hovered && root.tooltip !== "") { + M.FlyoutState.visible = false + } + } } } diff --git a/modules/BarTooltip.qml b/modules/BarTooltip.qml deleted file mode 100644 index f6fe501..0000000 --- a/modules/BarTooltip.qml +++ /dev/null @@ -1,22 +0,0 @@ -import QtQuick -import QtQuick.Controls -import "." as M - -ToolTip { - id: tip - padding: 6 - - background: Rectangle { - color: M.Theme.base01 - border.color: M.Theme.base03 - border.width: 1 - radius: 4 - } - - contentItem: Text { - text: tip.text - color: M.Theme.base05 - font.pixelSize: M.Theme.fontSize - font.family: M.Theme.fontFamily - } -} diff --git a/modules/Flyout.qml b/modules/Flyout.qml new file mode 100644 index 0000000..1a8c79e --- /dev/null +++ b/modules/Flyout.qml @@ -0,0 +1,50 @@ +import QtQuick +import Quickshell +import Quickshell.Wayland +import "." as M + +PanelWindow { + id: root + + required property var screen + + visible: M.FlyoutState.visible && M.FlyoutState.screen === screen + color: "transparent" + + WlrLayershell.layer: WlrLayer.Overlay + WlrLayershell.exclusiveZone: 0 + WlrLayershell.namespace: "nova-flyout" + + anchors { + top: true + left: true + right: true + } + + margins.top: M.Theme.barHeight + 4 + implicitHeight: box.implicitHeight + 8 + + Rectangle { + id: box + + x: Math.max(4, Math.min(M.FlyoutState.itemX - implicitWidth / 2, parent.width - implicitWidth - 4)) + y: 4 + + implicitWidth: label.implicitWidth + 16 + implicitHeight: label.implicitHeight + 12 + + color: M.Theme.base01 + border.color: M.Theme.base03 + border.width: 1 + radius: 4 + + Text { + id: label + anchors.centerIn: parent + text: M.FlyoutState.text + color: M.Theme.base05 + font.pixelSize: M.Theme.fontSize + font.family: M.Theme.fontFamily + } + } +} diff --git a/modules/FlyoutState.qml b/modules/FlyoutState.qml new file mode 100644 index 0000000..e2e51b3 --- /dev/null +++ b/modules/FlyoutState.qml @@ -0,0 +1,9 @@ +pragma Singleton +import QtQuick + +QtObject { + property bool visible: false + property string text: "" + property real itemX: 0 + property var screen: null +} diff --git a/modules/qmldir b/modules/qmldir index 0b272ba..9f995c4 100644 --- a/modules/qmldir +++ b/modules/qmldir @@ -1,8 +1,9 @@ module modules singleton Theme 1.0 Theme.qml +singleton FlyoutState 1.0 FlyoutState.qml Bar 1.0 Bar.qml BarSection 1.0 BarSection.qml -BarTooltip 1.0 BarTooltip.qml +Flyout 1.0 Flyout.qml Workspaces 1.0 Workspaces.qml WindowTitle 1.0 WindowTitle.qml Clock 1.0 Clock.qml diff --git a/shell.qml b/shell.qml index c7424a5..6b0317b 100644 --- a/shell.qml +++ b/shell.qml @@ -7,9 +7,17 @@ ShellRoot { Variants { model: Quickshell.screens - delegate: Bar { + Scope { + id: scope required property var modelData - screen: modelData + + Bar { + screen: scope.modelData + } + + Flyout { + screen: scope.modelData + } } } }