mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-08-01 19:18:28 -04:00
fix(Hover): refactor & update hover tracking w/context menus
Fixes #2737
This commit is contained in:
@@ -54,11 +54,14 @@ Item {
|
||||
property bool addHorizontalPadding: false
|
||||
property string emptyText: ""
|
||||
property bool usePopupTransparency: !checkParentDisablesTransparency()
|
||||
property var transientSurfaceTracker: null
|
||||
|
||||
signal valueChanged(string value)
|
||||
|
||||
property bool menuOpen: false
|
||||
|
||||
onMenuOpenChanged: transientSurfaceTracker?.setActive(root, menuOpen, null)
|
||||
|
||||
function closeDropdownMenu() {
|
||||
if (!root.menuOpen && !dropdownMenu.opened && !dropdownMenu.visible)
|
||||
return;
|
||||
@@ -113,10 +116,20 @@ Item {
|
||||
implicitHeight: !showTrigger ? 0 : (compactMode ? 40 : Math.max(60, labelColumn.implicitHeight + Theme.spacingM))
|
||||
|
||||
Component.onDestruction: {
|
||||
transientSurfaceTracker?.unregister(root);
|
||||
if (root.menuOpen || dropdownMenu.opened || dropdownMenu.visible)
|
||||
dropdownMenu.close();
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: root.transientSurfaceTracker
|
||||
ignoreUnknownSignals: true
|
||||
|
||||
function onCloseRequested() {
|
||||
root.closeDropdownMenu();
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
id: labelColumn
|
||||
|
||||
|
||||
@@ -27,6 +27,8 @@ Item {
|
||||
property bool hoverDismissEnabled: false
|
||||
property bool hoverDismissSuspended: false
|
||||
property var customKeyboardFocus: null
|
||||
readonly property alias transientSurfaceTracker: _transientSurfaceTracker
|
||||
readonly property bool effectiveHoverDismissSuspended: hoverDismissSuspended || (transientSurfaceTracker?.active ?? false)
|
||||
property bool backgroundInteractive: true
|
||||
property bool contentHandlesKeys: false
|
||||
property bool fullHeightSurface: false
|
||||
@@ -55,6 +57,10 @@ Item {
|
||||
readonly property var backgroundWindow: impl.item ? impl.item.backgroundWindow : null
|
||||
readonly property var contentWindow: impl.item ? impl.item.contentWindow : null
|
||||
|
||||
TransientSurfaceTracker {
|
||||
id: _transientSurfaceTracker
|
||||
}
|
||||
|
||||
// Hyprland OnDemand grab: whitelist popout surfaces and bars so dismiss clicks still land.
|
||||
HyprlandFocusGrab {
|
||||
windows: {
|
||||
@@ -63,7 +69,8 @@ Item {
|
||||
list.push(root.contentWindow);
|
||||
if (root.backgroundWindow && root.backgroundWindow !== root.contentWindow)
|
||||
list.push(root.backgroundWindow);
|
||||
return list.concat(KeyboardFocus.barWindows);
|
||||
const transientWindows = root.transientSurfaceTracker?.focusWindows ?? [];
|
||||
return list.concat(transientWindows).concat(KeyboardFocus.barWindows);
|
||||
}
|
||||
active: KeyboardFocus.wantsGrab(root.shouldBeVisible, root.customKeyboardFocus)
|
||||
|
||||
@@ -170,6 +177,7 @@ Item {
|
||||
function close() {
|
||||
_pendingOpen = false;
|
||||
_pendingOpenTimer.stop();
|
||||
transientSurfaceTracker?.closeAll?.();
|
||||
if (impl.item)
|
||||
impl.item.close();
|
||||
}
|
||||
@@ -186,8 +194,9 @@ Item {
|
||||
}
|
||||
|
||||
function closeFromHoverDismiss() {
|
||||
if (hoverDismissSuspended)
|
||||
if (effectiveHoverDismissSuspended)
|
||||
return;
|
||||
transientSurfaceTracker?.closeAll?.();
|
||||
hoverDismissEnabled = false;
|
||||
// Enable animations using standard Theme-bound popout motion to preserve bindings.
|
||||
if (impl.item)
|
||||
@@ -308,7 +317,7 @@ Item {
|
||||
it.effectiveBarPosition = Qt.binding(() => root.effectiveBarPosition);
|
||||
it.effectiveBarBottomGap = Qt.binding(() => root.effectiveBarBottomGap);
|
||||
it.hoverDismissEnabled = Qt.binding(() => root.hoverDismissEnabled);
|
||||
it.hoverDismissSuspended = Qt.binding(() => root.hoverDismissSuspended);
|
||||
it.hoverDismissSuspended = Qt.binding(() => root.effectiveHoverDismissSuspended);
|
||||
|
||||
it.shouldBeVisible = root.shouldBeVisible;
|
||||
if (root._primeContent && typeof it.primeContent === "function")
|
||||
@@ -332,6 +341,8 @@ Item {
|
||||
Connections {
|
||||
target: root
|
||||
function onShouldBeVisibleChanged() {
|
||||
if (!root.shouldBeVisible)
|
||||
root.transientSurfaceTracker?.closeAll?.();
|
||||
if (impl.item && impl.item.shouldBeVisible !== root.shouldBeVisible)
|
||||
impl.item.shouldBeVisible = root.shouldBeVisible;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
pragma ComponentBehavior: Bound
|
||||
|
||||
import QtQuick
|
||||
|
||||
QtObject {
|
||||
id: root
|
||||
|
||||
property var _entries: []
|
||||
readonly property bool active: _entries.length > 0
|
||||
readonly property var focusWindows: _entries.map(entry => entry.focusWindow).filter(window => window)
|
||||
|
||||
signal closeRequested
|
||||
|
||||
function setActive(owner, active, focusWindow) {
|
||||
if (!owner)
|
||||
return;
|
||||
const next = _entries.filter(entry => entry.owner !== owner);
|
||||
if (active) {
|
||||
next.push({
|
||||
"owner": owner,
|
||||
"focusWindow": focusWindow ?? null
|
||||
});
|
||||
}
|
||||
_entries = next;
|
||||
}
|
||||
|
||||
function unregister(owner) {
|
||||
setActive(owner, false, null);
|
||||
}
|
||||
|
||||
function closeAll() {
|
||||
if (_entries.length === 0)
|
||||
return;
|
||||
closeRequested();
|
||||
_entries = [];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user