Give the weather panel its host widget's identity in the bar
The bar identifies a panel by the widget mounted in its slot, but the nested panel handed the popout coordinator itself. The open-panel mark never lit under the weather pill, and Tab could not leave the panel. Closing for a popout switch also cleared the shared hover-reveal flag the incoming panel had just set. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
6d4fa7acaf
commit
c2610c3788
@@ -12,6 +12,7 @@ BarWidget {
|
|||||||
if ("bar" in target) target.bar = root.bar
|
if ("bar" in target) target.bar = root.bar
|
||||||
if ("settings" in target) target.settings = root.settings
|
if ("settings" in target) target.settings = root.settings
|
||||||
if ("anchorItem" in target) target.anchorItem = button
|
if ("anchorItem" in target) target.anchorItem = button
|
||||||
|
if ("hostWidget" in target) target.hostWidget = root
|
||||||
}
|
}
|
||||||
|
|
||||||
function refresh() {
|
function refresh() {
|
||||||
@@ -36,6 +37,15 @@ BarWidget {
|
|||||||
if (panelLoader.item && panelLoader.item.close) panelLoader.item.close()
|
if (panelLoader.item && panelLoader.item.close) panelLoader.item.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Forwarded so this widget can stand in for the panel as the bar's popout
|
||||||
|
// identity: Bar.requestPopout prefers closeForPopoutSwitch over close, and
|
||||||
|
// KeyboardPanel reads popoutSwitchClosing back off its owner.
|
||||||
|
readonly property bool popoutSwitchClosing: panelLoader.item ? panelLoader.item.popoutSwitchClosing === true : false
|
||||||
|
|
||||||
|
function closeForPopoutSwitch() {
|
||||||
|
if (panelLoader.item) panelLoader.item.closeForPopoutSwitch()
|
||||||
|
}
|
||||||
|
|
||||||
visible: panelLoader.item && panelLoader.item.label !== ""
|
visible: panelLoader.item && panelLoader.item.label !== ""
|
||||||
implicitWidth: button.implicitWidth
|
implicitWidth: button.implicitWidth
|
||||||
implicitHeight: button.implicitHeight
|
implicitHeight: button.implicitHeight
|
||||||
|
|||||||
@@ -15,6 +15,14 @@ Panel {
|
|||||||
property var anchorItem: null
|
property var anchorItem: null
|
||||||
property bool openedFromHotkey: false
|
property bool openedFromHotkey: false
|
||||||
|
|
||||||
|
// The bar tracks the widget mounted in its slot — BarWidget.qml — not this
|
||||||
|
// nested panel. Everything the bar identifies a panel by has to be that
|
||||||
|
// widget: the popout coordinator (and with it the open-panel dot under the
|
||||||
|
// pill) compares against `slot.activeItem`, and switchPanelFrom looks the
|
||||||
|
// slot up the same way.
|
||||||
|
property var hostWidget: null
|
||||||
|
readonly property var barIdentity: hostWidget || root
|
||||||
|
|
||||||
function open() {
|
function open() {
|
||||||
openedFromHotkey = false
|
openedFromHotkey = false
|
||||||
setCenterHoverRevealSuppressed(false)
|
setCenterHoverRevealSuppressed(false)
|
||||||
@@ -32,7 +40,10 @@ Panel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function close() {
|
function close() {
|
||||||
setCenterHoverRevealSuppressed(false)
|
// 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)
|
||||||
if (root.editingLocation) root.cancelEditingLocation()
|
if (root.editingLocation) root.cancelEditingLocation()
|
||||||
root.controller.hide()
|
root.controller.hide()
|
||||||
}
|
}
|
||||||
@@ -42,6 +53,12 @@ Panel {
|
|||||||
else root.openFromHotkey()
|
else root.openFromHotkey()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function switchPanel(direction) {
|
||||||
|
if (root.bar && typeof root.bar.switchPanelFrom === "function")
|
||||||
|
return root.bar.switchPanelFrom(root.barIdentity, direction)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
function setCenterHoverRevealSuppressed(value) {
|
function setCenterHoverRevealSuppressed(value) {
|
||||||
if (root.bar && "centerHoverRevealSuppressed" in root.bar)
|
if (root.bar && "centerHoverRevealSuppressed" in root.bar)
|
||||||
root.bar.centerHoverRevealSuppressed = value
|
root.bar.centerHoverRevealSuppressed = value
|
||||||
@@ -440,7 +457,7 @@ Panel {
|
|||||||
KeyboardPanel {
|
KeyboardPanel {
|
||||||
id: panel
|
id: panel
|
||||||
anchorItem: root.anchorItem
|
anchorItem: root.anchorItem
|
||||||
owner: root
|
owner: root.barIdentity
|
||||||
bar: root.bar
|
bar: root.bar
|
||||||
open: root.opened
|
open: root.opened
|
||||||
centerOnBar: true
|
centerOnBar: true
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ run_node_test <<'JS'
|
|||||||
const fs = require('fs')
|
const fs = require('fs')
|
||||||
const weather = requireFromRoot('shell/plugins/panels/weather/Model.js')
|
const weather = requireFromRoot('shell/plugins/panels/weather/Model.js')
|
||||||
const panelSource = fs.readFileSync(root + '/shell/plugins/panels/weather/Panel.qml', 'utf8')
|
const panelSource = fs.readFileSync(root + '/shell/plugins/panels/weather/Panel.qml', 'utf8')
|
||||||
|
const widgetSource = fs.readFileSync(root + '/shell/plugins/panels/weather/BarWidget.qml', 'utf8')
|
||||||
|
|
||||||
assertDeepEqual(
|
assertDeepEqual(
|
||||||
weather.parseWeatherStatus('{"text":"☀","class":"sunny"}'),
|
weather.parseWeatherStatus('{"text":"☀","class":"sunny"}'),
|
||||||
@@ -115,6 +116,30 @@ assertEqual(weather.currentIcon({ openMeteoWeatherCode: 0, isDay: 0 }, ''), weat
|
|||||||
assert(weather.iconForOpenMeteoCode(45, true) !== weather.iconForOpenMeteoCode(45, false), 'weather distinguishes nighttime fog from daytime fog')
|
assert(weather.iconForOpenMeteoCode(45, true) !== weather.iconForOpenMeteoCode(45, false), 'weather distinguishes nighttime fog from daytime fog')
|
||||||
assertEqual(weather.provisionalCurrentIcon({ weatherCode: 113 }, ''), weather.iconForCode(113, false), 'weather uses wttr to fill an empty initial icon')
|
assertEqual(weather.provisionalCurrentIcon({ weatherCode: 113 }, ''), weather.iconForCode(113, false), 'weather uses wttr to fill an empty initial icon')
|
||||||
assertEqual(weather.provisionalCurrentIcon({ weatherCode: 113 }, 'night'), 'night', 'weather refresh preserves a resolved day-night icon')
|
assertEqual(weather.provisionalCurrentIcon({ weatherCode: 113 }, 'night'), 'night', 'weather refresh preserves a resolved day-night icon')
|
||||||
|
// The bar identifies a panel by the widget in its slot, so the nested panel
|
||||||
|
// has to present the host widget rather than itself — otherwise the
|
||||||
|
// open-panel dot never lights and Tab cannot leave the panel.
|
||||||
|
assert(
|
||||||
|
panelSource.includes('owner: root.barIdentity'),
|
||||||
|
'weather panel gives the bar its host widget as popout identity'
|
||||||
|
)
|
||||||
|
assert(
|
||||||
|
panelSource.includes('switchPanelFrom(root.barIdentity, direction)'),
|
||||||
|
'weather panel switches panels as its host widget'
|
||||||
|
)
|
||||||
|
assert(
|
||||||
|
widgetSource.includes('target.hostWidget = root'),
|
||||||
|
'weather widget injects itself as the panel host'
|
||||||
|
)
|
||||||
|
assert(
|
||||||
|
widgetSource.includes('readonly property bool popoutSwitchClosing:') && widgetSource.includes('function closeForPopoutSwitch()'),
|
||||||
|
'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'
|
||||||
|
)
|
||||||
|
|
||||||
assert(
|
assert(
|
||||||
panelSource.includes('text: root.label || "—"'),
|
panelSource.includes('text: root.label || "—"'),
|
||||||
'weather hero and bar use the same resolved icon'
|
'weather hero and bar use the same resolved icon'
|
||||||
|
|||||||
Reference in New Issue
Block a user