Ensure you can click to open another panel while one is open

This commit is contained in:
David Heinemeier Hansson
2026-05-18 22:38:53 +02:00
parent 9daa0e6ed3
commit 1a457118a5
3 changed files with 91 additions and 17 deletions
+52 -12
View File
@@ -83,20 +83,17 @@ PanelWindow {
right: true
}
// Clickable region = whole screen MINUS the bar's strip. Clicks on the
// bar pass through to the bar layer; clicks anywhere else are caught
// by us and either land on the card (no-op) or trigger dismissal.
readonly property real _barStripSize: bar ? bar.barSize : 0
// Clickable region is the whole screen. Clicks in the bar strip are
// forwarded to registered bar buttons so switching between panel icons
// works in one click even when the overlay surface is above the bar.
readonly property real _barStripSize: {
if (!bar) return 0
var actual = (root.barPos === "top" || root.barPos === "bottom") ? root.barH : root.barW
return Math.max(bar.barSize, actual) + root.gap
}
mask: Region {
width: root.screenW
height: root.screenH
Region {
x: root.barPos === "right" ? root.screenW - root._barStripSize : 0
y: root.barPos === "bottom" ? root.screenH - root._barStripSize : 0
width: (root.barPos === "top" || root.barPos === "bottom") ? root.screenW : root._barStripSize
height: (root.barPos === "top" || root.barPos === "bottom") ? root._barStripSize : root.screenH
intersection: Intersection.Subtract
}
}
// Track every layout change between the bar's contentItem and the
@@ -177,9 +174,52 @@ PanelWindow {
// during the fade-out so the dying overlay doesn't swallow clicks that
// were meant for the apps behind it.
MouseArea {
id: dismissArea
anchors.fill: parent
enabled: root.open
onClicked: root.closePopout()
hoverEnabled: true
property bool hoveringBar: false
cursorShape: hoveringBar ? Qt.PointingHandCursor : Qt.ArrowCursor
function inBarRegion(px, py) {
if (root.barPos === "bottom") return py >= root.screenH - root._barStripSize
if (root.barPos === "left") return px <= root._barStripSize
if (root.barPos === "right") return px >= root.screenW - root._barStripSize
return py <= root._barStripSize
}
function barPoint(px, py) {
if (root.barPos === "bottom") return Qt.point(px, py - (root.screenH - root.barH))
if (root.barPos === "right") return Qt.point(px - (root.screenW - root.barW), py)
return Qt.point(px, py)
}
function pressTargetAt(px, py) {
if (!root.anchorWindow || !root.anchorWindow.contentItem || !root.bar || !root.bar.clickTargets) return null
var p = barPoint(px, py)
var targets = root.bar.clickTargets
for (var i = targets.length - 1; i >= 0; i--) {
var target = targets[i]
if (!target || !target.triggerPress || target.visible === false || target.opacity === 0 || !target.mapToItem) continue
var pos = root.anchorWindow.itemPosition(target)
if (p.x >= pos.x && p.x <= pos.x + target.width && p.y >= pos.y && p.y <= pos.y + target.height) return target
}
return null
}
function forwardBarClick(px, py, button) {
var target = pressTargetAt(px, py)
if (!target) return false
target.triggerPress(button)
return true
}
onPositionChanged: function(mouse) { hoveringBar = inBarRegion(mouse.x, mouse.y) }
onExited: hoveringBar = false
onClicked: function(mouse) {
if (inBarRegion(mouse.x, mouse.y) && forwardBarClick(mouse.x, mouse.y, mouse.button)) return
root.closePopout()
}
}
// --- card ----------------------------------------------------------------
+17 -4
View File
@@ -18,10 +18,26 @@ Item {
property real textRotation: 0
property bool keepSpace: false
property string tooltipText: ""
property var registeredBar: null
signal pressed(int button)
signal wheelMoved(int delta)
function triggerPress(button) {
if (root.bar) root.bar.hideTooltip(root)
root.pressed(button)
}
function syncClickRegistration() {
if (registeredBar && registeredBar.unregisterClickTarget) registeredBar.unregisterClickTarget(root)
registeredBar = root.bar
if (registeredBar && registeredBar.registerClickTarget) registeredBar.registerClickTarget(root)
}
onBarChanged: syncClickRegistration()
Component.onCompleted: syncClickRegistration()
Component.onDestruction: if (registeredBar && registeredBar.unregisterClickTarget) registeredBar.unregisterClickTarget(root)
readonly property bool vertical: bar ? bar.vertical : false
readonly property int barSize: bar ? bar.barSize : 26
@@ -60,10 +76,7 @@ Item {
cursorShape: Qt.PointingHandCursor
onEntered: if (root.bar) root.bar.showTooltip(root, root.tooltipText)
onExited: if (root.bar) root.bar.hideTooltip(root)
onClicked: function(mouse) {
if (root.bar) root.bar.hideTooltip(root)
root.pressed(mouse.button)
}
onClicked: function(mouse) { root.triggerPress(mouse.button) }
onWheel: function(wheel) { root.wheelMoved(wheel.angleDelta.y) }
}
}
+22 -1
View File
@@ -68,6 +68,19 @@ Item {
property string tooltipText: ""
property bool tooltipShown: false
property var activePopout: null
property var clickTargets: []
function registerClickTarget(target) {
if (!target || clickTargets.indexOf(target) !== -1) return
var next = clickTargets.slice()
next.push(target)
clickTargets = next
}
function unregisterClickTarget(target) {
var next = clickTargets.filter(function(item) { return item !== target })
clickTargets = next
}
function requestPopout(owner) {
if (activePopout === owner) return
@@ -1086,6 +1099,14 @@ Item {
signal pressed(int button)
signal wheelMoved(int delta)
function triggerPress(button) {
root.hideTooltip(buttonRoot)
buttonRoot.pressed(button)
}
Component.onCompleted: root.registerClickTarget(buttonRoot)
Component.onDestruction: root.unregisterClickTarget(buttonRoot)
visible: text !== "" || keepSpace
opacity: text === "" ? 0 : 1
implicitWidth: fixedWidth > 0 ? fixedWidth : (root.vertical ? root.barSize : Math.max(12, label.implicitWidth + horizontalMargin * 2 + rightExtraMargin))
@@ -1113,7 +1134,7 @@ Item {
cursorShape: Qt.PointingHandCursor
onEntered: root.showTooltip(buttonRoot, buttonRoot.tooltipText)
onExited: root.hideTooltip(buttonRoot)
onClicked: function(mouse) { buttonRoot.pressed(mouse.button) }
onClicked: function(mouse) { buttonRoot.triggerPress(mouse.button) }
onWheel: function(wheel) { buttonRoot.wheelMoved(wheel.angleDelta.y) }
}
}