mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-06-27 05:25:19 -04:00
feat(popouts): hover & settings cleanup
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
repos:
|
repos:
|
||||||
- repo: https://github.com/golangci/golangci-lint
|
- repo: https://github.com/golangci/golangci-lint
|
||||||
rev: v2.10.1
|
rev: v2.12.2
|
||||||
hooks:
|
hooks:
|
||||||
- id: golangci-lint-fmt
|
- id: golangci-lint-fmt
|
||||||
require_serial: true
|
require_serial: true
|
||||||
|
|||||||
@@ -191,7 +191,7 @@ 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;
|
return p.hoverDismissEnabled === false || p.hoverDismissSuspended === true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isCurrentPopout(popout, screenName) {
|
function isCurrentPopout(popout, screenName) {
|
||||||
|
|||||||
@@ -98,6 +98,7 @@ DankPopout {
|
|||||||
property bool anyModalOpen: credentialsPromptOpen || wifiPasswordModalOpen || polkitModalOpen || powerMenuOpen
|
property bool anyModalOpen: credentialsPromptOpen || wifiPasswordModalOpen || polkitModalOpen || powerMenuOpen
|
||||||
|
|
||||||
backgroundInteractive: !anyModalOpen
|
backgroundInteractive: !anyModalOpen
|
||||||
|
hoverDismissSuspended: editMode || anyModalOpen
|
||||||
|
|
||||||
onCredentialsPromptOpenChanged: {
|
onCredentialsPromptOpenChanged: {
|
||||||
if (credentialsPromptOpen && shouldBeVisible)
|
if (credentialsPromptOpen && shouldBeVisible)
|
||||||
|
|||||||
@@ -95,6 +95,14 @@ Item {
|
|||||||
enableFrameInsetAnimation.schedule();
|
enableFrameInsetAnimation.schedule();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: topBarContent._hasBarWindow ? topBarContent.barWindow.axis : null
|
||||||
|
|
||||||
|
function onEdgeChanged() {
|
||||||
|
topBarContent.resetHoverForBarGeometryChange();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Behavior on anchors.leftMargin {
|
Behavior on anchors.leftMargin {
|
||||||
enabled: _animateFrameInsets && _usesFrameBarChrome
|
enabled: _animateFrameInsets && _usesFrameBarChrome
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
@@ -401,6 +409,19 @@ Item {
|
|||||||
property var _pendingHoverHit: null
|
property var _pendingHoverHit: null
|
||||||
property string _pendingHoverTrigger: ""
|
property string _pendingHoverTrigger: ""
|
||||||
|
|
||||||
|
function resetHoverForBarGeometryChange() {
|
||||||
|
_cancelPendingHover();
|
||||||
|
_hoverCloseTimer.stop();
|
||||||
|
_pendingPopoutOpenSpec = null;
|
||||||
|
|
||||||
|
const activePopout = PopoutManager.getActivePopout(barWindow?.screen);
|
||||||
|
const hasTransientSurface = activeHoverTrigger !== "" || activePopout?.hoverDismissEnabled === true;
|
||||||
|
if (hasTransientSurface && !PopoutManager.isActivePopoutPinned(barWindow?.screen))
|
||||||
|
closeHoverSurfaces();
|
||||||
|
else
|
||||||
|
activeHoverTrigger = "";
|
||||||
|
}
|
||||||
|
|
||||||
Timer {
|
Timer {
|
||||||
id: _hoverIntentTimer
|
id: _hoverIntentTimer
|
||||||
interval: topBarContent.hoverPopoutDelay
|
interval: topBarContent.hoverPopoutDelay
|
||||||
@@ -525,6 +546,9 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (typeof popout.prepareForTrigger === "function")
|
||||||
|
popout.prepareForTrigger(spec.triggerSource, mode);
|
||||||
|
|
||||||
if (spec.prepare)
|
if (spec.prepare)
|
||||||
spec.prepare(popout);
|
spec.prepare(popout);
|
||||||
|
|
||||||
@@ -859,6 +883,10 @@ Item {
|
|||||||
const inst = _notepadWidgetForScreen()?.notepadInstance;
|
const inst = _notepadWidgetForScreen()?.notepadInstance;
|
||||||
return inst?.isVisible ?? false;
|
return inst?.isVisible ?? false;
|
||||||
}
|
}
|
||||||
|
if (activeHoverTrigger.startsWith("tray-")) {
|
||||||
|
const screenName = barWindow.screen?.name;
|
||||||
|
return !!(screenName && TrayMenuManager.activeTrayMenus[screenName]);
|
||||||
|
}
|
||||||
const popout = PopoutManager.getActivePopout(barWindow?.screen);
|
const popout = PopoutManager.getActivePopout(barWindow?.screen);
|
||||||
if (!popout)
|
if (!popout)
|
||||||
return false;
|
return false;
|
||||||
@@ -1116,12 +1144,19 @@ Item {
|
|||||||
if (!PopoutManager.cursorOverBar(_lastHoverGlobalX, _lastHoverGlobalY))
|
if (!PopoutManager.cursorOverBar(_lastHoverGlobalX, _lastHoverGlobalY))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
const activePopout = PopoutManager.getActivePopout(barWindow?.screen);
|
||||||
|
const targetLoader = _loaderForWidgetId(hit.widgetId);
|
||||||
|
const targetPopout = _resolvePopoutFromLoader(targetLoader);
|
||||||
|
const managerOwnsTransition = !!(activePopout && targetPopout);
|
||||||
|
|
||||||
// A different trigger backed by the same already-open popout swaps tab/position
|
// A different trigger backed by the same already-open popout swaps tab/position
|
||||||
// in place (requestHoverPopout handles it) — don't close+reopen the same surface.
|
// in place. PopoutManager also owns handoff between loaded popouts, so only
|
||||||
|
// pre-close special/unmanaged surfaces here.
|
||||||
if (triggerKey !== activeHoverTrigger && activeHoverTrigger !== "" && !_hitTargetsActivePopout(hit)) {
|
if (triggerKey !== activeHoverTrigger && activeHoverTrigger !== "" && !_hitTargetsActivePopout(hit)) {
|
||||||
// Mark popout as superseded to fade in-place before closing.
|
if (!managerOwnsTransition) {
|
||||||
_beginSupersededCloseForActive();
|
_beginSupersededCloseForActive();
|
||||||
closeHoverSurfaces();
|
closeHoverSurfaces();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!openHoverPopoutForHit(hit)) {
|
if (!openHoverPopoutForHit(hit)) {
|
||||||
|
|||||||
@@ -26,6 +26,19 @@ DankPopout {
|
|||||||
open();
|
open();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function prepareForTrigger(triggerSource) {
|
||||||
|
switch (triggerSource) {
|
||||||
|
case "memory":
|
||||||
|
DgopService.setSortBy("memory");
|
||||||
|
break;
|
||||||
|
case "cpu":
|
||||||
|
case "cpu_temp":
|
||||||
|
case "gpu_temp":
|
||||||
|
DgopService.setSortBy("cpu");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
popupWidth: Math.round(Theme.fontSizeMedium * 46)
|
popupWidth: Math.round(Theme.fontSizeMedium * 46)
|
||||||
popupHeight: Math.round(Theme.fontSizeMedium * 39)
|
popupHeight: Math.round(Theme.fontSizeMedium * 39)
|
||||||
triggerWidth: 55
|
triggerWidth: 55
|
||||||
|
|||||||
@@ -1256,6 +1256,50 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SettingsToggleCard {
|
||||||
|
iconName: "touch_app"
|
||||||
|
title: I18n.tr("Hover Popouts")
|
||||||
|
description: I18n.tr("Open widget popouts by hovering over the bar. Moving to another widget switches the popout.")
|
||||||
|
visible: !dankBarTab.appearanceOnly && selectedBarConfig?.enabled
|
||||||
|
enabled: !(selectedBarConfig?.clickThrough ?? false)
|
||||||
|
opacity: (selectedBarConfig?.clickThrough ?? false) ? 0.5 : 1.0
|
||||||
|
checked: selectedBarConfig?.hoverPopouts ?? false
|
||||||
|
onToggled: checked => SettingsData.updateBarConfig(selectedBarId, {
|
||||||
|
hoverPopouts: checked
|
||||||
|
})
|
||||||
|
|
||||||
|
Column {
|
||||||
|
width: parent.width
|
||||||
|
spacing: Theme.spacingS
|
||||||
|
visible: selectedBarConfig?.hoverPopouts ?? false
|
||||||
|
leftPadding: Theme.spacingM
|
||||||
|
|
||||||
|
SettingsSliderRow {
|
||||||
|
id: hoverDelaySlider
|
||||||
|
width: parent.width - parent.leftPadding
|
||||||
|
text: I18n.tr("Open Delay")
|
||||||
|
description: I18n.tr("Time to rest on a widget before its popout opens")
|
||||||
|
value: selectedBarConfig?.hoverPopoutDelay ?? 150
|
||||||
|
minimum: 0
|
||||||
|
maximum: 1000
|
||||||
|
unit: "ms"
|
||||||
|
defaultValue: 150
|
||||||
|
onSliderValueChanged: newValue => {
|
||||||
|
SettingsData.updateBarConfig(selectedBarId, {
|
||||||
|
hoverPopoutDelay: newValue
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Binding {
|
||||||
|
target: hoverDelaySlider
|
||||||
|
property: "value"
|
||||||
|
value: selectedBarConfig?.hoverPopoutDelay ?? 150
|
||||||
|
restoreMode: Binding.RestoreBinding
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SettingsToggleCard {
|
SettingsToggleCard {
|
||||||
iconName: "fit_screen"
|
iconName: "fit_screen"
|
||||||
title: I18n.tr("Maximize Detection")
|
title: I18n.tr("Maximize Detection")
|
||||||
@@ -1800,50 +1844,6 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingsToggleCard {
|
|
||||||
iconName: "touch_app"
|
|
||||||
title: I18n.tr("Hover Popouts")
|
|
||||||
description: I18n.tr("Open widget popouts by hovering over the bar. Moving to another widget switches the popout.")
|
|
||||||
visible: !dankBarTab.appearanceOnly && selectedBarConfig?.enabled
|
|
||||||
enabled: !(selectedBarConfig?.clickThrough ?? false)
|
|
||||||
opacity: (selectedBarConfig?.clickThrough ?? false) ? 0.5 : 1.0
|
|
||||||
checked: selectedBarConfig?.hoverPopouts ?? false
|
|
||||||
onToggled: checked => SettingsData.updateBarConfig(selectedBarId, {
|
|
||||||
hoverPopouts: checked
|
|
||||||
})
|
|
||||||
|
|
||||||
Column {
|
|
||||||
width: parent.width
|
|
||||||
spacing: Theme.spacingS
|
|
||||||
visible: selectedBarConfig?.hoverPopouts ?? false
|
|
||||||
leftPadding: Theme.spacingM
|
|
||||||
|
|
||||||
SettingsSliderRow {
|
|
||||||
id: hoverDelaySlider
|
|
||||||
width: parent.width - parent.leftPadding
|
|
||||||
text: I18n.tr("Open Delay")
|
|
||||||
description: I18n.tr("Time to rest on a widget before its popout opens")
|
|
||||||
value: selectedBarConfig?.hoverPopoutDelay ?? 150
|
|
||||||
minimum: 0
|
|
||||||
maximum: 1000
|
|
||||||
unit: "ms"
|
|
||||||
defaultValue: 150
|
|
||||||
onSliderValueChanged: newValue => {
|
|
||||||
SettingsData.updateBarConfig(selectedBarId, {
|
|
||||||
hoverPopoutDelay: newValue
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Binding {
|
|
||||||
target: hoverDelaySlider
|
|
||||||
property: "value"
|
|
||||||
value: selectedBarConfig?.hoverPopoutDelay ?? 150
|
|
||||||
restoreMode: Binding.RestoreBinding
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SettingsToggleCard {
|
SettingsToggleCard {
|
||||||
iconName: "mouse"
|
iconName: "mouse"
|
||||||
title: I18n.tr("Scroll Wheel")
|
title: I18n.tr("Scroll Wheel")
|
||||||
|
|||||||
@@ -359,7 +359,7 @@ Item {
|
|||||||
tags: ["background", "color", "fill", "fit", "custom"]
|
tags: ["background", "color", "fill", "fit", "custom"]
|
||||||
settingKey: "wallpaperBackgroundColorMode"
|
settingKey: "wallpaperBackgroundColorMode"
|
||||||
text: I18n.tr("Background Color")
|
text: I18n.tr("Background Color")
|
||||||
description: I18n.tr("Color shown for areas not covered by wallpaper (e.g. Fit or Pad modes)")
|
description: I18n.tr("Color shown for areas not covered by wallpaper")
|
||||||
visible: root.currentWallpaper !== "" && !root.currentWallpaper.startsWith("#")
|
visible: root.currentWallpaper !== "" && !root.currentWallpaper.startsWith("#")
|
||||||
dropdownWidth: 220
|
dropdownWidth: 220
|
||||||
options: [
|
options: [
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ Item {
|
|||||||
property bool suspendShadowWhileResizing: false
|
property bool suspendShadowWhileResizing: false
|
||||||
property bool shouldBeVisible: false
|
property bool shouldBeVisible: false
|
||||||
property bool hoverDismissEnabled: false
|
property bool hoverDismissEnabled: false
|
||||||
|
property bool hoverDismissSuspended: false
|
||||||
property var customKeyboardFocus: null
|
property var customKeyboardFocus: null
|
||||||
property bool backgroundInteractive: true
|
property bool backgroundInteractive: true
|
||||||
property bool contentHandlesKeys: false
|
property bool contentHandlesKeys: false
|
||||||
@@ -187,6 +188,8 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function closeFromHoverDismiss() {
|
function closeFromHoverDismiss() {
|
||||||
|
if (hoverDismissSuspended)
|
||||||
|
return;
|
||||||
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)
|
||||||
@@ -307,6 +310,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.shouldBeVisible = root.shouldBeVisible;
|
it.shouldBeVisible = root.shouldBeVisible;
|
||||||
if (root._primeContent && typeof it.primeContent === "function")
|
if (root._primeContent && typeof it.primeContent === "function")
|
||||||
|
|||||||
@@ -409,13 +409,15 @@ Item {
|
|||||||
|
|
||||||
property bool animationsEnabled: true
|
property bool animationsEnabled: true
|
||||||
property bool hoverDismissEnabled: false
|
property bool hoverDismissEnabled: false
|
||||||
|
property bool hoverDismissSuspended: false
|
||||||
|
|
||||||
function cancelHoverDismiss() {
|
function cancelHoverDismiss() {
|
||||||
hoverDismissTracker.cancelPending();
|
hoverDismissTracker.cancelPending();
|
||||||
|
_hoverDismissGrace.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
function closeFromHoverDismiss() {
|
function closeFromHoverDismiss() {
|
||||||
if (isClosing || !shouldBeVisible)
|
if (hoverDismissSuspended || isClosing || !shouldBeVisible)
|
||||||
return;
|
return;
|
||||||
if (popoutHandle?.closeFromHoverDismiss)
|
if (popoutHandle?.closeFromHoverDismiss)
|
||||||
popoutHandle.closeFromHoverDismiss();
|
popoutHandle.closeFromHoverDismiss();
|
||||||
@@ -479,7 +481,10 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function close() {
|
function close() {
|
||||||
_endMorphTravel();
|
if (_supersededClose && morphTravelEnabled)
|
||||||
|
_freezeMorphTravel();
|
||||||
|
else
|
||||||
|
_endMorphTravel();
|
||||||
isClosing = true;
|
isClosing = true;
|
||||||
shouldBeVisible = false;
|
shouldBeVisible = false;
|
||||||
_primeContent = false;
|
_primeContent = false;
|
||||||
@@ -518,6 +523,7 @@ Item {
|
|||||||
onTriggered: {
|
onTriggered: {
|
||||||
if (!shouldBeVisible) {
|
if (!shouldBeVisible) {
|
||||||
contentWindow.visible = false;
|
contentWindow.visible = false;
|
||||||
|
root._endMorphTravel();
|
||||||
isClosing = false;
|
isClosing = false;
|
||||||
PopoutManager.hidePopout(popoutHandle);
|
PopoutManager.hidePopout(popoutHandle);
|
||||||
popoutClosed();
|
popoutClosed();
|
||||||
@@ -682,8 +688,9 @@ Item {
|
|||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
duration: root._morphTravelDuration
|
duration: root._morphTravelDuration
|
||||||
easing.type: Easing.BezierSpline
|
easing.type: Easing.BezierSpline
|
||||||
// Emphasized curve for fluid morph travel.
|
// M3 Expressive spatial motion starts with momentum and settles gently,
|
||||||
easing.bezierCurve: Theme.expressiveCurves.emphasized
|
// which keeps rapid hover retargets from pausing between surfaces.
|
||||||
|
easing.bezierCurve: Theme.variantEnterCurve
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -692,10 +699,9 @@ Item {
|
|||||||
readonly property real pubBodyW: morphSeedW + (alignedWidth - morphSeedW) * morphProgress
|
readonly property real pubBodyW: morphSeedW + (alignedWidth - morphSeedW) * morphProgress
|
||||||
readonly property real pubBodyH: morphSeedH + (renderedAlignedHeight - morphSeedH) * morphProgress
|
readonly property real pubBodyH: morphSeedH + (renderedAlignedHeight - morphSeedH) * morphProgress
|
||||||
|
|
||||||
onPubBodyXChanged: _queueBodySync()
|
// One animation drives all four coordinates, so queue one coalesced state update
|
||||||
onPubBodyYChanged: _queueBodySync()
|
// per progress tick instead of reacting independently to each derived property.
|
||||||
onPubBodyWChanged: _queueBodySync()
|
onMorphProgressChanged: _queueBodySync()
|
||||||
onPubBodyHChanged: _queueBodySync()
|
|
||||||
|
|
||||||
function _beginMorphTravel() {
|
function _beginMorphTravel() {
|
||||||
morphTravelEnabled = false;
|
morphTravelEnabled = false;
|
||||||
@@ -716,12 +722,13 @@ Item {
|
|||||||
morphSeedY = ConnectedModeState.popoutBodyY;
|
morphSeedY = ConnectedModeState.popoutBodyY;
|
||||||
morphSeedW = w;
|
morphSeedW = w;
|
||||||
morphSeedH = h;
|
morphSeedH = h;
|
||||||
// Scale travel time with distance within ~[0.8x, 1.4x] of the popout duration:
|
// Scale spatial motion with both travel and shape change. Never shorten the
|
||||||
// enough room for the emphasized curve to breathe (fluid, not abrupt), capped so
|
// configured enter duration; cap long sweeps so hover switching stays responsive.
|
||||||
// long sweeps don't drag, and collapsing to 0 when popout animations are off.
|
const base = Math.max(0, Theme.variantDuration(root.animationDuration, true));
|
||||||
const base = Math.max(0, root.animationDuration);
|
const travel = Math.hypot(root.alignedX - morphSeedX, root.renderedAlignedY - morphSeedY);
|
||||||
const dist = Math.hypot(root.alignedX - morphSeedX, root.renderedAlignedY - morphSeedY);
|
const resize = Math.hypot(root.alignedWidth - morphSeedW, root.renderedAlignedHeight - morphSeedH);
|
||||||
_morphTravelDuration = Math.round(Math.min(base * 1.4, base * 0.8 + dist * 0.16));
|
const spatialDistance = travel + resize * 0.35;
|
||||||
|
_morphTravelDuration = Math.round(Math.min(base * 1.6, base + spatialDistance * 0.15));
|
||||||
morphProgress = 0;
|
morphProgress = 0;
|
||||||
morphTravelEnabled = true;
|
morphTravelEnabled = true;
|
||||||
Qt.callLater(() => {
|
Qt.callLater(() => {
|
||||||
@@ -730,6 +737,25 @@ Item {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function _freezeMorphTravel() {
|
||||||
|
const x = pubBodyX;
|
||||||
|
const y = pubBodyY;
|
||||||
|
const w = pubBodyW;
|
||||||
|
const h = pubBodyH;
|
||||||
|
|
||||||
|
// A third hover can supersede a morph before it settles. Freeze the outgoing
|
||||||
|
// content at the live rectangle so it fades in place while the next surface
|
||||||
|
// inherits exactly the same geometry.
|
||||||
|
morphTravelEnabled = false;
|
||||||
|
morphSeedX = x;
|
||||||
|
morphSeedY = y;
|
||||||
|
morphSeedW = w;
|
||||||
|
morphSeedH = h;
|
||||||
|
morphProgress = 0;
|
||||||
|
morphTravelEnabled = true;
|
||||||
|
_syncPopoutBody();
|
||||||
|
}
|
||||||
|
|
||||||
function _endMorphTravel() {
|
function _endMorphTravel() {
|
||||||
morphTravelEnabled = false;
|
morphTravelEnabled = false;
|
||||||
morphProgress = 1;
|
morphProgress = 1;
|
||||||
@@ -856,16 +882,24 @@ Item {
|
|||||||
_hoverOverBody = over;
|
_hoverOverBody = over;
|
||||||
if (over)
|
if (over)
|
||||||
_hoverDismissGrace.stop();
|
_hoverDismissGrace.stop();
|
||||||
else if (root.hoverDismissEnabled && root.shouldBeVisible)
|
else if (root.hoverDismissEnabled && !root.hoverDismissSuspended && root.shouldBeVisible)
|
||||||
_hoverDismissGrace.restart();
|
_hoverDismissGrace.restart();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onHoverDismissSuspendedChanged: {
|
||||||
|
if (hoverDismissSuspended) {
|
||||||
|
_hoverDismissGrace.stop();
|
||||||
|
} else if (hoverDismissEnabled && shouldBeVisible && !_hoverOverBody) {
|
||||||
|
_hoverDismissGrace.restart();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Timer {
|
Timer {
|
||||||
id: _hoverDismissGrace
|
id: _hoverDismissGrace
|
||||||
interval: 150
|
interval: 150
|
||||||
repeat: false
|
repeat: false
|
||||||
onTriggered: {
|
onTriggered: {
|
||||||
if (!root.hoverDismissEnabled || !root.shouldBeVisible)
|
if (!root.hoverDismissEnabled || root.hoverDismissSuspended || !root.shouldBeVisible)
|
||||||
return;
|
return;
|
||||||
if (root._hoverOverBody)
|
if (root._hoverOverBody)
|
||||||
return;
|
return;
|
||||||
@@ -907,7 +941,7 @@ Item {
|
|||||||
HoverDismissTracker {
|
HoverDismissTracker {
|
||||||
id: hoverDismissTracker
|
id: hoverDismissTracker
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
enabled: root.hoverDismissEnabled && root.shouldBeVisible
|
enabled: root.hoverDismissEnabled && !root.hoverDismissSuspended && root.shouldBeVisible
|
||||||
shouldDismiss: function () {
|
shouldDismiss: function () {
|
||||||
return !PopoutManager.cursorOverBar(PopoutManager.hoverCursorGlobalX, PopoutManager.hoverCursorGlobalY);
|
return !PopoutManager.cursorOverBar(PopoutManager.hoverCursorGlobalX, PopoutManager.hoverCursorGlobalY);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,13 +37,15 @@ Item {
|
|||||||
property bool isClosing: false
|
property bool isClosing: false
|
||||||
property bool animationsEnabled: true
|
property bool animationsEnabled: true
|
||||||
property bool hoverDismissEnabled: false
|
property bool hoverDismissEnabled: false
|
||||||
|
property bool hoverDismissSuspended: false
|
||||||
|
|
||||||
function cancelHoverDismiss() {
|
function cancelHoverDismiss() {
|
||||||
hoverDismissTracker.cancelPending();
|
hoverDismissTracker.cancelPending();
|
||||||
|
_hoverDismissGrace.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
function closeFromHoverDismiss() {
|
function closeFromHoverDismiss() {
|
||||||
if (isClosing || !shouldBeVisible)
|
if (hoverDismissSuspended || isClosing || !shouldBeVisible)
|
||||||
return;
|
return;
|
||||||
if (popoutHandle?.closeFromHoverDismiss)
|
if (popoutHandle?.closeFromHoverDismiss)
|
||||||
popoutHandle.closeFromHoverDismiss();
|
popoutHandle.closeFromHoverDismiss();
|
||||||
@@ -58,16 +60,24 @@ Item {
|
|||||||
_hoverOverBody = over;
|
_hoverOverBody = over;
|
||||||
if (over)
|
if (over)
|
||||||
_hoverDismissGrace.stop();
|
_hoverDismissGrace.stop();
|
||||||
else if (root.hoverDismissEnabled && root.shouldBeVisible)
|
else if (root.hoverDismissEnabled && !root.hoverDismissSuspended && root.shouldBeVisible)
|
||||||
_hoverDismissGrace.restart();
|
_hoverDismissGrace.restart();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onHoverDismissSuspendedChanged: {
|
||||||
|
if (hoverDismissSuspended) {
|
||||||
|
_hoverDismissGrace.stop();
|
||||||
|
} else if (hoverDismissEnabled && shouldBeVisible && !_hoverOverBody) {
|
||||||
|
_hoverDismissGrace.restart();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Timer {
|
Timer {
|
||||||
id: _hoverDismissGrace
|
id: _hoverDismissGrace
|
||||||
interval: 150
|
interval: 150
|
||||||
repeat: false
|
repeat: false
|
||||||
onTriggered: {
|
onTriggered: {
|
||||||
if (!root.hoverDismissEnabled || !root.shouldBeVisible)
|
if (!root.hoverDismissEnabled || root.hoverDismissSuspended || !root.shouldBeVisible)
|
||||||
return;
|
return;
|
||||||
if (root._hoverOverBody)
|
if (root._hoverOverBody)
|
||||||
return;
|
return;
|
||||||
@@ -641,7 +651,7 @@ Item {
|
|||||||
HoverDismissTracker {
|
HoverDismissTracker {
|
||||||
id: hoverDismissTracker
|
id: hoverDismissTracker
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
enabled: root.hoverDismissEnabled && root.shouldBeVisible
|
enabled: root.hoverDismissEnabled && !root.hoverDismissSuspended && root.shouldBeVisible
|
||||||
shouldDismiss: function () {
|
shouldDismiss: function () {
|
||||||
return !PopoutManager.cursorOverBar(PopoutManager.hoverCursorGlobalX, PopoutManager.hoverCursorGlobalY);
|
return !PopoutManager.cursorOverBar(PopoutManager.hoverCursorGlobalX, PopoutManager.hoverCursorGlobalY);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -362,7 +362,7 @@
|
|||||||
"wallpaper"
|
"wallpaper"
|
||||||
],
|
],
|
||||||
"icon": "wallpaper",
|
"icon": "wallpaper",
|
||||||
"description": "Color shown for areas not covered by wallpaper (e.g. Fit or Pad modes)"
|
"description": "Color shown for areas not covered by wallpaper"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"section": "selectedMonitor",
|
"section": "selectedMonitor",
|
||||||
@@ -8139,6 +8139,36 @@
|
|||||||
],
|
],
|
||||||
"icon": "monitor"
|
"icon": "monitor"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"section": "frameLauncherEdgeHover",
|
||||||
|
"label": "Edge Hover Reveal",
|
||||||
|
"tabIndex": 33,
|
||||||
|
"category": "Frame",
|
||||||
|
"keywords": [
|
||||||
|
"app drawer",
|
||||||
|
"app menu",
|
||||||
|
"applications",
|
||||||
|
"border",
|
||||||
|
"connected",
|
||||||
|
"decoration",
|
||||||
|
"edge",
|
||||||
|
"emerge",
|
||||||
|
"frame",
|
||||||
|
"free",
|
||||||
|
"hover",
|
||||||
|
"hovering",
|
||||||
|
"launcher",
|
||||||
|
"open",
|
||||||
|
"panel",
|
||||||
|
"reveal",
|
||||||
|
"start menu",
|
||||||
|
"statusbar",
|
||||||
|
"taskbar",
|
||||||
|
"topbar",
|
||||||
|
"window"
|
||||||
|
],
|
||||||
|
"description": "Open the launcher by hovering the emerge edge (when free of bar and dock)"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"section": "frameEnable",
|
"section": "frameEnable",
|
||||||
"label": "Enable Frame",
|
"label": "Enable Frame",
|
||||||
|
|||||||
Reference in New Issue
Block a user