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:
@@ -8,6 +8,7 @@ Item {
|
||||
id: clipboardContent
|
||||
|
||||
required property var modal
|
||||
property var transientSurfaceTracker: null
|
||||
|
||||
property alias searchField: searchField
|
||||
property alias clipboardListView: clipboardListView
|
||||
@@ -66,7 +67,7 @@ Item {
|
||||
contextMenu.hide();
|
||||
}
|
||||
|
||||
readonly property bool contextMenuActive: contextMenu.openState
|
||||
readonly property bool contextMenuActive: contextMenu.renderActive
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
@@ -74,6 +75,7 @@ Item {
|
||||
id: contextMenu
|
||||
modal: clipboardContent.modal
|
||||
parentHandler: clipboardContent
|
||||
transientSurfaceTracker: clipboardContent.transientSurfaceTracker
|
||||
}
|
||||
|
||||
Column {
|
||||
|
||||
@@ -23,6 +23,8 @@ Item {
|
||||
property real anchorY: 0
|
||||
property bool openState: false
|
||||
property bool renderActive: false
|
||||
property var transientSurfaceTracker: null
|
||||
readonly property alias contextWindow: menuWindow
|
||||
readonly property bool blurActive: renderActive && openState && BlurService.enabled && Theme.connectedSurfaceBlurEnabled
|
||||
|
||||
readonly property bool hasPinnedDuplicate: !!entry && !entry.pinned && ClipboardService.getPinnedEntryByHash(entry.hash) !== null
|
||||
@@ -90,6 +92,18 @@ Item {
|
||||
readonly property real effectiveMenuHeight: Math.min(maxMenuHeight, naturalMenuHeight)
|
||||
readonly property bool menuScrolls: naturalMenuHeight > effectiveMenuHeight + 0.5
|
||||
|
||||
onRenderActiveChanged: transientSurfaceTracker?.setActive(root, renderActive, contextWindow)
|
||||
Component.onDestruction: transientSurfaceTracker?.unregister(root)
|
||||
|
||||
Connections {
|
||||
target: root.transientSurfaceTracker
|
||||
ignoreUnknownSignals: true
|
||||
|
||||
function onCloseRequested() {
|
||||
root.hide();
|
||||
}
|
||||
}
|
||||
|
||||
TextMetrics {
|
||||
id: menuTextMetrics
|
||||
text: root.longestMenuText
|
||||
|
||||
@@ -9,6 +9,7 @@ FocusScope {
|
||||
|
||||
property var clearConfirmDialog: null
|
||||
property var surfaceHost: null
|
||||
property var transientSurfaceTracker: null
|
||||
|
||||
property string activeTab: "recents"
|
||||
property bool showKeyboardHints: false
|
||||
@@ -198,6 +199,7 @@ FocusScope {
|
||||
id: historyContent
|
||||
anchors.fill: parent
|
||||
modal: root
|
||||
transientSurfaceTracker: root.transientSurfaceTracker
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -130,6 +130,7 @@ DankModal {
|
||||
content: Component {
|
||||
ClipboardHistoryContent {
|
||||
surfaceHost: clipboardHistoryModal
|
||||
transientSurfaceTracker: clipboardHistoryModal.transientSurfaceTracker
|
||||
clearConfirmDialog: clearConfirmDialog
|
||||
onCloseRequested: clipboardHistoryModal.hide()
|
||||
onInstantCloseRequested: clipboardHistoryModal.instantHide()
|
||||
|
||||
@@ -141,6 +141,7 @@ DankPopout {
|
||||
LayoutMirroring.childrenInherit: true
|
||||
|
||||
surfaceHost: root
|
||||
transientSurfaceTracker: root.transientSurfaceTracker
|
||||
clearConfirmDialog: clearConfirmDialog
|
||||
onCloseRequested: root.hide()
|
||||
onInstantCloseRequested: root.hide()
|
||||
|
||||
@@ -2,6 +2,7 @@ import QtQuick
|
||||
import Quickshell.Hyprland
|
||||
import qs.Common
|
||||
import qs.Services
|
||||
import qs.Widgets
|
||||
|
||||
Item {
|
||||
id: root
|
||||
@@ -38,6 +39,7 @@ Item {
|
||||
property bool keepContentLoaded: false
|
||||
property bool keepPopoutsOpen: false
|
||||
property var customKeyboardFocus: null
|
||||
readonly property alias transientSurfaceTracker: _transientSurfaceTracker
|
||||
property bool useOverlayLayer: false
|
||||
|
||||
signal opened
|
||||
@@ -47,6 +49,10 @@ Item {
|
||||
readonly property var contentLoader: impl.item ? impl.item.contentLoader : null
|
||||
readonly property alias modalFocusScope: _modalFocusScope
|
||||
|
||||
TransientSurfaceTracker {
|
||||
id: _transientSurfaceTracker
|
||||
}
|
||||
|
||||
FocusScope {
|
||||
id: _modalFocusScope
|
||||
objectName: "modalFocusScope"
|
||||
@@ -56,7 +62,7 @@ Item {
|
||||
|
||||
// Hyprland OnDemand grab delivers keyboard focus to the modal content surface.
|
||||
HyprlandFocusGrab {
|
||||
windows: root.contentWindow ? [root.contentWindow] : []
|
||||
windows: (root.contentWindow ? [root.contentWindow] : []).concat(root.transientSurfaceTracker?.focusWindows ?? [])
|
||||
active: KeyboardFocus.wantsGrab(root.shouldHaveFocus, root.customKeyboardFocus)
|
||||
|
||||
property var restoreToplevel: null
|
||||
@@ -79,11 +85,13 @@ Item {
|
||||
}
|
||||
|
||||
function close() {
|
||||
transientSurfaceTracker?.closeAll?.();
|
||||
if (impl.item)
|
||||
impl.item.close();
|
||||
}
|
||||
|
||||
function instantClose() {
|
||||
transientSurfaceTracker?.closeAll?.();
|
||||
if (impl.item && typeof impl.item.instantClose === "function")
|
||||
impl.item.instantClose();
|
||||
}
|
||||
@@ -175,6 +183,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;
|
||||
}
|
||||
|
||||
@@ -35,6 +35,10 @@ Item {
|
||||
property real _frozenMotionX: 0
|
||||
property real _frozenMotionY: 0
|
||||
|
||||
TransientSurfaceTracker {
|
||||
id: transientSurfaces
|
||||
}
|
||||
|
||||
readonly property bool useHyprlandFocusGrab: CompositorService.useHyprlandFocusGrab
|
||||
readonly property var effectiveScreen: contentWindow.screen
|
||||
readonly property real screenWidth: effectiveScreen?.width ?? 1920
|
||||
@@ -499,10 +503,18 @@ Item {
|
||||
}
|
||||
|
||||
// Handles hover dismissal grace periods for edge-hover sessions w/cursor
|
||||
readonly property bool _edgeRetractEnabled: (modalHandle && modalHandle.edgeHoverManaged === true) && spotlightOpen && !isClosing
|
||||
readonly property bool _edgeRetractEnabled: (modalHandle && modalHandle.edgeHoverManaged === true) && spotlightOpen && !isClosing && !transientSurfaces.active
|
||||
property bool _edgeBodyHover: false
|
||||
property bool _edgeArmed: false
|
||||
|
||||
on_EdgeRetractEnabledChanged: {
|
||||
if (!_edgeRetractEnabled) {
|
||||
_edgeRetractGrace.stop();
|
||||
} else if (_edgeArmed && !_edgeBodyHover) {
|
||||
_edgeRetractGrace.restart();
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: _edgeRetractGrace
|
||||
interval: 150
|
||||
@@ -534,9 +546,7 @@ Item {
|
||||
|
||||
HyprlandFocusGrab {
|
||||
id: focusGrab
|
||||
readonly property var contextMenuWindow: root.spotlightContent?.activeContextMenu?.contextWindow ?? null
|
||||
readonly property bool contextMenuActive: root.spotlightContent?.activeContextMenu?.renderActive ?? false
|
||||
windows: contextMenuActive && contextMenuWindow ? [contentWindow, contextMenuWindow] : [contentWindow]
|
||||
windows: [contentWindow].concat(transientSurfaces.focusWindows)
|
||||
active: root.useHyprlandFocusGrab && root.spotlightOpen
|
||||
|
||||
onCleared: {
|
||||
@@ -869,6 +879,7 @@ Item {
|
||||
sourceComponent: LauncherContent {
|
||||
focus: true
|
||||
parentModal: root
|
||||
transientSurfaceTracker: transientSurfaces
|
||||
}
|
||||
|
||||
onLoaded: {
|
||||
|
||||
@@ -26,6 +26,10 @@ Item {
|
||||
property string _pendingMode: ""
|
||||
|
||||
readonly property bool useHyprlandFocusGrab: CompositorService.useHyprlandFocusGrab
|
||||
|
||||
TransientSurfaceTracker {
|
||||
id: transientSurfaces
|
||||
}
|
||||
readonly property var effectiveScreen: launcherWindow.screen
|
||||
readonly property real screenWidth: effectiveScreen?.width ?? 1920
|
||||
readonly property real screenHeight: effectiveScreen?.height ?? 1080
|
||||
@@ -228,9 +232,7 @@ Item {
|
||||
|
||||
HyprlandFocusGrab {
|
||||
id: focusGrab
|
||||
readonly property var contextMenuWindow: root.spotlightContent?.activeContextMenu?.contextWindow ?? null
|
||||
readonly property bool contextMenuActive: root.spotlightContent?.activeContextMenu?.renderActive ?? false
|
||||
windows: contextMenuActive && contextMenuWindow ? [launcherWindow, contextMenuWindow] : [launcherWindow]
|
||||
windows: [launcherWindow].concat(transientSurfaces.focusWindows)
|
||||
active: root.useHyprlandFocusGrab && root.keyboardActive
|
||||
onCleared: {
|
||||
if (spotlightOpen)
|
||||
@@ -482,6 +484,7 @@ Item {
|
||||
sourceComponent: SpotlightLauncherContent {
|
||||
focus: true
|
||||
parentModal: root
|
||||
transientSurfaceTracker: transientSurfaces
|
||||
}
|
||||
|
||||
onLoaded: {
|
||||
|
||||
@@ -27,6 +27,10 @@ Item {
|
||||
readonly property bool unloadContentOnClose: SettingsData.dankLauncherV2UnloadOnClose
|
||||
|
||||
readonly property bool useHyprlandFocusGrab: CompositorService.useHyprlandFocusGrab
|
||||
|
||||
TransientSurfaceTracker {
|
||||
id: transientSurfaces
|
||||
}
|
||||
readonly property var effectiveScreen: launcherWindow.screen
|
||||
readonly property real screenWidth: effectiveScreen?.width ?? 1920
|
||||
readonly property real screenHeight: effectiveScreen?.height ?? 1080
|
||||
@@ -260,9 +264,7 @@ Item {
|
||||
|
||||
HyprlandFocusGrab {
|
||||
id: focusGrab
|
||||
readonly property var contextMenuWindow: root.spotlightContent?.activeContextMenu?.contextWindow ?? null
|
||||
readonly property bool contextMenuActive: root.spotlightContent?.activeContextMenu?.renderActive ?? false
|
||||
windows: contextMenuActive && contextMenuWindow ? [launcherWindow, contextMenuWindow] : [launcherWindow]
|
||||
windows: [launcherWindow].concat(transientSurfaces.focusWindows)
|
||||
active: root.useHyprlandFocusGrab && root.keyboardActive
|
||||
|
||||
onCleared: {
|
||||
@@ -530,6 +532,7 @@ Item {
|
||||
sourceComponent: LauncherContent {
|
||||
focus: true
|
||||
parentModal: root
|
||||
transientSurfaceTracker: transientSurfaces
|
||||
}
|
||||
|
||||
onLoaded: {
|
||||
|
||||
@@ -18,6 +18,7 @@ FocusScope {
|
||||
property alias resultsList: resultsList
|
||||
property alias actionPanel: actionPanel
|
||||
readonly property alias activeContextMenu: contextMenu
|
||||
property var transientSurfaceTracker: null
|
||||
|
||||
property bool editMode: false
|
||||
property var editingApp: null
|
||||
@@ -43,7 +44,7 @@ FocusScope {
|
||||
}
|
||||
|
||||
function closeTransientUi() {
|
||||
contextMenu.hide();
|
||||
transientSurfaceTracker?.closeAll?.();
|
||||
actionPanel.hide();
|
||||
root.enabled = true;
|
||||
}
|
||||
@@ -123,6 +124,7 @@ FocusScope {
|
||||
controller: root.controller
|
||||
searchField: root.searchField
|
||||
parentHandler: root
|
||||
transientSurfaceTracker: root.transientSurfaceTracker
|
||||
|
||||
onEditAppRequested: app => {
|
||||
root.openEditMode(app);
|
||||
@@ -779,6 +781,7 @@ FocusScope {
|
||||
anchors.fill: parent
|
||||
controller: root.controller
|
||||
leadingSectionHeaderAtBottom: contentHolder.inverted
|
||||
transientSurfaceTracker: root.transientSurfaceTracker
|
||||
|
||||
onItemRightClicked: (index, item, sceneX, sceneY) => {
|
||||
if (item && contextMenu.hasContextMenuActions(item)) {
|
||||
|
||||
@@ -25,6 +25,7 @@ Item {
|
||||
property real anchorY: 0
|
||||
property bool openState: false
|
||||
property bool renderActive: false
|
||||
property var transientSurfaceTracker: null
|
||||
readonly property alias contextWindow: menuWindow
|
||||
readonly property bool blurActive: renderActive && openState && BlurService.enabled && Theme.connectedSurfaceBlurEnabled
|
||||
|
||||
@@ -49,6 +50,18 @@ Item {
|
||||
signal hideRequested
|
||||
signal editAppRequested(var app)
|
||||
|
||||
onRenderActiveChanged: transientSurfaceTracker?.setActive(root, renderActive, contextWindow)
|
||||
Component.onDestruction: transientSurfaceTracker?.unregister(root)
|
||||
|
||||
Connections {
|
||||
target: root.transientSurfaceTracker
|
||||
ignoreUnknownSignals: true
|
||||
|
||||
function onCloseRequested() {
|
||||
root.hide();
|
||||
}
|
||||
}
|
||||
|
||||
TextMetrics {
|
||||
id: menuTextMetrics
|
||||
text: root.longestMenuText
|
||||
|
||||
@@ -15,6 +15,7 @@ Item {
|
||||
property var _visualRows: []
|
||||
property var _flatIndexToRowMap: ({})
|
||||
property var _cumulativeHeights: []
|
||||
property var transientSurfaceTracker: null
|
||||
readonly property bool _bottomSectionHeaderActive: leadingSectionHeaderAtBottom && (controller?.sections?.length ?? 0) > 0
|
||||
|
||||
signal itemRightClicked(int index, var item, real mouseX, real mouseY)
|
||||
@@ -259,6 +260,7 @@ Item {
|
||||
return root.controller?.canChangeSectionViewMode(delegateRoot.modelData?.sectionId ?? "") ?? false;
|
||||
}
|
||||
canCollapse: root.controller?.canCollapseSection(delegateRoot.modelData?.sectionId ?? "") ?? false
|
||||
transientSurfaceTracker: root.transientSurfaceTracker
|
||||
}
|
||||
|
||||
ResultItem {
|
||||
@@ -447,6 +449,7 @@ Item {
|
||||
return root.controller?.canCollapseSection(stickyHeader.stickyHeaderSection?.id) ?? false;
|
||||
}
|
||||
isSticky: true
|
||||
transientSurfaceTracker: root.transientSurfaceTracker
|
||||
}
|
||||
}
|
||||
|
||||
@@ -472,6 +475,7 @@ Item {
|
||||
canCollapse: root.controller?.canCollapseSection(section?.id ?? "") ?? false
|
||||
isSticky: true
|
||||
popupAbove: true
|
||||
transientSurfaceTracker: root.transientSurfaceTracker
|
||||
}
|
||||
|
||||
Item {
|
||||
|
||||
@@ -17,9 +17,21 @@ Rectangle {
|
||||
property bool isSticky: false
|
||||
property bool popupAbove: false
|
||||
property Item popupAboveItem: null
|
||||
property var transientSurfaceTracker: null
|
||||
|
||||
signal viewModeToggled
|
||||
|
||||
Component.onDestruction: transientSurfaceTracker?.unregister(root)
|
||||
|
||||
Connections {
|
||||
target: root.transientSurfaceTracker
|
||||
ignoreUnknownSignals: true
|
||||
|
||||
function onCloseRequested() {
|
||||
categoryPopup.close();
|
||||
}
|
||||
}
|
||||
|
||||
width: parent?.width ?? 200
|
||||
height: 32
|
||||
color: isSticky ? Theme.withAlpha(Theme.surfaceHover, 0) : (hoverArea.containsMouse ? Theme.surfaceHover : Theme.withAlpha(Theme.surfaceHover, 0))
|
||||
@@ -142,6 +154,8 @@ Rectangle {
|
||||
dim: false
|
||||
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
|
||||
|
||||
onVisibleChanged: root.transientSurfaceTracker?.setActive(root, visible, null)
|
||||
|
||||
background: Rectangle {
|
||||
color: "transparent"
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ FocusScope {
|
||||
property alias searchField: searchInput
|
||||
property alias controller: searchController
|
||||
readonly property alias activeContextMenu: contextMenu
|
||||
property var transientSurfaceTracker: null
|
||||
|
||||
readonly property bool _hasQuery: searchInput.text.length > 0
|
||||
readonly property real _searchBarH: 56
|
||||
@@ -48,7 +49,7 @@ FocusScope {
|
||||
}
|
||||
|
||||
function closeTransientUi() {
|
||||
contextMenu.hide();
|
||||
transientSurfaceTracker?.closeAll?.();
|
||||
root.enabled = true;
|
||||
}
|
||||
|
||||
@@ -220,6 +221,7 @@ FocusScope {
|
||||
searchField: searchInput
|
||||
parentHandler: root
|
||||
allowEditActions: false
|
||||
transientSurfaceTracker: root.transientSurfaceTracker
|
||||
}
|
||||
|
||||
Connections {
|
||||
|
||||
@@ -210,12 +210,14 @@ DankModal {
|
||||
NotificationHeader {
|
||||
id: notificationHeader
|
||||
keyboardController: modalKeyboardController
|
||||
transientSurfaceTracker: notificationModal.transientSurfaceTracker
|
||||
onCurrentTabChanged: notificationModal.currentTab = currentTab
|
||||
Component.onCompleted: notificationModal.notificationHeaderRef = notificationHeader
|
||||
}
|
||||
|
||||
NotificationSettings {
|
||||
id: notificationSettings
|
||||
transientSurfaceTracker: notificationModal.transientSurfaceTracker
|
||||
expanded: notificationHeader.showSettings
|
||||
}
|
||||
|
||||
@@ -225,6 +227,7 @@ DankModal {
|
||||
height: parent.height - y
|
||||
visible: notificationHeader.currentTab === 0
|
||||
keyboardController: modalKeyboardController
|
||||
transientSurfaceTracker: notificationModal.transientSurfaceTracker
|
||||
Component.onCompleted: {
|
||||
notificationModal.notificationListRef = notificationList;
|
||||
if (modalKeyboardController) {
|
||||
|
||||
Reference in New Issue
Block a user