From c6198654326ac404f1a278599318a4683ef3db61 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Sun, 26 Jul 2026 19:16:05 -0700 Subject: [PATCH] Keep the center hover reveal honest when panels hand off Claiming the shared suppression flag before showing meant the outgoing panel's close cleared it again, leaving the incoming panel open with the indicators still revealed. Guarding the clear instead only moved the problem: handing off to a panel that does not manage the flag left it stuck on, and the center indicators stopped revealing on hover for good. Claim it after the handoff instead. The panel taking over always wins, and a handoff to a panel that knows nothing about the flag still leaves it cleared. Co-Authored-By: Claude Opus 5 (1M context) --- shell/plugins/panels/clock/Panel.qml | 14 +++++++++----- shell/plugins/panels/weather/Panel.qml | 14 +++++++++----- test/shell.d/clock-test.sh | 3 ++- test/shell.d/weather-test.sh | 4 ++-- 4 files changed, 22 insertions(+), 13 deletions(-) diff --git a/shell/plugins/panels/clock/Panel.qml b/shell/plugins/panels/clock/Panel.qml index f12950d6..aba21af9 100644 --- a/shell/plugins/panels/clock/Panel.qml +++ b/shell/plugins/panels/clock/Panel.qml @@ -70,16 +70,20 @@ Panel { readonly property int gutterWidth: Style.space(14) function open() { - setCenterHoverRevealSuppressed(true) refresh() root.controller.show() + // Set after showing, not before: showing hands the popout coordinator + // over, which closes whichever panel was open, and that close clears the + // shared flag. Deferring means the panel taking over always wins, while + // a handoff to a panel that does not manage the flag still leaves it + // cleared rather than stuck on. + Qt.callLater(function() { + if (root.opened) setCenterHoverRevealSuppressed(true) + }) } function close() { - // Not when another panel is taking over: it has already set the shared - // flag for itself, and clearing it here would leave the incoming panel - // open with the center indicators revealed behind it. - if (!root.popoutSwitchClosing) setCenterHoverRevealSuppressed(false) + setCenterHoverRevealSuppressed(false) root.controller.hide() } diff --git a/shell/plugins/panels/weather/Panel.qml b/shell/plugins/panels/weather/Panel.qml index 35df14f9..3757d942 100644 --- a/shell/plugins/panels/weather/Panel.qml +++ b/shell/plugins/panels/weather/Panel.qml @@ -33,17 +33,21 @@ Panel { function openFromHotkey() { openedFromHotkey = true - setCenterHoverRevealSuppressed(true) root.controller.show() locationFile.reload() root.refresh() + // Set after showing, not before: showing hands the popout coordinator + // over, which closes whichever panel was open, and that close clears the + // shared flag. Deferring means the panel taking over always wins, while + // a handoff to a panel that does not manage the flag still leaves it + // cleared rather than stuck on. + Qt.callLater(function() { + if (root.opened) setCenterHoverRevealSuppressed(true) + }) } function close() { - // Not when another panel is taking over: it has already set the shared - // flag for itself, and clearing it here would leave the incoming panel - // open with the center indicators revealed behind it. - if (!root.popoutSwitchClosing) setCenterHoverRevealSuppressed(false) + setCenterHoverRevealSuppressed(false) if (root.editingLocation) root.cancelEditingLocation() root.controller.hide() } diff --git a/test/shell.d/clock-test.sh b/test/shell.d/clock-test.sh index eef31506..db9e6a85 100755 --- a/test/shell.d/clock-test.sh +++ b/test/shell.d/clock-test.sh @@ -115,7 +115,8 @@ assert(!/property bool onToday/.test(panelSource) && !/root\.onToday/.test(panel assert(/readonly property bool viewingCurrentMonth:/.test(panelSource), 'calendar panel tracks whether the current month is on screen') assert(!/MouseArea/.test(panelSource.slice(panelSource.indexOf('model: modelData.days'), panelSource.indexOf('// Hairline'))), 'calendar day cells are not selectable') assert(/yearDone: Model\.yearProgress\(today\./.test(panelSource), 'calendar year bar stays pinned to today while months are stepped') -assert(/if \(!root\.popoutSwitchClosing\) setCenterHoverRevealSuppressed\(false\)/.test(panelSource), 'calendar leaves the shared hover-reveal flag alone when another panel takes over') +assert(/Qt\.callLater\(function\(\) \{\s*\n\s*if \(root\.opened\) setCenterHoverRevealSuppressed\(true\)/.test(panelSource), 'calendar claims the shared hover-reveal flag after the popout handoff, so the panel taking over wins') +assert(/function close\(\) \{\s*\n\s*setCenterHoverRevealSuppressed\(false\)/.test(panelSource), 'calendar always releases the shared hover-reveal flag on close') assert(/width: Math\.max\(calendarScroll\.width, gridColumn\.width\)/.test(panelSource), 'calendar scrolls rather than clipping the grid on a narrow popup') assert(/enabled: !root\.viewingCurrentMonth/.test(panelSource) && /onClicked: root\.goToToday\(\)/.test(panelSource), 'calendar hero returns to today once the view has stepped away') assert(!/clampMonth/.test(panelSource), 'calendar steps freely into future months') diff --git a/test/shell.d/weather-test.sh b/test/shell.d/weather-test.sh index 954cbf41..bc94c11b 100644 --- a/test/shell.d/weather-test.sh +++ b/test/shell.d/weather-test.sh @@ -136,8 +136,8 @@ assert( 'weather widget forwards the popout-switch handshake' ) assert( - panelSource.includes('if (!root.popoutSwitchClosing) setCenterHoverRevealSuppressed(false)'), - 'weather leaves the shared hover-reveal flag alone when another panel takes over' + /Qt\.callLater\(function\(\) \{\s*\n\s*if \(root\.opened\) setCenterHoverRevealSuppressed\(true\)/.test(panelSource), + 'weather claims the shared hover-reveal flag after the popout handoff, so the panel taking over wins' ) assert(