mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-10-31 15:37:47 -04:00
popout: keep hover popouts open after a transient menu closes
fixes #3492
This commit is contained in:
1 parent
8508121f4a
commit
7975136c10
20 files changed
+86
-21
No files matched your search
@@ -78,7 +78,7 @@ Item {
|
||||
width: CcMetrics.configMenuWidth
|
||||
height: menu.implicitHeight + Theme.spacingS * 2
|
||||
radius: Theme.windowRadius
|
||||
color: Theme.nestedSurface
|
||||
color: Theme.readableSurface
|
||||
border.width: Theme.layerOutlineWidth
|
||||
border.color: Theme.outlineMedium
|
||||
x: Math.max(Theme.spacingS, Math.min(root.anchorX + root.anchorWidth - width, root.width - width - Theme.spacingS))
|
||||
|
||||
@@ -133,7 +133,7 @@ Item {
|
||||
width: CcMetrics.menuMinWidth
|
||||
height: root.visibleItems.length * Theme.menuItemHeight + Theme.spacingS * 2
|
||||
radius: Theme.windowRadius
|
||||
color: Theme.nestedSurface
|
||||
color: Theme.foregroundColor(Theme.chipSurface, Theme.isFloatingWindow(root))
|
||||
border.width: Theme.layerOutlineWidth
|
||||
border.color: Theme.outlineMedium
|
||||
opacity: root._open ? 1 : 0
|
||||
|
||||
@@ -49,7 +49,7 @@ Item {
|
||||
topRightRadius: root.cornerRadii.y
|
||||
bottomRightRadius: root.cornerRadii.z
|
||||
bottomLeftRadius: root.cornerRadii.w
|
||||
color: Qt.rgba(0, 0, 0, Theme.scrimAlpha)
|
||||
color: Theme.withAlpha(Theme.scrimColor, Theme.scrimAlpha)
|
||||
opacity: root.shown ? 1 : 0
|
||||
|
||||
Behavior on opacity {
|
||||
@@ -81,7 +81,7 @@ Item {
|
||||
width: Math.min(root.panelWidth, root.width - Theme.spacingL * 2)
|
||||
height: column.implicitHeight + Theme.spacingL * 2
|
||||
radius: Theme.windowRadius
|
||||
color: Theme.nestedSurface
|
||||
color: Theme.readableSurface
|
||||
border.width: Theme.layerOutlineWidth
|
||||
border.color: Theme.outlineMedium
|
||||
opacity: root.shown ? 1 : 0
|
||||
|
||||
@@ -26,7 +26,7 @@ Rectangle {
|
||||
implicitWidth: CcMetrics.libraryPanelWidth
|
||||
implicitHeight: CcMetrics.libraryPanelHeight
|
||||
radius: Theme.windowRadius
|
||||
color: Theme.nestedSurface
|
||||
color: Theme.readableSurface
|
||||
border.width: Theme.layerOutlineWidth
|
||||
border.color: Theme.outlineMedium
|
||||
|
||||
|
||||
@@ -77,6 +77,8 @@ FocusScope {
|
||||
target.parentPopout = root.dashHost;
|
||||
if ("dashHost" in target)
|
||||
target.dashHost = root.dashHost;
|
||||
if ("transientSurfaceTracker" in target)
|
||||
target.transientSurfaceTracker = root.dashHost.transientSurfaceTracker;
|
||||
if ("targetScreen" in target)
|
||||
target.targetScreen = Qt.binding(() => root.dashHost.screen);
|
||||
if ("preferredFocusId" in target)
|
||||
|
||||
@@ -13,6 +13,8 @@ FocusScope {
|
||||
property bool nested: false
|
||||
property string entryId: "notifications"
|
||||
property int currentTab: 0
|
||||
property var transientSurfaceTracker: null
|
||||
readonly property var surfaces: transientSurfaceTracker ?? localSurfaces
|
||||
readonly property bool hasNotifications: list.count > 0
|
||||
readonly property Item focusTarget: root
|
||||
property bool blocksTabNavigation: false
|
||||
@@ -105,7 +107,7 @@ FocusScope {
|
||||
}
|
||||
|
||||
TransientSurfaceTracker {
|
||||
id: surfaces
|
||||
id: localSurfaces
|
||||
}
|
||||
|
||||
NotificationKeyboardController {
|
||||
@@ -131,7 +133,7 @@ FocusScope {
|
||||
visible: root.currentTab === 0
|
||||
keyboardController: keyboard
|
||||
focusAllowed: root.activeFocus
|
||||
transientSurfaceTracker: surfaces
|
||||
transientSurfaceTracker: root.surfaces
|
||||
trackStableContentHeight: false
|
||||
}
|
||||
|
||||
@@ -198,7 +200,7 @@ FocusScope {
|
||||
popupAnchorItem: dndButton
|
||||
popupWidth: NotificationMetrics.menuWidth
|
||||
openUpwards: true
|
||||
transientSurfaceTracker: surfaces
|
||||
transientSurfaceTracker: root.surfaces
|
||||
options: [I18n.tr("Off")].concat(DndPresets.presetOptions.map(option => option.label))
|
||||
onValueChanged: value => {
|
||||
if (value === I18n.tr("Off")) {
|
||||
|
||||
@@ -12,6 +12,7 @@ Column {
|
||||
|
||||
property var eventData: null
|
||||
property date initialDate: new Date()
|
||||
property var transientSurfaceTracker: null
|
||||
|
||||
signal saved
|
||||
signal closeRequested
|
||||
@@ -240,6 +241,7 @@ Column {
|
||||
DankDropdown {
|
||||
width: parent.width
|
||||
text: I18n.tr("Calendar")
|
||||
transientSurfaceTracker: root.transientSurfaceTracker
|
||||
options: root._cals.map(c => c.name)
|
||||
currentValue: root._calendarName(root.fCalendarId)
|
||||
onValueChanged: value => {
|
||||
@@ -255,6 +257,7 @@ Column {
|
||||
DankDropdown {
|
||||
width: parent.width
|
||||
text: I18n.tr("Reminder", "noun, calendar event reminder time dropdown label")
|
||||
transientSurfaceTracker: root.transientSurfaceTracker
|
||||
options: root._remLabels
|
||||
currentValue: root._remLabels[Math.max(0, root._remMins.indexOf(root.fReminder))]
|
||||
onValueChanged: value => {
|
||||
|
||||
@@ -16,6 +16,7 @@ DankEditableGrid {
|
||||
property int columnCap: DashMetrics.maximumGridColumns
|
||||
property bool panelPreviewing: false
|
||||
property string preferredFocusId: "calendar"
|
||||
property var transientSurfaceTracker: null
|
||||
property string pendingFocusId: ""
|
||||
property int pendingFocusReason: Qt.OtherFocusReason
|
||||
property Item flashSlot: null
|
||||
|
||||
@@ -52,6 +52,8 @@ DankEditableGridSlot {
|
||||
return;
|
||||
if ("entryId" in item)
|
||||
item.entryId = root.cardId;
|
||||
if ("transientSurfaceTracker" in item)
|
||||
item.transientSurfaceTracker = Qt.binding(() => root.grid.transientSurfaceTracker);
|
||||
if (!root.entry?.isPlugin)
|
||||
return;
|
||||
if ("pluginId" in item)
|
||||
|
||||
@@ -5,6 +5,7 @@ import qs.Modules.DankDash
|
||||
Card {
|
||||
id: root
|
||||
property bool live: Window.window?.visible ?? false
|
||||
property var transientSurfaceTracker: null
|
||||
readonly property bool opensTab: false
|
||||
focusTarget: panel
|
||||
activeFocusOnTab: interactive
|
||||
@@ -23,5 +24,6 @@ Card {
|
||||
live: root.live
|
||||
interactive: root.interactive
|
||||
nested: true
|
||||
transientSurfaceTracker: root.transientSurfaceTracker
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@ FocusScope {
|
||||
property int rowBudget: DashMetrics.minimumTabRows
|
||||
property int columnCap: DashMetrics.maximumGridColumns
|
||||
property string preferredFocusId: "calendar"
|
||||
property var transientSurfaceTracker: null
|
||||
|
||||
signal cardFocusChanged(string id)
|
||||
readonly property Item focusTarget: grid
|
||||
@@ -88,6 +89,7 @@ FocusScope {
|
||||
columnCap: root.columnCap
|
||||
live: root.live
|
||||
preferredFocusId: root.preferredFocusId
|
||||
transientSurfaceTracker: root.transientSurfaceTracker
|
||||
onCardFocusChanged: id => root.cardFocusChanged(id)
|
||||
|
||||
onCardClicked: cardId => {
|
||||
@@ -186,6 +188,7 @@ FocusScope {
|
||||
sourceComponent: CalendarEventEditor {
|
||||
eventData: editorSheet.eventData
|
||||
initialDate: editorSheet.initialDate
|
||||
transientSurfaceTracker: root.transientSurfaceTracker
|
||||
onSaved: editorSheet.dismiss()
|
||||
onCloseRequested: editorSheet.dismiss()
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ Item {
|
||||
property int gridIndex: 0
|
||||
property Item keyForwardTarget: null
|
||||
property var parentPopout: null
|
||||
property var transientSurfaceTracker: null
|
||||
property bool enableAnimation: false
|
||||
property string selectedFileName: ""
|
||||
property var targetScreen: null
|
||||
@@ -813,6 +814,7 @@ Item {
|
||||
showTrigger: false
|
||||
popupAnchorItem: sortButton
|
||||
focusReturnTarget: sortButton
|
||||
transientSurfaceTracker: root.transientSurfaceTracker
|
||||
openUpwards: true
|
||||
alignPopupRight: !I18n.isRtl
|
||||
popupWidth: Math.min(root.width, Theme.smallBreakpoint / 2)
|
||||
|
||||
@@ -14,6 +14,7 @@ DashTabFace {
|
||||
live: root.live
|
||||
editMode: root.editMode
|
||||
rowBudget: root.controller.dashboardRowBudget
|
||||
transientSurfaceTracker: root.controller.transientSurfaces
|
||||
onTabRequested: id => {
|
||||
switch (id) {
|
||||
case "media":
|
||||
|
||||
@@ -11,6 +11,7 @@ DashTabFace {
|
||||
tabComponent: Component {
|
||||
NotificationsTab {
|
||||
live: root.live
|
||||
transientSurfaceTracker: root.controller.transientSurfaces
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ DashTabFace {
|
||||
pagerCachePages: 0
|
||||
targetScreen: root.effectiveScreen
|
||||
parentPopout: hostContract
|
||||
transientSurfaceTracker: root.controller.transientSurfaces
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -97,7 +97,7 @@ Item {
|
||||
property bool keyboardFocusArmed: true
|
||||
readonly property var keyboardFocusPolicy: KeyboardFocus.keyboardFocus(controller.keyboardDismissRequested && root.keyboardFocusArmed && !controller.keyboardYielded, null)
|
||||
readonly property bool wantsFocusGrab: KeyboardFocus.wantsGrab(controller.keyboardDismissRequested && !controller.keyboardYielded, null)
|
||||
readonly property var transientFocusWindows: launcherTransientSurfaces.focusWindows
|
||||
readonly property var transientFocusWindows: islandTransientSurfaces.focusWindows
|
||||
readonly property string registryKey: IslandHostRegistry.key(root.screen?.name, root.barId)
|
||||
property string registeredKey: ""
|
||||
|
||||
@@ -189,11 +189,12 @@ Item {
|
||||
onKeyboardDismissRequestedChanged: root.requestKeyboardFocus()
|
||||
onLauncherSessionActiveChanged: {
|
||||
if (!launcherSessionActive)
|
||||
launcherTransientSurfaces.closeAll();
|
||||
islandTransientSurfaces.closeAll();
|
||||
}
|
||||
|
||||
barConfig: root.barConfig
|
||||
edge: root.edge
|
||||
transientSurfaces: islandTransientSurfaces
|
||||
freeMode: root.freeMode
|
||||
dotMode: root.dotMode
|
||||
dotSize: root.dotSize * root.freeScale
|
||||
@@ -230,7 +231,7 @@ Item {
|
||||
}
|
||||
|
||||
TransientSurfaceTracker {
|
||||
id: launcherTransientSurfaces
|
||||
id: islandTransientSurfaces
|
||||
}
|
||||
|
||||
IslandMediaSource {
|
||||
@@ -262,7 +263,7 @@ Item {
|
||||
systemModel: systemSource
|
||||
notificationModel: notificationSource
|
||||
launcherController: launcherController
|
||||
launcherTransientSurfaceTracker: launcherTransientSurfaces
|
||||
launcherTransientSurfaceTracker: islandTransientSurfaces
|
||||
effectiveScreen: root.screen
|
||||
hostOriginX: root.hostOriginX
|
||||
hostOriginY: root.hostOriginY
|
||||
|
||||
@@ -26,6 +26,14 @@ QtObject {
|
||||
if (launcherInputFocused)
|
||||
hoverExpanded = false;
|
||||
}
|
||||
property var transientSurfaces: null
|
||||
readonly property bool transientSurfacesActive: transientSurfaces?.active ?? false
|
||||
onTransientSurfacesActiveChanged: {
|
||||
if (!transientSurfacesActive)
|
||||
return;
|
||||
hoverExpanded = false;
|
||||
hoverCloseTimer.stop();
|
||||
}
|
||||
property string launcherPendingQuery: ""
|
||||
property string launcherPendingMode: ""
|
||||
property string controlCenterPendingSection: ""
|
||||
|
||||
@@ -200,7 +200,7 @@ Popup {
|
||||
onClosed: focusRestore.restart()
|
||||
|
||||
background: Rectangle {
|
||||
color: Theme.nestedSurface
|
||||
color: Theme.isFloatingWindow(processContextMenu) ? Theme.floatingWindowSurface : Theme.readableSurface
|
||||
border.width: Theme.layerOutlineWidth
|
||||
border.color: Theme.outlineMedium
|
||||
radius: Theme.windowRadius
|
||||
@@ -274,10 +274,10 @@ Popup {
|
||||
}
|
||||
|
||||
contentItem: Rectangle {
|
||||
color: Theme.nestedSurface
|
||||
color: Theme.foregroundColor(Theme.chipSurfaceNested, Theme.isFloatingWindow(processContextMenu))
|
||||
radius: Theme.windowRadius
|
||||
border.color: BlurService.borderColor
|
||||
border.width: BlurService.borderWidth
|
||||
border.color: Theme.outlineMedium
|
||||
border.width: Theme.layerOutlineWidth
|
||||
|
||||
Item {
|
||||
id: keyboardHandler
|
||||
|
||||
@@ -1422,6 +1422,20 @@ Item {
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
|
||||
onClicked: root.backgroundClicked()
|
||||
}
|
||||
|
||||
HoverHandler {
|
||||
enabled: root.hoverDismissEnabled && root.shouldBeVisible
|
||||
|
||||
function notePointer() {
|
||||
if (!hovered)
|
||||
return;
|
||||
PopoutManager.updateHoverCursor(point.position.x, point.position.y);
|
||||
hoverDismissController.notePointerMoved();
|
||||
}
|
||||
|
||||
onHoveredChanged: notePointer()
|
||||
onPointChanged: notePointer()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,8 @@ Item {
|
||||
|
||||
property int graceInterval: 150
|
||||
property bool bodyHovered: false
|
||||
// A closed transient surface leaves bodyHovered stale; sway sends no enter until the pointer moves.
|
||||
property bool pointerUnknown: false
|
||||
property real globalOffsetX: 0
|
||||
property real globalOffsetY: 0
|
||||
|
||||
@@ -19,12 +21,14 @@ Item {
|
||||
|
||||
function cancelPending() {
|
||||
graceTimer.stop();
|
||||
pointerUnknown = false;
|
||||
hoverTracker.cancelPending();
|
||||
}
|
||||
|
||||
function updateBodyHover(over) {
|
||||
bodyHovered = over;
|
||||
if (over) {
|
||||
pointerUnknown = false;
|
||||
graceTimer.stop();
|
||||
} else if (dismissEnabled && !dismissSuspended && surfaceVisible) {
|
||||
graceTimer.restart();
|
||||
@@ -35,15 +39,26 @@ Item {
|
||||
PopoutManager.updateHoverCursor(sceneX + globalOffsetX, sceneY + globalOffsetY);
|
||||
}
|
||||
|
||||
function notePointerMoved() {
|
||||
if (pointerUnknown)
|
||||
Qt.callLater(root.resolveUnknownPointer);
|
||||
}
|
||||
|
||||
function resolveUnknownPointer() {
|
||||
if (!pointerUnknown || bodyHovered)
|
||||
return;
|
||||
pointerUnknown = false;
|
||||
if (dismissEnabled && !dismissSuspended && surfaceVisible)
|
||||
graceTimer.restart();
|
||||
}
|
||||
|
||||
onDismissEnabledChanged: {
|
||||
if (!dismissEnabled)
|
||||
cancelPending();
|
||||
}
|
||||
onDismissSuspendedChanged: {
|
||||
if (dismissSuspended)
|
||||
graceTimer.stop();
|
||||
else if (dismissEnabled && surfaceVisible && !bodyHovered)
|
||||
graceTimer.restart();
|
||||
graceTimer.stop();
|
||||
pointerUnknown = !dismissSuspended && dismissEnabled && surfaceVisible && !bodyHovered;
|
||||
}
|
||||
onSurfaceVisibleChanged: {
|
||||
if (!surfaceVisible)
|
||||
@@ -70,6 +85,13 @@ Item {
|
||||
return !PopoutManager.cursorOverBar(PopoutManager.hoverCursorGlobalX, PopoutManager.hoverCursorGlobalY);
|
||||
}
|
||||
onDismissRequested: root.dismissRequested()
|
||||
onHoverMoved: (gx, gy) => root.updateCursor(gx, gy)
|
||||
onHoveredChanged: {
|
||||
if (hovered)
|
||||
root.notePointerMoved();
|
||||
}
|
||||
onHoverMoved: (gx, gy) => {
|
||||
root.updateCursor(gx, gy);
|
||||
root.notePointerMoved();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user