From d638e54ed7b061918bee0fd99c0f3fffcadcb470 Mon Sep 17 00:00:00 2001 From: bbedward Date: Mon, 18 Aug 2025 14:05:27 -0400 Subject: [PATCH] Add RunningApps tooltip --- Modules/TopBar/RunningApps.qml | 34 +++++++++++++- Modules/TopBar/RunningAppsTooltip.qml | 67 +++++++++++++++++++++++++++ Modules/TopBar/TopBar.qml | 1 + 3 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 Modules/TopBar/RunningAppsTooltip.qml diff --git a/Modules/TopBar/RunningApps.qml b/Modules/TopBar/RunningApps.qml index 299e3506..7624177a 100644 --- a/Modules/TopBar/RunningApps.qml +++ b/Modules/TopBar/RunningApps.qml @@ -11,6 +11,11 @@ Rectangle { property string section: "left" property var parentScreen + property var hoveredItem: null + property var topBar: null + + // The visual root for this window + property Item windowRoot: (Window.window ? Window.window.contentItem : null) readonly property int windowCount: NiriService.windows.length readonly property int calculatedWidth: windowCount > 0 ? windowCount * 24 + (windowCount - 1) * Theme.spacingXS + Theme.spacingS * 2 : 0 @@ -19,6 +24,7 @@ Rectangle { height: 30 radius: Theme.cornerRadius visible: windowCount > 0 + clip: false color: { if (windowCount === 0) return "transparent" @@ -38,6 +44,7 @@ Rectangle { model: NiriService.windows delegate: Item { + id: delegateItem property bool isFocused: String(modelData.id) === String(FocusedWindowService.focusedWindowId) property string appId: modelData.app_id || "" property string windowTitle: modelData.title || "(Unnamed)" @@ -122,8 +129,33 @@ Rectangle { onClicked: { NiriService.focusWindow(windowId) } + onEntered: { + root.hoveredItem = delegateItem + var globalPos = delegateItem.mapToGlobal(delegateItem.width / 2, delegateItem.height) + tooltipLoader.active = true + if (tooltipLoader.item) { + var tooltipY = Theme.barHeight + SettingsData.topBarSpacing + Theme.spacingXS + tooltipLoader.item.showTooltip(delegateItem.tooltipText, globalPos.x, tooltipY, root.parentScreen) + } + } + onExited: { + if (root.hoveredItem === delegateItem) { + root.hoveredItem = null + if (tooltipLoader.item) { + tooltipLoader.item.hideTooltip() + } + tooltipLoader.active = false + } + } } } } } -} \ No newline at end of file + + Loader { + id: tooltipLoader + active: false + sourceComponent: RunningAppsTooltip { + } + } +} diff --git a/Modules/TopBar/RunningAppsTooltip.qml b/Modules/TopBar/RunningAppsTooltip.qml new file mode 100644 index 00000000..1fca0fde --- /dev/null +++ b/Modules/TopBar/RunningAppsTooltip.qml @@ -0,0 +1,67 @@ +import QtQuick +import Quickshell +import Quickshell.Wayland +import qs.Common + +PanelWindow { + id: root + + property string tooltipText: "" + property real targetX: 0 + property real targetY: 0 + property var targetScreen: null + + function showTooltip(text, x, y, screen) { + tooltipText = text + targetScreen = screen + + var screenX = screen ? screen.x : 0 + targetX = x - screenX + targetY = y + + visible = true + } + + function hideTooltip() { + visible = false + } + + screen: targetScreen + implicitWidth: Math.min(300, Math.max(120, textContent.implicitWidth + Theme.spacingM * 2)) + implicitHeight: textContent.implicitHeight + Theme.spacingS * 2 + color: "transparent" + visible: false + + WlrLayershell.layer: WlrLayershell.Overlay + WlrLayershell.exclusiveZone: -1 + + anchors { + top: true + left: true + } + + margins { + left: Math.round(targetX - implicitWidth / 2) + top: Math.round(targetY) + } + + Rectangle { + anchors.fill: parent + color: Theme.surfaceContainer + radius: Theme.cornerRadius + border.width: 1 + border.color: Theme.outlineMedium + + Text { + id: textContent + anchors.centerIn: parent + text: root.tooltipText + font.pixelSize: Theme.fontSizeSmall + color: Theme.surfaceText + wrapMode: Text.NoWrap + maximumLineCount: 1 + elide: Text.ElideRight + width: parent.width - Theme.spacingM * 2 + } + } +} \ No newline at end of file diff --git a/Modules/TopBar/TopBar.qml b/Modules/TopBar/TopBar.qml index f6d340d9..4b057168 100644 --- a/Modules/TopBar/TopBar.qml +++ b/Modules/TopBar/TopBar.qml @@ -670,6 +670,7 @@ PanelWindow { return "left" } parentScreen: root.screen + topBar: topBarContent } }