From 495f76900f0b8c8514036b13d945bb7dec9c23ec Mon Sep 17 00:00:00 2001 From: Marco Allegretti Date: Wed, 27 May 2026 21:32:18 +0200 Subject: [PATCH] Restore dock hover tracking Replace the fullscreen convergence pointer tracker with edge-local hover areas so dock buttons keep receiving hover, tooltip, and cursor events. --- containments/homescreens/folio/qml/main.qml | 108 ++++++++------------ tests/check-convergence-dock-invariant.sh | 12 +++ tests/check-dynamic-tiles-motion.sh | 3 +- 3 files changed, 59 insertions(+), 64 deletions(-) diff --git a/containments/homescreens/folio/qml/main.qml b/containments/homescreens/folio/qml/main.qml index 1cce5531..c7ad5876 100644 --- a/containments/homescreens/folio/qml/main.qml +++ b/containments/homescreens/folio/qml/main.qml @@ -415,6 +415,8 @@ ContainmentItem { function refreshLeftLauncherVisibility() { if (!leftLauncherEnabled) { leftLauncherCloseTimer.stop() + leftEdgeHovered = false + leftLauncherHovered = false leftLauncherOpen = false inputRegionTimer.restart() return @@ -448,54 +450,6 @@ ContainmentItem { inputRegionTimer.restart() } - function updateLeftLauncherHoverState(pointerX, pointerY, withinWindow) { - const insideEdge = withinWindow - && pointerX >= 0 - && pointerX <= leftEdgeHotzoneWidth - && pointerY >= topBarHitHeight - && pointerY <= (height - dockHeight) - - const launcherTop = height - dockHeight - leftLauncherHeight - const insideLauncher = withinWindow - && leftLauncherOpen - && pointerX >= 0 - && pointerX <= leftLauncherWidth - && pointerY >= launcherTop - && pointerY <= (launcherTop + leftLauncherHeight) - - if (leftEdgeHovered !== insideEdge) { - leftEdgeHovered = insideEdge - } - if (leftLauncherHovered !== insideLauncher) { - leftLauncherHovered = insideLauncher - } - refreshLeftLauncherVisibility() - } - - function updateLayoutMenuHoverState(pointerX, pointerY, withinWindow) { - const insideEdge = layoutMenuEnabled - && withinWindow - && pointerX >= (width - rightEdgeHotzoneWidth) - && pointerX <= width - && pointerY >= topBarHitHeight - && pointerY <= (height - dockHeight) - - const insideMenu = withinWindow - && layoutMenuOpen - && pointerX >= rightLayoutMenu.x - && pointerX <= width - && pointerY >= rightLayoutMenu.y - && pointerY <= (rightLayoutMenu.y + rightLayoutMenu.height) - - if (rightEdgeHovered !== insideEdge) { - rightEdgeHovered = insideEdge - } - if (layoutMenuHovered !== insideMenu) { - layoutMenuHovered = insideMenu - } - refreshLayoutMenuVisibility() - } - onActiveChanged: { hoverRevealTimer.stop() hoverRevealing = false @@ -801,6 +755,20 @@ ContainmentItem { anchors.top: topBarSurface.bottom anchors.bottom: dockSurface.top width: convergenceChrome.leftEdgeHotzoneWidth + + MouseArea { + id: leftEdgeHoverArea + anchors.fill: parent + acceptedButtons: Qt.NoButton + enabled: convergenceChrome.leftLauncherEnabled + hoverEnabled: enabled + cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor + + onContainsMouseChanged: { + convergenceChrome.leftEdgeHovered = containsMouse + convergenceChrome.refreshLeftLauncherVisibility() + } + } } Item { @@ -810,23 +778,19 @@ ContainmentItem { anchors.top: topBarSurface.bottom anchors.bottom: dockSurface.top width: convergenceChrome.layoutMenuEnabled ? convergenceChrome.rightEdgeHotzoneWidth : 0 - } - MouseArea { - id: leftLauncherPointerTracker + MouseArea { + id: rightEdgeHoverArea + anchors.fill: parent + acceptedButtons: Qt.NoButton + enabled: convergenceChrome.layoutMenuEnabled + hoverEnabled: enabled + cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor - anchors.fill: parent - acceptedButtons: Qt.NoButton - hoverEnabled: true - z: 10 - - onPositionChanged: (mouse) => { - convergenceChrome.updateLeftLauncherHoverState(mouse.x, mouse.y, true) - convergenceChrome.updateLayoutMenuHoverState(mouse.x, mouse.y, true) - } - onExited: { - convergenceChrome.updateLeftLauncherHoverState(-1, -1, false) - convergenceChrome.updateLayoutMenuHoverState(-1, -1, false) + onContainsMouseChanged: { + convergenceChrome.rightEdgeHovered = containsMouse + convergenceChrome.refreshLayoutMenuVisibility() + } } } @@ -845,6 +809,15 @@ ContainmentItem { surfaceColor: convergenceChrome.chromeColor animationDuration: root.shortAnimationDuration + HoverHandler { + enabled: convergenceChrome.layoutMenuOpen + + onHoveredChanged: { + convergenceChrome.layoutMenuHovered = hovered + convergenceChrome.refreshLayoutMenuVisibility() + } + } + transform: Translate { y: convergenceChrome.layoutMenuOpen ? 0 : Kirigami.Units.gridUnit x: convergenceChrome.layoutMenuOpen ? 0 : rightLayoutMenu.width - convergenceChrome.rightEdgeHotzoneWidth @@ -887,6 +860,15 @@ ContainmentItem { readonly property real cornerRadius: Math.min(MobileShell.Constants.convergenceWorkspaceFrameRadius, height * 0.24) + HoverHandler { + enabled: convergenceChrome.leftLauncherOpen + + onHoveredChanged: { + convergenceChrome.leftLauncherHovered = hovered + convergenceChrome.refreshLeftLauncherVisibility() + } + } + Shape { id: leftLauncherSurface anchors.fill: parent diff --git a/tests/check-convergence-dock-invariant.sh b/tests/check-convergence-dock-invariant.sh index 5f2972b0..36bf02bf 100644 --- a/tests/check-convergence-dock-invariant.sh +++ b/tests/check-convergence-dock-invariant.sh @@ -119,12 +119,24 @@ require_line "$folio_main" "readonly property real workAreaY: topBarHitHeight" require_line "$folio_main" "readonly property real workAreaWidth: Math.max(0, width - frameThickness * 2)" require_line "$folio_main" "readonly property real workAreaHeight: Math.max(0, height - topBarHeight - dockHeight - frameThickness * 2)" require_line "$folio_main" "fillRule: ShapePath.OddEvenFill" +require_line "$folio_main" "id: leftEdgeHoverArea" +require_line "$folio_main" "id: rightEdgeHoverArea" +require_line "$folio_main" "cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor" +require_line "$folio_main" "convergenceChrome.leftEdgeHovered = containsMouse" +require_line "$folio_main" "convergenceChrome.rightEdgeHovered = containsMouse" +require_line "$folio_main" "convergenceChrome.leftLauncherHovered = hovered" +require_line "$folio_main" "convergenceChrome.layoutMenuHovered = hovered" if grep -Fq "root.panel.visibilityMode = (!ShellSettings.Settings.convergenceModeEnabled && ShellSettings.Settings.autoHidePanelsEnabled) ? 3 : 0" "$panel"; then echo "Convergence panel hit area must not reserve extra top space" >&2 exit 1 fi +if grep -Fq "id: leftLauncherPointerTracker" "$folio_main"; then + echo "Folio convergence chrome must not cover the dock with a fullscreen hover tracker" >&2 + exit 1 +fi + require_line "$folio_main" "PathLine { x: convergenceChrome.width; y: convergenceChrome.height - convergenceChrome.dockHeight }" require_line "$folio_main" "PathLine { x: 0; y: convergenceChrome.height - convergenceChrome.dockHeight }" require_line "$folio_main" "PathArc { x: convergenceChrome.workAreaX + convergenceChrome.workAreaWidth - convergenceChrome.frameRadius; y: convergenceChrome.workAreaY + convergenceChrome.workAreaHeight; radiusX: convergenceChrome.frameRadius; radiusY: convergenceChrome.frameRadius }" diff --git a/tests/check-dynamic-tiles-motion.sh b/tests/check-dynamic-tiles-motion.sh index 2f16840e..89f755a3 100644 --- a/tests/check-dynamic-tiles-motion.sh +++ b/tests/check-dynamic-tiles-motion.sh @@ -138,7 +138,8 @@ require_line "$folio_main" "regions.push(rightEdgeRegion)" require_line "$folio_main" "if (layoutMenuEnabled && layoutMenuOpen)" require_line "$folio_main" "rightEdgeHovered = false" require_line "$folio_main" "layoutMenuHovered = false" -require_line "$folio_main" "const insideEdge = layoutMenuEnabled" +require_line "$folio_main" "id: rightEdgeHoverArea" +require_line "$folio_main" "convergenceChrome.rightEdgeHovered = containsMouse" require_line "$folio_main" "width: convergenceChrome.layoutMenuEnabled ? convergenceChrome.rightEdgeHotzoneWidth : 0" running_panel_group_disabled_count="$(grep -F "groupMode: TaskManager.TasksModel.GroupDisabled" "$running_apps_panel" | wc -l)"