mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-08-08 14:38:30 -04:00
fix(Hover): refactor & update hover tracking w/context menus
Fixes #2737
This commit is contained in:
@@ -79,12 +79,6 @@ Singleton {
|
|||||||
|
|
||||||
function _closePopout(popout) {
|
function _closePopout(popout) {
|
||||||
try {
|
try {
|
||||||
if (popout?.hoverDismissEnabled) {
|
|
||||||
if (typeof popout.closeFromHoverDismiss === "function") {
|
|
||||||
popout.closeFromHoverDismiss();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (popout.hoverDismissEnabled !== undefined)
|
if (popout.hoverDismissEnabled !== undefined)
|
||||||
popout.hoverDismissEnabled = false;
|
popout.hoverDismissEnabled = false;
|
||||||
switch (true) {
|
switch (true) {
|
||||||
@@ -104,6 +98,20 @@ Singleton {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function _dismissPopoutFromHover(popout) {
|
||||||
|
try {
|
||||||
|
if (!popout || popout.hoverDismissEnabled !== true)
|
||||||
|
return;
|
||||||
|
if (typeof popout.closeFromHoverDismiss === "function") {
|
||||||
|
popout.closeFromHoverDismiss();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_closePopout(popout);
|
||||||
|
} catch (e) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function _isStale(popout) {
|
function _isStale(popout) {
|
||||||
try {
|
try {
|
||||||
if (!popout || !("shouldBeVisible" in popout))
|
if (!popout || !("shouldBeVisible" in popout))
|
||||||
@@ -174,6 +182,19 @@ Singleton {
|
|||||||
_closePopout(popout);
|
_closePopout(popout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function dismissHoverPopoutForScreen(screen) {
|
||||||
|
if (!screen)
|
||||||
|
return;
|
||||||
|
const screenName = screen.name;
|
||||||
|
const popout = currentPopoutsByScreen[screenName];
|
||||||
|
if (!popout || _isStale(popout)) {
|
||||||
|
currentPopoutsByScreen[screenName] = null;
|
||||||
|
currentPopoutTriggers[screenName] = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_dismissPopoutFromHover(popout);
|
||||||
|
}
|
||||||
|
|
||||||
function cancelHoverDismiss(screen) {
|
function cancelHoverDismiss(screen) {
|
||||||
const popout = getActivePopout(screen);
|
const popout = getActivePopout(screen);
|
||||||
if (popout?.cancelHoverDismiss)
|
if (popout?.cancelHoverDismiss)
|
||||||
@@ -191,7 +212,8 @@ Singleton {
|
|||||||
const p = getActivePopout(screen);
|
const p = getActivePopout(screen);
|
||||||
if (!p || !_isPopoutPresented(p))
|
if (!p || !_isPopoutPresented(p))
|
||||||
return false;
|
return false;
|
||||||
return p.hoverDismissEnabled === false || p.hoverDismissSuspended === true;
|
const dismissSuspended = p.effectiveHoverDismissSuspended ?? p.hoverDismissSuspended;
|
||||||
|
return p.hoverDismissEnabled === false || dismissSuspended === true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isCurrentPopout(popout, screenName) {
|
function isCurrentPopout(popout, screenName) {
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ Item {
|
|||||||
id: clipboardContent
|
id: clipboardContent
|
||||||
|
|
||||||
required property var modal
|
required property var modal
|
||||||
|
property var transientSurfaceTracker: null
|
||||||
|
|
||||||
property alias searchField: searchField
|
property alias searchField: searchField
|
||||||
property alias clipboardListView: clipboardListView
|
property alias clipboardListView: clipboardListView
|
||||||
@@ -66,7 +67,7 @@ Item {
|
|||||||
contextMenu.hide();
|
contextMenu.hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly property bool contextMenuActive: contextMenu.openState
|
readonly property bool contextMenuActive: contextMenu.renderActive
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
||||||
@@ -74,6 +75,7 @@ Item {
|
|||||||
id: contextMenu
|
id: contextMenu
|
||||||
modal: clipboardContent.modal
|
modal: clipboardContent.modal
|
||||||
parentHandler: clipboardContent
|
parentHandler: clipboardContent
|
||||||
|
transientSurfaceTracker: clipboardContent.transientSurfaceTracker
|
||||||
}
|
}
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ Item {
|
|||||||
property real anchorY: 0
|
property real anchorY: 0
|
||||||
property bool openState: false
|
property bool openState: false
|
||||||
property bool renderActive: 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 blurActive: renderActive && openState && BlurService.enabled && Theme.connectedSurfaceBlurEnabled
|
||||||
|
|
||||||
readonly property bool hasPinnedDuplicate: !!entry && !entry.pinned && ClipboardService.getPinnedEntryByHash(entry.hash) !== null
|
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 real effectiveMenuHeight: Math.min(maxMenuHeight, naturalMenuHeight)
|
||||||
readonly property bool menuScrolls: naturalMenuHeight > effectiveMenuHeight + 0.5
|
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 {
|
TextMetrics {
|
||||||
id: menuTextMetrics
|
id: menuTextMetrics
|
||||||
text: root.longestMenuText
|
text: root.longestMenuText
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ FocusScope {
|
|||||||
|
|
||||||
property var clearConfirmDialog: null
|
property var clearConfirmDialog: null
|
||||||
property var surfaceHost: null
|
property var surfaceHost: null
|
||||||
|
property var transientSurfaceTracker: null
|
||||||
|
|
||||||
property string activeTab: "recents"
|
property string activeTab: "recents"
|
||||||
property bool showKeyboardHints: false
|
property bool showKeyboardHints: false
|
||||||
@@ -198,6 +199,7 @@ FocusScope {
|
|||||||
id: historyContent
|
id: historyContent
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
modal: root
|
modal: root
|
||||||
|
transientSurfaceTracker: root.transientSurfaceTracker
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -130,6 +130,7 @@ DankModal {
|
|||||||
content: Component {
|
content: Component {
|
||||||
ClipboardHistoryContent {
|
ClipboardHistoryContent {
|
||||||
surfaceHost: clipboardHistoryModal
|
surfaceHost: clipboardHistoryModal
|
||||||
|
transientSurfaceTracker: clipboardHistoryModal.transientSurfaceTracker
|
||||||
clearConfirmDialog: clearConfirmDialog
|
clearConfirmDialog: clearConfirmDialog
|
||||||
onCloseRequested: clipboardHistoryModal.hide()
|
onCloseRequested: clipboardHistoryModal.hide()
|
||||||
onInstantCloseRequested: clipboardHistoryModal.instantHide()
|
onInstantCloseRequested: clipboardHistoryModal.instantHide()
|
||||||
|
|||||||
@@ -141,6 +141,7 @@ DankPopout {
|
|||||||
LayoutMirroring.childrenInherit: true
|
LayoutMirroring.childrenInherit: true
|
||||||
|
|
||||||
surfaceHost: root
|
surfaceHost: root
|
||||||
|
transientSurfaceTracker: root.transientSurfaceTracker
|
||||||
clearConfirmDialog: clearConfirmDialog
|
clearConfirmDialog: clearConfirmDialog
|
||||||
onCloseRequested: root.hide()
|
onCloseRequested: root.hide()
|
||||||
onInstantCloseRequested: root.hide()
|
onInstantCloseRequested: root.hide()
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import QtQuick
|
|||||||
import Quickshell.Hyprland
|
import Quickshell.Hyprland
|
||||||
import qs.Common
|
import qs.Common
|
||||||
import qs.Services
|
import qs.Services
|
||||||
|
import qs.Widgets
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
@@ -38,6 +39,7 @@ Item {
|
|||||||
property bool keepContentLoaded: false
|
property bool keepContentLoaded: false
|
||||||
property bool keepPopoutsOpen: false
|
property bool keepPopoutsOpen: false
|
||||||
property var customKeyboardFocus: null
|
property var customKeyboardFocus: null
|
||||||
|
readonly property alias transientSurfaceTracker: _transientSurfaceTracker
|
||||||
property bool useOverlayLayer: false
|
property bool useOverlayLayer: false
|
||||||
|
|
||||||
signal opened
|
signal opened
|
||||||
@@ -47,6 +49,10 @@ Item {
|
|||||||
readonly property var contentLoader: impl.item ? impl.item.contentLoader : null
|
readonly property var contentLoader: impl.item ? impl.item.contentLoader : null
|
||||||
readonly property alias modalFocusScope: _modalFocusScope
|
readonly property alias modalFocusScope: _modalFocusScope
|
||||||
|
|
||||||
|
TransientSurfaceTracker {
|
||||||
|
id: _transientSurfaceTracker
|
||||||
|
}
|
||||||
|
|
||||||
FocusScope {
|
FocusScope {
|
||||||
id: _modalFocusScope
|
id: _modalFocusScope
|
||||||
objectName: "modalFocusScope"
|
objectName: "modalFocusScope"
|
||||||
@@ -56,7 +62,7 @@ Item {
|
|||||||
|
|
||||||
// Hyprland OnDemand grab delivers keyboard focus to the modal content surface.
|
// Hyprland OnDemand grab delivers keyboard focus to the modal content surface.
|
||||||
HyprlandFocusGrab {
|
HyprlandFocusGrab {
|
||||||
windows: root.contentWindow ? [root.contentWindow] : []
|
windows: (root.contentWindow ? [root.contentWindow] : []).concat(root.transientSurfaceTracker?.focusWindows ?? [])
|
||||||
active: KeyboardFocus.wantsGrab(root.shouldHaveFocus, root.customKeyboardFocus)
|
active: KeyboardFocus.wantsGrab(root.shouldHaveFocus, root.customKeyboardFocus)
|
||||||
|
|
||||||
property var restoreToplevel: null
|
property var restoreToplevel: null
|
||||||
@@ -79,11 +85,13 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function close() {
|
function close() {
|
||||||
|
transientSurfaceTracker?.closeAll?.();
|
||||||
if (impl.item)
|
if (impl.item)
|
||||||
impl.item.close();
|
impl.item.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
function instantClose() {
|
function instantClose() {
|
||||||
|
transientSurfaceTracker?.closeAll?.();
|
||||||
if (impl.item && typeof impl.item.instantClose === "function")
|
if (impl.item && typeof impl.item.instantClose === "function")
|
||||||
impl.item.instantClose();
|
impl.item.instantClose();
|
||||||
}
|
}
|
||||||
@@ -175,6 +183,8 @@ Item {
|
|||||||
Connections {
|
Connections {
|
||||||
target: root
|
target: root
|
||||||
function onShouldBeVisibleChanged() {
|
function onShouldBeVisibleChanged() {
|
||||||
|
if (!root.shouldBeVisible)
|
||||||
|
root.transientSurfaceTracker?.closeAll?.();
|
||||||
if (impl.item && impl.item.shouldBeVisible !== root.shouldBeVisible)
|
if (impl.item && impl.item.shouldBeVisible !== root.shouldBeVisible)
|
||||||
impl.item.shouldBeVisible = root.shouldBeVisible;
|
impl.item.shouldBeVisible = root.shouldBeVisible;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,10 @@ Item {
|
|||||||
property real _frozenMotionX: 0
|
property real _frozenMotionX: 0
|
||||||
property real _frozenMotionY: 0
|
property real _frozenMotionY: 0
|
||||||
|
|
||||||
|
TransientSurfaceTracker {
|
||||||
|
id: transientSurfaces
|
||||||
|
}
|
||||||
|
|
||||||
readonly property bool useHyprlandFocusGrab: CompositorService.useHyprlandFocusGrab
|
readonly property bool useHyprlandFocusGrab: CompositorService.useHyprlandFocusGrab
|
||||||
readonly property var effectiveScreen: contentWindow.screen
|
readonly property var effectiveScreen: contentWindow.screen
|
||||||
readonly property real screenWidth: effectiveScreen?.width ?? 1920
|
readonly property real screenWidth: effectiveScreen?.width ?? 1920
|
||||||
@@ -499,10 +503,18 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handles hover dismissal grace periods for edge-hover sessions w/cursor
|
// 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 _edgeBodyHover: false
|
||||||
property bool _edgeArmed: false
|
property bool _edgeArmed: false
|
||||||
|
|
||||||
|
on_EdgeRetractEnabledChanged: {
|
||||||
|
if (!_edgeRetractEnabled) {
|
||||||
|
_edgeRetractGrace.stop();
|
||||||
|
} else if (_edgeArmed && !_edgeBodyHover) {
|
||||||
|
_edgeRetractGrace.restart();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Timer {
|
Timer {
|
||||||
id: _edgeRetractGrace
|
id: _edgeRetractGrace
|
||||||
interval: 150
|
interval: 150
|
||||||
@@ -534,9 +546,7 @@ Item {
|
|||||||
|
|
||||||
HyprlandFocusGrab {
|
HyprlandFocusGrab {
|
||||||
id: focusGrab
|
id: focusGrab
|
||||||
readonly property var contextMenuWindow: root.spotlightContent?.activeContextMenu?.contextWindow ?? null
|
windows: [contentWindow].concat(transientSurfaces.focusWindows)
|
||||||
readonly property bool contextMenuActive: root.spotlightContent?.activeContextMenu?.renderActive ?? false
|
|
||||||
windows: contextMenuActive && contextMenuWindow ? [contentWindow, contextMenuWindow] : [contentWindow]
|
|
||||||
active: root.useHyprlandFocusGrab && root.spotlightOpen
|
active: root.useHyprlandFocusGrab && root.spotlightOpen
|
||||||
|
|
||||||
onCleared: {
|
onCleared: {
|
||||||
@@ -869,6 +879,7 @@ Item {
|
|||||||
sourceComponent: LauncherContent {
|
sourceComponent: LauncherContent {
|
||||||
focus: true
|
focus: true
|
||||||
parentModal: root
|
parentModal: root
|
||||||
|
transientSurfaceTracker: transientSurfaces
|
||||||
}
|
}
|
||||||
|
|
||||||
onLoaded: {
|
onLoaded: {
|
||||||
|
|||||||
@@ -26,6 +26,10 @@ Item {
|
|||||||
property string _pendingMode: ""
|
property string _pendingMode: ""
|
||||||
|
|
||||||
readonly property bool useHyprlandFocusGrab: CompositorService.useHyprlandFocusGrab
|
readonly property bool useHyprlandFocusGrab: CompositorService.useHyprlandFocusGrab
|
||||||
|
|
||||||
|
TransientSurfaceTracker {
|
||||||
|
id: transientSurfaces
|
||||||
|
}
|
||||||
readonly property var effectiveScreen: launcherWindow.screen
|
readonly property var effectiveScreen: launcherWindow.screen
|
||||||
readonly property real screenWidth: effectiveScreen?.width ?? 1920
|
readonly property real screenWidth: effectiveScreen?.width ?? 1920
|
||||||
readonly property real screenHeight: effectiveScreen?.height ?? 1080
|
readonly property real screenHeight: effectiveScreen?.height ?? 1080
|
||||||
@@ -228,9 +232,7 @@ Item {
|
|||||||
|
|
||||||
HyprlandFocusGrab {
|
HyprlandFocusGrab {
|
||||||
id: focusGrab
|
id: focusGrab
|
||||||
readonly property var contextMenuWindow: root.spotlightContent?.activeContextMenu?.contextWindow ?? null
|
windows: [launcherWindow].concat(transientSurfaces.focusWindows)
|
||||||
readonly property bool contextMenuActive: root.spotlightContent?.activeContextMenu?.renderActive ?? false
|
|
||||||
windows: contextMenuActive && contextMenuWindow ? [launcherWindow, contextMenuWindow] : [launcherWindow]
|
|
||||||
active: root.useHyprlandFocusGrab && root.keyboardActive
|
active: root.useHyprlandFocusGrab && root.keyboardActive
|
||||||
onCleared: {
|
onCleared: {
|
||||||
if (spotlightOpen)
|
if (spotlightOpen)
|
||||||
@@ -482,6 +484,7 @@ Item {
|
|||||||
sourceComponent: SpotlightLauncherContent {
|
sourceComponent: SpotlightLauncherContent {
|
||||||
focus: true
|
focus: true
|
||||||
parentModal: root
|
parentModal: root
|
||||||
|
transientSurfaceTracker: transientSurfaces
|
||||||
}
|
}
|
||||||
|
|
||||||
onLoaded: {
|
onLoaded: {
|
||||||
|
|||||||
@@ -27,6 +27,10 @@ Item {
|
|||||||
readonly property bool unloadContentOnClose: SettingsData.dankLauncherV2UnloadOnClose
|
readonly property bool unloadContentOnClose: SettingsData.dankLauncherV2UnloadOnClose
|
||||||
|
|
||||||
readonly property bool useHyprlandFocusGrab: CompositorService.useHyprlandFocusGrab
|
readonly property bool useHyprlandFocusGrab: CompositorService.useHyprlandFocusGrab
|
||||||
|
|
||||||
|
TransientSurfaceTracker {
|
||||||
|
id: transientSurfaces
|
||||||
|
}
|
||||||
readonly property var effectiveScreen: launcherWindow.screen
|
readonly property var effectiveScreen: launcherWindow.screen
|
||||||
readonly property real screenWidth: effectiveScreen?.width ?? 1920
|
readonly property real screenWidth: effectiveScreen?.width ?? 1920
|
||||||
readonly property real screenHeight: effectiveScreen?.height ?? 1080
|
readonly property real screenHeight: effectiveScreen?.height ?? 1080
|
||||||
@@ -260,9 +264,7 @@ Item {
|
|||||||
|
|
||||||
HyprlandFocusGrab {
|
HyprlandFocusGrab {
|
||||||
id: focusGrab
|
id: focusGrab
|
||||||
readonly property var contextMenuWindow: root.spotlightContent?.activeContextMenu?.contextWindow ?? null
|
windows: [launcherWindow].concat(transientSurfaces.focusWindows)
|
||||||
readonly property bool contextMenuActive: root.spotlightContent?.activeContextMenu?.renderActive ?? false
|
|
||||||
windows: contextMenuActive && contextMenuWindow ? [launcherWindow, contextMenuWindow] : [launcherWindow]
|
|
||||||
active: root.useHyprlandFocusGrab && root.keyboardActive
|
active: root.useHyprlandFocusGrab && root.keyboardActive
|
||||||
|
|
||||||
onCleared: {
|
onCleared: {
|
||||||
@@ -530,6 +532,7 @@ Item {
|
|||||||
sourceComponent: LauncherContent {
|
sourceComponent: LauncherContent {
|
||||||
focus: true
|
focus: true
|
||||||
parentModal: root
|
parentModal: root
|
||||||
|
transientSurfaceTracker: transientSurfaces
|
||||||
}
|
}
|
||||||
|
|
||||||
onLoaded: {
|
onLoaded: {
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ FocusScope {
|
|||||||
property alias resultsList: resultsList
|
property alias resultsList: resultsList
|
||||||
property alias actionPanel: actionPanel
|
property alias actionPanel: actionPanel
|
||||||
readonly property alias activeContextMenu: contextMenu
|
readonly property alias activeContextMenu: contextMenu
|
||||||
|
property var transientSurfaceTracker: null
|
||||||
|
|
||||||
property bool editMode: false
|
property bool editMode: false
|
||||||
property var editingApp: null
|
property var editingApp: null
|
||||||
@@ -43,7 +44,7 @@ FocusScope {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function closeTransientUi() {
|
function closeTransientUi() {
|
||||||
contextMenu.hide();
|
transientSurfaceTracker?.closeAll?.();
|
||||||
actionPanel.hide();
|
actionPanel.hide();
|
||||||
root.enabled = true;
|
root.enabled = true;
|
||||||
}
|
}
|
||||||
@@ -123,6 +124,7 @@ FocusScope {
|
|||||||
controller: root.controller
|
controller: root.controller
|
||||||
searchField: root.searchField
|
searchField: root.searchField
|
||||||
parentHandler: root
|
parentHandler: root
|
||||||
|
transientSurfaceTracker: root.transientSurfaceTracker
|
||||||
|
|
||||||
onEditAppRequested: app => {
|
onEditAppRequested: app => {
|
||||||
root.openEditMode(app);
|
root.openEditMode(app);
|
||||||
@@ -779,6 +781,7 @@ FocusScope {
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
controller: root.controller
|
controller: root.controller
|
||||||
leadingSectionHeaderAtBottom: contentHolder.inverted
|
leadingSectionHeaderAtBottom: contentHolder.inverted
|
||||||
|
transientSurfaceTracker: root.transientSurfaceTracker
|
||||||
|
|
||||||
onItemRightClicked: (index, item, sceneX, sceneY) => {
|
onItemRightClicked: (index, item, sceneX, sceneY) => {
|
||||||
if (item && contextMenu.hasContextMenuActions(item)) {
|
if (item && contextMenu.hasContextMenuActions(item)) {
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ Item {
|
|||||||
property real anchorY: 0
|
property real anchorY: 0
|
||||||
property bool openState: false
|
property bool openState: false
|
||||||
property bool renderActive: false
|
property bool renderActive: false
|
||||||
|
property var transientSurfaceTracker: null
|
||||||
readonly property alias contextWindow: menuWindow
|
readonly property alias contextWindow: menuWindow
|
||||||
readonly property bool blurActive: renderActive && openState && BlurService.enabled && Theme.connectedSurfaceBlurEnabled
|
readonly property bool blurActive: renderActive && openState && BlurService.enabled && Theme.connectedSurfaceBlurEnabled
|
||||||
|
|
||||||
@@ -49,6 +50,18 @@ Item {
|
|||||||
signal hideRequested
|
signal hideRequested
|
||||||
signal editAppRequested(var app)
|
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 {
|
TextMetrics {
|
||||||
id: menuTextMetrics
|
id: menuTextMetrics
|
||||||
text: root.longestMenuText
|
text: root.longestMenuText
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ Item {
|
|||||||
property var _visualRows: []
|
property var _visualRows: []
|
||||||
property var _flatIndexToRowMap: ({})
|
property var _flatIndexToRowMap: ({})
|
||||||
property var _cumulativeHeights: []
|
property var _cumulativeHeights: []
|
||||||
|
property var transientSurfaceTracker: null
|
||||||
readonly property bool _bottomSectionHeaderActive: leadingSectionHeaderAtBottom && (controller?.sections?.length ?? 0) > 0
|
readonly property bool _bottomSectionHeaderActive: leadingSectionHeaderAtBottom && (controller?.sections?.length ?? 0) > 0
|
||||||
|
|
||||||
signal itemRightClicked(int index, var item, real mouseX, real mouseY)
|
signal itemRightClicked(int index, var item, real mouseX, real mouseY)
|
||||||
@@ -259,6 +260,7 @@ Item {
|
|||||||
return root.controller?.canChangeSectionViewMode(delegateRoot.modelData?.sectionId ?? "") ?? false;
|
return root.controller?.canChangeSectionViewMode(delegateRoot.modelData?.sectionId ?? "") ?? false;
|
||||||
}
|
}
|
||||||
canCollapse: root.controller?.canCollapseSection(delegateRoot.modelData?.sectionId ?? "") ?? false
|
canCollapse: root.controller?.canCollapseSection(delegateRoot.modelData?.sectionId ?? "") ?? false
|
||||||
|
transientSurfaceTracker: root.transientSurfaceTracker
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultItem {
|
ResultItem {
|
||||||
@@ -447,6 +449,7 @@ Item {
|
|||||||
return root.controller?.canCollapseSection(stickyHeader.stickyHeaderSection?.id) ?? false;
|
return root.controller?.canCollapseSection(stickyHeader.stickyHeaderSection?.id) ?? false;
|
||||||
}
|
}
|
||||||
isSticky: true
|
isSticky: true
|
||||||
|
transientSurfaceTracker: root.transientSurfaceTracker
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -472,6 +475,7 @@ Item {
|
|||||||
canCollapse: root.controller?.canCollapseSection(section?.id ?? "") ?? false
|
canCollapse: root.controller?.canCollapseSection(section?.id ?? "") ?? false
|
||||||
isSticky: true
|
isSticky: true
|
||||||
popupAbove: true
|
popupAbove: true
|
||||||
|
transientSurfaceTracker: root.transientSurfaceTracker
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
|
|||||||
@@ -17,9 +17,21 @@ Rectangle {
|
|||||||
property bool isSticky: false
|
property bool isSticky: false
|
||||||
property bool popupAbove: false
|
property bool popupAbove: false
|
||||||
property Item popupAboveItem: null
|
property Item popupAboveItem: null
|
||||||
|
property var transientSurfaceTracker: null
|
||||||
|
|
||||||
signal viewModeToggled
|
signal viewModeToggled
|
||||||
|
|
||||||
|
Component.onDestruction: transientSurfaceTracker?.unregister(root)
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: root.transientSurfaceTracker
|
||||||
|
ignoreUnknownSignals: true
|
||||||
|
|
||||||
|
function onCloseRequested() {
|
||||||
|
categoryPopup.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
width: parent?.width ?? 200
|
width: parent?.width ?? 200
|
||||||
height: 32
|
height: 32
|
||||||
color: isSticky ? Theme.withAlpha(Theme.surfaceHover, 0) : (hoverArea.containsMouse ? Theme.surfaceHover : Theme.withAlpha(Theme.surfaceHover, 0))
|
color: isSticky ? Theme.withAlpha(Theme.surfaceHover, 0) : (hoverArea.containsMouse ? Theme.surfaceHover : Theme.withAlpha(Theme.surfaceHover, 0))
|
||||||
@@ -142,6 +154,8 @@ Rectangle {
|
|||||||
dim: false
|
dim: false
|
||||||
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
|
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
|
||||||
|
|
||||||
|
onVisibleChanged: root.transientSurfaceTracker?.setActive(root, visible, null)
|
||||||
|
|
||||||
background: Rectangle {
|
background: Rectangle {
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ FocusScope {
|
|||||||
property alias searchField: searchInput
|
property alias searchField: searchInput
|
||||||
property alias controller: searchController
|
property alias controller: searchController
|
||||||
readonly property alias activeContextMenu: contextMenu
|
readonly property alias activeContextMenu: contextMenu
|
||||||
|
property var transientSurfaceTracker: null
|
||||||
|
|
||||||
readonly property bool _hasQuery: searchInput.text.length > 0
|
readonly property bool _hasQuery: searchInput.text.length > 0
|
||||||
readonly property real _searchBarH: 56
|
readonly property real _searchBarH: 56
|
||||||
@@ -48,7 +49,7 @@ FocusScope {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function closeTransientUi() {
|
function closeTransientUi() {
|
||||||
contextMenu.hide();
|
transientSurfaceTracker?.closeAll?.();
|
||||||
root.enabled = true;
|
root.enabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -220,6 +221,7 @@ FocusScope {
|
|||||||
searchField: searchInput
|
searchField: searchInput
|
||||||
parentHandler: root
|
parentHandler: root
|
||||||
allowEditActions: false
|
allowEditActions: false
|
||||||
|
transientSurfaceTracker: root.transientSurfaceTracker
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
|
|||||||
@@ -210,12 +210,14 @@ DankModal {
|
|||||||
NotificationHeader {
|
NotificationHeader {
|
||||||
id: notificationHeader
|
id: notificationHeader
|
||||||
keyboardController: modalKeyboardController
|
keyboardController: modalKeyboardController
|
||||||
|
transientSurfaceTracker: notificationModal.transientSurfaceTracker
|
||||||
onCurrentTabChanged: notificationModal.currentTab = currentTab
|
onCurrentTabChanged: notificationModal.currentTab = currentTab
|
||||||
Component.onCompleted: notificationModal.notificationHeaderRef = notificationHeader
|
Component.onCompleted: notificationModal.notificationHeaderRef = notificationHeader
|
||||||
}
|
}
|
||||||
|
|
||||||
NotificationSettings {
|
NotificationSettings {
|
||||||
id: notificationSettings
|
id: notificationSettings
|
||||||
|
transientSurfaceTracker: notificationModal.transientSurfaceTracker
|
||||||
expanded: notificationHeader.showSettings
|
expanded: notificationHeader.showSettings
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,6 +227,7 @@ DankModal {
|
|||||||
height: parent.height - y
|
height: parent.height - y
|
||||||
visible: notificationHeader.currentTab === 0
|
visible: notificationHeader.currentTab === 0
|
||||||
keyboardController: modalKeyboardController
|
keyboardController: modalKeyboardController
|
||||||
|
transientSurfaceTracker: notificationModal.transientSurfaceTracker
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
notificationModal.notificationListRef = notificationList;
|
notificationModal.notificationListRef = notificationList;
|
||||||
if (modalKeyboardController) {
|
if (modalKeyboardController) {
|
||||||
|
|||||||
@@ -122,6 +122,7 @@ DankPopout {
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
parentModal: modalAdapter
|
parentModal: modalAdapter
|
||||||
viewModeContext: "appDrawer"
|
viewModeContext: "appDrawer"
|
||||||
|
transientSurfaceTracker: appDrawerPopout.transientSurfaceTracker
|
||||||
}
|
}
|
||||||
|
|
||||||
Keys.onEscapePressed: event => {
|
Keys.onEscapePressed: event => {
|
||||||
|
|||||||
@@ -608,7 +608,7 @@ Item {
|
|||||||
function closeHoverSurfaces() {
|
function closeHoverSurfaces() {
|
||||||
_closeHoverNotepad();
|
_closeHoverNotepad();
|
||||||
activeHoverTrigger = "";
|
activeHoverTrigger = "";
|
||||||
PopoutManager.closePopoutForScreen(barWindow?.screen);
|
PopoutManager.dismissHoverPopoutForScreen(barWindow?.screen);
|
||||||
TrayMenuManager.closeAllMenus();
|
TrayMenuManager.closeAllMenus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ DankListView {
|
|||||||
property int swipingCardIndex: -1
|
property int swipingCardIndex: -1
|
||||||
property real swipingCardOffset: 0
|
property real swipingCardOffset: 0
|
||||||
property bool _stableHeightUpdatePending: false
|
property bool _stableHeightUpdatePending: false
|
||||||
|
property var transientSurfaceTracker: null
|
||||||
readonly property real shadowBlurPx: Theme.elevationEnabled ? ((Theme.elevationLevel1 && Theme.elevationLevel1.blurPx !== undefined) ? Theme.elevationLevel1.blurPx : 4) : 0
|
readonly property real shadowBlurPx: Theme.elevationEnabled ? ((Theme.elevationLevel1 && Theme.elevationLevel1.blurPx !== undefined) ? Theme.elevationLevel1.blurPx : 4) : 0
|
||||||
readonly property real shadowHorizontalGutter: Theme.snap(Math.max(Theme.spacingS, Math.min(32, shadowBlurPx * 1.5 + 6)), 1)
|
readonly property real shadowHorizontalGutter: Theme.snap(Math.max(Theme.spacingS, Math.min(32, shadowBlurPx * 1.5 + 6)), 1)
|
||||||
readonly property real shadowVerticalGutter: Theme.snap(Math.max(Theme.spacingXS, 6), 1)
|
readonly property real shadowVerticalGutter: Theme.snap(Math.max(Theme.spacingXS, 6), 1)
|
||||||
@@ -173,6 +174,7 @@ DankListView {
|
|||||||
notificationGroup: modelData
|
notificationGroup: modelData
|
||||||
keyboardNavigationActive: listView.keyboardActive
|
keyboardNavigationActive: listView.keyboardActive
|
||||||
animateExpansion: listView.cardAnimateExpansion && listView.listInitialized
|
animateExpansion: listView.cardAnimateExpansion && listView.listInitialized
|
||||||
|
transientSurfaceTracker: listView.transientSurfaceTracker
|
||||||
opacity: {
|
opacity: {
|
||||||
const swipeAmount = Math.abs(delegateRoot.swipeOffset);
|
const swipeAmount = Math.abs(delegateRoot.swipeOffset);
|
||||||
if (swipeAmount <= delegateRoot.swipeFadeStartOffset)
|
if (swipeAmount <= delegateRoot.swipeFadeStartOffset)
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ Rectangle {
|
|||||||
property real swipingNotificationOffset: 0
|
property real swipingNotificationOffset: 0
|
||||||
property real listLevelAdjacentScaleInfluence: 1.0
|
property real listLevelAdjacentScaleInfluence: 1.0
|
||||||
property bool listLevelScaleAnimationsEnabled: true
|
property bool listLevelScaleAnimationsEnabled: true
|
||||||
|
property var transientSurfaceTracker: null
|
||||||
|
|
||||||
readonly property bool compactMode: SettingsData.notificationCompactMode
|
readonly property bool compactMode: SettingsData.notificationCompactMode
|
||||||
readonly property real cardPadding: compactMode ? Theme.notificationCardPaddingCompact : Theme.notificationCardPadding
|
readonly property real cardPadding: compactMode ? Theme.notificationCardPaddingCompact : Theme.notificationCardPadding
|
||||||
@@ -63,6 +64,20 @@ Rectangle {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Component.onDestruction: {
|
||||||
|
transientSurfaceTracker?.unregister(root);
|
||||||
|
notificationCardContextMenu.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: root.transientSurfaceTracker
|
||||||
|
ignoreUnknownSignals: true
|
||||||
|
|
||||||
|
function onCloseRequested() {
|
||||||
|
notificationCardContextMenu.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function expansionMotionDuration() {
|
function expansionMotionDuration() {
|
||||||
if (isDescriptionToggleAnimation)
|
if (isDescriptionToggleAnimation)
|
||||||
return descriptionExpanded ? Theme.notificationInlineExpandDuration : Theme.notificationInlineCollapseDuration;
|
return descriptionExpanded ? Theme.notificationInlineExpandDuration : Theme.notificationInlineCollapseDuration;
|
||||||
@@ -1059,6 +1074,8 @@ Rectangle {
|
|||||||
width: 220
|
width: 220
|
||||||
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
|
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
|
||||||
|
|
||||||
|
onVisibleChanged: root.transientSurfaceTracker?.setActive(root, visible, null)
|
||||||
|
|
||||||
background: Rectangle {
|
background: Rectangle {
|
||||||
color: BlurService.enabled ? Theme.surfaceContainer : Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
|
color: BlurService.enabled ? Theme.surfaceContainer : Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
|
|||||||
@@ -283,11 +283,13 @@ DankPopout {
|
|||||||
NotificationHeader {
|
NotificationHeader {
|
||||||
id: notificationHeader
|
id: notificationHeader
|
||||||
objectName: "notificationHeader"
|
objectName: "notificationHeader"
|
||||||
|
transientSurfaceTracker: root.transientSurfaceTracker
|
||||||
onHeightChanged: notificationContent.cachedHeaderHeight = height
|
onHeightChanged: notificationContent.cachedHeaderHeight = height
|
||||||
}
|
}
|
||||||
|
|
||||||
NotificationSettings {
|
NotificationSettings {
|
||||||
id: notificationSettings
|
id: notificationSettings
|
||||||
|
transientSurfaceTracker: root.transientSurfaceTracker
|
||||||
expanded: notificationHeader.showSettings
|
expanded: notificationHeader.showSettings
|
||||||
maxAllowedHeight: notificationContent.settingsMaxHeight
|
maxAllowedHeight: notificationContent.settingsMaxHeight
|
||||||
}
|
}
|
||||||
@@ -306,6 +308,7 @@ DankPopout {
|
|||||||
anchors.topMargin: -(shadowVerticalGutter + delegateShadowGutter / 2)
|
anchors.topMargin: -(shadowVerticalGutter + delegateShadowGutter / 2)
|
||||||
anchors.bottomMargin: -(shadowVerticalGutter + delegateShadowGutter / 2)
|
anchors.bottomMargin: -(shadowVerticalGutter + delegateShadowGutter / 2)
|
||||||
cardAnimateExpansion: true
|
cardAnimateExpansion: true
|
||||||
|
transientSurfaceTracker: root.transientSurfaceTracker
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,19 @@ Item {
|
|||||||
property bool showSettings: false
|
property bool showSettings: false
|
||||||
property int currentTab: 0
|
property int currentTab: 0
|
||||||
property bool showDndMenu: false
|
property bool showDndMenu: false
|
||||||
|
property var transientSurfaceTracker: null
|
||||||
|
|
||||||
|
onShowDndMenuChanged: transientSurfaceTracker?.setActive(root, showDndMenu, null)
|
||||||
|
Component.onDestruction: transientSurfaceTracker?.unregister(root)
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: root.transientSurfaceTracker
|
||||||
|
ignoreUnknownSignals: true
|
||||||
|
|
||||||
|
function onCloseRequested() {
|
||||||
|
root.showDndMenu = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onCurrentTabChanged: {
|
onCurrentTabChanged: {
|
||||||
if (currentTab === 1 && !SettingsData.notificationHistoryEnabled)
|
if (currentTab === 1 && !SettingsData.notificationHistoryEnabled)
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ Rectangle {
|
|||||||
|
|
||||||
property bool expanded: false
|
property bool expanded: false
|
||||||
property real maxAllowedHeight: 0
|
property real maxAllowedHeight: 0
|
||||||
|
property var transientSurfaceTracker: null
|
||||||
readonly property real naturalContentHeight: contentColumn.height + Theme.spacingL * 2
|
readonly property real naturalContentHeight: contentColumn.height + Theme.spacingL * 2
|
||||||
|
|
||||||
width: parent.width
|
width: parent.width
|
||||||
@@ -178,6 +179,8 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DankDropdown {
|
DankDropdown {
|
||||||
|
id: lowTimeoutDropdown
|
||||||
|
transientSurfaceTracker: root.transientSurfaceTracker
|
||||||
text: I18n.tr("Low Priority")
|
text: I18n.tr("Low Priority")
|
||||||
description: I18n.tr("Timeout for low priority notifications")
|
description: I18n.tr("Timeout for low priority notifications")
|
||||||
currentValue: getTimeoutText(SettingsData.notificationTimeoutLow)
|
currentValue: getTimeoutText(SettingsData.notificationTimeoutLow)
|
||||||
@@ -193,6 +196,8 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DankDropdown {
|
DankDropdown {
|
||||||
|
id: normalTimeoutDropdown
|
||||||
|
transientSurfaceTracker: root.transientSurfaceTracker
|
||||||
text: I18n.tr("Normal Priority")
|
text: I18n.tr("Normal Priority")
|
||||||
description: I18n.tr("Timeout for normal priority notifications")
|
description: I18n.tr("Timeout for normal priority notifications")
|
||||||
currentValue: getTimeoutText(SettingsData.notificationTimeoutNormal)
|
currentValue: getTimeoutText(SettingsData.notificationTimeoutNormal)
|
||||||
@@ -208,6 +213,8 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DankDropdown {
|
DankDropdown {
|
||||||
|
id: criticalTimeoutDropdown
|
||||||
|
transientSurfaceTracker: root.transientSurfaceTracker
|
||||||
text: I18n.tr("Critical Priority")
|
text: I18n.tr("Critical Priority")
|
||||||
description: I18n.tr("Timeout for critical priority notifications")
|
description: I18n.tr("Timeout for critical priority notifications")
|
||||||
currentValue: getTimeoutText(SettingsData.notificationTimeoutCritical)
|
currentValue: getTimeoutText(SettingsData.notificationTimeoutCritical)
|
||||||
|
|||||||
@@ -11,12 +11,25 @@ PanelWindow {
|
|||||||
property string appName: ""
|
property string appName: ""
|
||||||
property string desktopEntry: ""
|
property string desktopEntry: ""
|
||||||
property point anchorPos: Qt.point(0, 0)
|
property point anchorPos: Qt.point(0, 0)
|
||||||
|
property var transientSurfaceTracker: null
|
||||||
|
|
||||||
signal muted
|
signal muted
|
||||||
signal dismissRequested
|
signal dismissRequested
|
||||||
|
|
||||||
readonly property bool isMuted: SettingsData.isAppMuted(appName, desktopEntry)
|
readonly property bool isMuted: SettingsData.isAppMuted(appName, desktopEntry)
|
||||||
|
|
||||||
|
onVisibleChanged: transientSurfaceTracker?.setActive(root, visible, root)
|
||||||
|
Component.onDestruction: transientSurfaceTracker?.unregister(root)
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: root.transientSurfaceTracker
|
||||||
|
ignoreUnknownSignals: true
|
||||||
|
|
||||||
|
function onCloseRequested() {
|
||||||
|
root.closeMenu();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function showAt(x, y, targetScreen) {
|
function showAt(x, y, targetScreen) {
|
||||||
if (targetScreen)
|
if (targetScreen)
|
||||||
screen = targetScreen;
|
screen = targetScreen;
|
||||||
|
|||||||
@@ -70,6 +70,11 @@ PanelWindow {
|
|||||||
property real _storedTopMargin: 0
|
property real _storedTopMargin: 0
|
||||||
property real _storedBottomMargin: 0
|
property real _storedBottomMargin: 0
|
||||||
property bool _inlineGeometryReady: false
|
property bool _inlineGeometryReady: false
|
||||||
|
readonly property bool contextMenuActive: transientSurfaces.active
|
||||||
|
|
||||||
|
TransientSurfaceTracker {
|
||||||
|
id: transientSurfaces
|
||||||
|
}
|
||||||
readonly property bool directionalEffect: Theme.isDirectionalEffect
|
readonly property bool directionalEffect: Theme.isDirectionalEffect
|
||||||
readonly property bool depthEffect: Theme.isDepthEffect
|
readonly property bool depthEffect: Theme.isDepthEffect
|
||||||
readonly property real entryTravel: {
|
readonly property real entryTravel: {
|
||||||
@@ -122,6 +127,7 @@ PanelWindow {
|
|||||||
if (exiting || _isDestroying) {
|
if (exiting || _isDestroying) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
closeTransientUi();
|
||||||
exiting = true;
|
exiting = true;
|
||||||
exitStarted();
|
exitStarted();
|
||||||
popupChromeGeometryChanged();
|
popupChromeGeometryChanged();
|
||||||
@@ -135,6 +141,7 @@ PanelWindow {
|
|||||||
if (_isDestroying) {
|
if (_isDestroying) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
closeTransientUi();
|
||||||
_isDestroying = true;
|
_isDestroying = true;
|
||||||
exiting = true;
|
exiting = true;
|
||||||
visible = false;
|
visible = false;
|
||||||
@@ -147,6 +154,7 @@ PanelWindow {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
closeTransientUi();
|
||||||
_finalized = true;
|
_finalized = true;
|
||||||
_isDestroying = true;
|
_isDestroying = true;
|
||||||
exitWatchdog.stop();
|
exitWatchdog.stop();
|
||||||
@@ -155,6 +163,11 @@ PanelWindow {
|
|||||||
win.exitFinished();
|
win.exitFinished();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function closeTransientUi() {
|
||||||
|
transientSurfaces.closeAll();
|
||||||
|
popupContextMenuLoader.active = false;
|
||||||
|
}
|
||||||
|
|
||||||
visible: !_finalized
|
visible: !_finalized
|
||||||
WlrLayershell.layer: {
|
WlrLayershell.layer: {
|
||||||
const shouldUseOverlay = notificationData && (SettingsData.notificationOverlayEnabled || notificationData.urgency === NotificationUrgency.Critical);
|
const shouldUseOverlay = notificationData && (SettingsData.notificationOverlayEnabled || notificationData.urgency === NotificationUrgency.Critical);
|
||||||
@@ -274,6 +287,7 @@ PanelWindow {
|
|||||||
}
|
}
|
||||||
onNotificationDataChanged: {
|
onNotificationDataChanged: {
|
||||||
if (!_isDestroying) {
|
if (!_isDestroying) {
|
||||||
|
closeTransientUi();
|
||||||
if (SettingsData.notificationPopupPrivacyMode)
|
if (SettingsData.notificationPopupPrivacyMode)
|
||||||
descriptionExpanded = false;
|
descriptionExpanded = false;
|
||||||
wrapperConn.target = win.notificationData || null;
|
wrapperConn.target = win.notificationData || null;
|
||||||
@@ -286,6 +300,7 @@ PanelWindow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Component.onDestruction: {
|
Component.onDestruction: {
|
||||||
|
closeTransientUi();
|
||||||
_isDestroying = true;
|
_isDestroying = true;
|
||||||
exitWatchdog.stop();
|
exitWatchdog.stop();
|
||||||
if (notificationData && notificationData.timer) {
|
if (notificationData && notificationData.timer) {
|
||||||
@@ -716,7 +731,7 @@ PanelWindow {
|
|||||||
if (cardHoverHandler.hovered) {
|
if (cardHoverHandler.hovered) {
|
||||||
if (notificationData.timer)
|
if (notificationData.timer)
|
||||||
notificationData.timer.stop();
|
notificationData.timer.stop();
|
||||||
} else if (notificationData.popup && notificationData.timer) {
|
} else if (!win.contextMenuActive && notificationData.popup && notificationData.timer) {
|
||||||
notificationData.timer.restart();
|
notificationData.timer.restart();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1357,11 +1372,26 @@ PanelWindow {
|
|||||||
interval: 160
|
interval: 160
|
||||||
repeat: false
|
repeat: false
|
||||||
onTriggered: {
|
onTriggered: {
|
||||||
if (notificationData && notificationData.timer && !exiting && !_isDestroying)
|
if (notificationData && notificationData.timer && !contextMenuActive && !exiting && !_isDestroying)
|
||||||
notificationData.timer.start();
|
notificationData.timer.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: popupContextMenuLoader.item
|
||||||
|
ignoreUnknownSignals: true
|
||||||
|
|
||||||
|
function onVisibleChanged() {
|
||||||
|
if (!notificationData?.timer || exiting || _isDestroying)
|
||||||
|
return;
|
||||||
|
if (win.contextMenuActive) {
|
||||||
|
notificationData.timer.stop();
|
||||||
|
} else if (!cardHoverHandler.hovered && notificationData.popup) {
|
||||||
|
notificationData.timer.restart();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Timer {
|
Timer {
|
||||||
id: exitWatchdog
|
id: exitWatchdog
|
||||||
|
|
||||||
@@ -1387,6 +1417,7 @@ PanelWindow {
|
|||||||
active: false
|
active: false
|
||||||
|
|
||||||
sourceComponent: NotificationContextMenu {
|
sourceComponent: NotificationContextMenu {
|
||||||
|
transientSurfaceTracker: transientSurfaces
|
||||||
appName: notificationData?.appName ?? ""
|
appName: notificationData?.appName ?? ""
|
||||||
desktopEntry: notificationData?.desktopEntry ?? ""
|
desktopEntry: notificationData?.desktopEntry ?? ""
|
||||||
onMuted: {
|
onMuted: {
|
||||||
|
|||||||
@@ -12,10 +12,23 @@ Popup {
|
|||||||
property int selectedIndex: -1
|
property int selectedIndex: -1
|
||||||
property bool keyboardNavigation: false
|
property bool keyboardNavigation: false
|
||||||
property var parentFocusItem: null
|
property var parentFocusItem: null
|
||||||
|
property var transientSurfaceTracker: null
|
||||||
|
|
||||||
signal menuClosed
|
signal menuClosed
|
||||||
signal processKilled
|
signal processKilled
|
||||||
|
|
||||||
|
onVisibleChanged: transientSurfaceTracker?.setActive(root, visible, null)
|
||||||
|
Component.onDestruction: transientSurfaceTracker?.unregister(root)
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: processContextMenu.transientSurfaceTracker
|
||||||
|
ignoreUnknownSignals: true
|
||||||
|
|
||||||
|
function onCloseRequested() {
|
||||||
|
processContextMenu.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
readonly property var menuItems: [
|
readonly property var menuItems: [
|
||||||
{
|
{
|
||||||
text: I18n.tr("Copy PID"),
|
text: I18n.tr("Copy PID"),
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ DankPopout {
|
|||||||
|
|
||||||
ProcessContextMenu {
|
ProcessContextMenu {
|
||||||
id: processContextMenu
|
id: processContextMenu
|
||||||
|
transientSurfaceTracker: processListPopout.transientSurfaceTracker
|
||||||
}
|
}
|
||||||
|
|
||||||
content: Component {
|
content: Component {
|
||||||
|
|||||||
@@ -54,11 +54,14 @@ Item {
|
|||||||
property bool addHorizontalPadding: false
|
property bool addHorizontalPadding: false
|
||||||
property string emptyText: ""
|
property string emptyText: ""
|
||||||
property bool usePopupTransparency: !checkParentDisablesTransparency()
|
property bool usePopupTransparency: !checkParentDisablesTransparency()
|
||||||
|
property var transientSurfaceTracker: null
|
||||||
|
|
||||||
signal valueChanged(string value)
|
signal valueChanged(string value)
|
||||||
|
|
||||||
property bool menuOpen: false
|
property bool menuOpen: false
|
||||||
|
|
||||||
|
onMenuOpenChanged: transientSurfaceTracker?.setActive(root, menuOpen, null)
|
||||||
|
|
||||||
function closeDropdownMenu() {
|
function closeDropdownMenu() {
|
||||||
if (!root.menuOpen && !dropdownMenu.opened && !dropdownMenu.visible)
|
if (!root.menuOpen && !dropdownMenu.opened && !dropdownMenu.visible)
|
||||||
return;
|
return;
|
||||||
@@ -113,10 +116,20 @@ Item {
|
|||||||
implicitHeight: !showTrigger ? 0 : (compactMode ? 40 : Math.max(60, labelColumn.implicitHeight + Theme.spacingM))
|
implicitHeight: !showTrigger ? 0 : (compactMode ? 40 : Math.max(60, labelColumn.implicitHeight + Theme.spacingM))
|
||||||
|
|
||||||
Component.onDestruction: {
|
Component.onDestruction: {
|
||||||
|
transientSurfaceTracker?.unregister(root);
|
||||||
if (root.menuOpen || dropdownMenu.opened || dropdownMenu.visible)
|
if (root.menuOpen || dropdownMenu.opened || dropdownMenu.visible)
|
||||||
dropdownMenu.close();
|
dropdownMenu.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: root.transientSurfaceTracker
|
||||||
|
ignoreUnknownSignals: true
|
||||||
|
|
||||||
|
function onCloseRequested() {
|
||||||
|
root.closeDropdownMenu();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
id: labelColumn
|
id: labelColumn
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ Item {
|
|||||||
property bool hoverDismissEnabled: false
|
property bool hoverDismissEnabled: false
|
||||||
property bool hoverDismissSuspended: false
|
property bool hoverDismissSuspended: false
|
||||||
property var customKeyboardFocus: null
|
property var customKeyboardFocus: null
|
||||||
|
readonly property alias transientSurfaceTracker: _transientSurfaceTracker
|
||||||
|
readonly property bool effectiveHoverDismissSuspended: hoverDismissSuspended || (transientSurfaceTracker?.active ?? false)
|
||||||
property bool backgroundInteractive: true
|
property bool backgroundInteractive: true
|
||||||
property bool contentHandlesKeys: false
|
property bool contentHandlesKeys: false
|
||||||
property bool fullHeightSurface: false
|
property bool fullHeightSurface: false
|
||||||
@@ -55,6 +57,10 @@ Item {
|
|||||||
readonly property var backgroundWindow: impl.item ? impl.item.backgroundWindow : null
|
readonly property var backgroundWindow: impl.item ? impl.item.backgroundWindow : null
|
||||||
readonly property var contentWindow: impl.item ? impl.item.contentWindow : 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.
|
// Hyprland OnDemand grab: whitelist popout surfaces and bars so dismiss clicks still land.
|
||||||
HyprlandFocusGrab {
|
HyprlandFocusGrab {
|
||||||
windows: {
|
windows: {
|
||||||
@@ -63,7 +69,8 @@ Item {
|
|||||||
list.push(root.contentWindow);
|
list.push(root.contentWindow);
|
||||||
if (root.backgroundWindow && root.backgroundWindow !== root.contentWindow)
|
if (root.backgroundWindow && root.backgroundWindow !== root.contentWindow)
|
||||||
list.push(root.backgroundWindow);
|
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)
|
active: KeyboardFocus.wantsGrab(root.shouldBeVisible, root.customKeyboardFocus)
|
||||||
|
|
||||||
@@ -170,6 +177,7 @@ Item {
|
|||||||
function close() {
|
function close() {
|
||||||
_pendingOpen = false;
|
_pendingOpen = false;
|
||||||
_pendingOpenTimer.stop();
|
_pendingOpenTimer.stop();
|
||||||
|
transientSurfaceTracker?.closeAll?.();
|
||||||
if (impl.item)
|
if (impl.item)
|
||||||
impl.item.close();
|
impl.item.close();
|
||||||
}
|
}
|
||||||
@@ -186,8 +194,9 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function closeFromHoverDismiss() {
|
function closeFromHoverDismiss() {
|
||||||
if (hoverDismissSuspended)
|
if (effectiveHoverDismissSuspended)
|
||||||
return;
|
return;
|
||||||
|
transientSurfaceTracker?.closeAll?.();
|
||||||
hoverDismissEnabled = false;
|
hoverDismissEnabled = false;
|
||||||
// Enable animations using standard Theme-bound popout motion to preserve bindings.
|
// Enable animations using standard Theme-bound popout motion to preserve bindings.
|
||||||
if (impl.item)
|
if (impl.item)
|
||||||
@@ -308,7 +317,7 @@ Item {
|
|||||||
it.effectiveBarPosition = Qt.binding(() => root.effectiveBarPosition);
|
it.effectiveBarPosition = Qt.binding(() => root.effectiveBarPosition);
|
||||||
it.effectiveBarBottomGap = Qt.binding(() => root.effectiveBarBottomGap);
|
it.effectiveBarBottomGap = Qt.binding(() => root.effectiveBarBottomGap);
|
||||||
it.hoverDismissEnabled = Qt.binding(() => root.hoverDismissEnabled);
|
it.hoverDismissEnabled = Qt.binding(() => root.hoverDismissEnabled);
|
||||||
it.hoverDismissSuspended = Qt.binding(() => root.hoverDismissSuspended);
|
it.hoverDismissSuspended = Qt.binding(() => root.effectiveHoverDismissSuspended);
|
||||||
|
|
||||||
it.shouldBeVisible = root.shouldBeVisible;
|
it.shouldBeVisible = root.shouldBeVisible;
|
||||||
if (root._primeContent && typeof it.primeContent === "function")
|
if (root._primeContent && typeof it.primeContent === "function")
|
||||||
@@ -332,6 +341,8 @@ Item {
|
|||||||
Connections {
|
Connections {
|
||||||
target: root
|
target: root
|
||||||
function onShouldBeVisibleChanged() {
|
function onShouldBeVisibleChanged() {
|
||||||
|
if (!root.shouldBeVisible)
|
||||||
|
root.transientSurfaceTracker?.closeAll?.();
|
||||||
if (impl.item && impl.item.shouldBeVisible !== root.shouldBeVisible)
|
if (impl.item && impl.item.shouldBeVisible !== root.shouldBeVisible)
|
||||||
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