mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-08-10 07:28:30 -04:00
refactor: (modals/popouts): sync functions & improve blur calculations across modals
This commit is contained in:
@@ -162,37 +162,16 @@ Item {
|
|||||||
_publishModalChromeState();
|
_publishModalChromeState();
|
||||||
}
|
}
|
||||||
|
|
||||||
property bool _animSyncQueued: false
|
|
||||||
property bool _bodySyncQueued: false
|
|
||||||
|
|
||||||
function _queueFullSync() {
|
function _queueFullSync() {
|
||||||
_fullSyncPending = true;
|
_fullSyncPending = true;
|
||||||
if (!_syncTimer.running)
|
if (!_syncTimer.running)
|
||||||
_syncTimer.restart();
|
_syncTimer.restart();
|
||||||
}
|
}
|
||||||
function _queueAnimSync() {
|
|
||||||
_animSyncQueued = true;
|
|
||||||
if (!_syncTimer.running)
|
|
||||||
_syncTimer.restart();
|
|
||||||
}
|
|
||||||
function _queueBodySync() {
|
|
||||||
_bodySyncQueued = true;
|
|
||||||
if (!_syncTimer.running)
|
|
||||||
_syncTimer.restart();
|
|
||||||
}
|
|
||||||
function _flushSync() {
|
function _flushSync() {
|
||||||
const fullDirty = _fullSyncPending;
|
if (!_fullSyncPending)
|
||||||
const animDirty = _animSyncQueued;
|
return;
|
||||||
const bodyDirty = _bodySyncQueued;
|
|
||||||
_fullSyncPending = false;
|
_fullSyncPending = false;
|
||||||
_animSyncQueued = false;
|
|
||||||
_bodySyncQueued = false;
|
|
||||||
if (fullDirty)
|
|
||||||
_syncModalChromeState();
|
_syncModalChromeState();
|
||||||
if (animDirty)
|
|
||||||
_syncModalAnim();
|
|
||||||
if (bodyDirty)
|
|
||||||
_syncModalBody();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function _syncModalAnim() {
|
function _syncModalAnim() {
|
||||||
@@ -216,10 +195,11 @@ Item {
|
|||||||
onFrameOwnsConnectedChromeChanged: _syncModalChromeState()
|
onFrameOwnsConnectedChromeChanged: _syncModalChromeState()
|
||||||
onResolvedConnectedBarSideChanged: _queueFullSync()
|
onResolvedConnectedBarSideChanged: _queueFullSync()
|
||||||
onShouldBeVisibleChanged: _queueFullSync()
|
onShouldBeVisibleChanged: _queueFullSync()
|
||||||
onAlignedXChanged: _queueBodySync()
|
// Low resource scalar writes: publish synchronously to stay in the same frame
|
||||||
onAlignedYChanged: _queueBodySync()
|
onAlignedXChanged: _syncModalBody()
|
||||||
onAlignedWidthChanged: _queueBodySync()
|
onAlignedYChanged: _syncModalBody()
|
||||||
onAlignedHeightChanged: _queueBodySync()
|
onAlignedWidthChanged: _syncModalBody()
|
||||||
|
onAlignedHeightChanged: _syncModalBody()
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: contentWindow
|
target: contentWindow
|
||||||
@@ -613,9 +593,9 @@ Item {
|
|||||||
readonly property real scaleValue: computedScaleCollapsed + (1.0 - computedScaleCollapsed) * morph.openProgress
|
readonly property real scaleValue: computedScaleCollapsed + (1.0 - computedScaleCollapsed) * morph.openProgress
|
||||||
|
|
||||||
onAnimXChanged: if (root.frameOwnsConnectedChrome)
|
onAnimXChanged: if (root.frameOwnsConnectedChrome)
|
||||||
root._queueAnimSync()
|
root._syncModalAnim()
|
||||||
onAnimYChanged: if (root.frameOwnsConnectedChrome)
|
onAnimYChanged: if (root.frameOwnsConnectedChrome)
|
||||||
root._queueAnimSync()
|
root._syncModalAnim()
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: contentContainer
|
id: contentContainer
|
||||||
|
|||||||
@@ -244,11 +244,11 @@ Item {
|
|||||||
WindowBlur {
|
WindowBlur {
|
||||||
targetWindow: contentWindow
|
targetWindow: contentWindow
|
||||||
readonly property real s: Math.min(1, modalContainer.scaleValue)
|
readonly property real s: Math.min(1, modalContainer.scaleValue)
|
||||||
readonly property real op: Math.max(0, Math.min(1, (morph.openProgress - 0.06) * 2))
|
// Blur tracks the surface's scaled rect, matching the connected backend.
|
||||||
blurX: modalContainer.x + modalContainer.width * (1 - s * op) * 0.5 + Theme.snap(modalContainer.animX, root.dpr)
|
blurX: modalContainer.x + modalContainer.width * (1 - s) * 0.5 + Theme.snap(modalContainer.animX, root.dpr)
|
||||||
blurY: modalContainer.y + modalContainer.height * (1 - s * op) * 0.5 + Theme.snap(modalContainer.animY, root.dpr)
|
blurY: modalContainer.y + modalContainer.height * (1 - s) * 0.5 + Theme.snap(modalContainer.animY, root.dpr)
|
||||||
blurWidth: root.shouldBeVisible ? modalContainer.width * s * op : 0
|
blurWidth: root.shouldBeVisible ? modalContainer.width * s : 0
|
||||||
blurHeight: root.shouldBeVisible ? modalContainer.height * s * op : 0
|
blurHeight: root.shouldBeVisible ? modalContainer.height * s : 0
|
||||||
blurRadius: root.cornerRadius
|
blurRadius: root.cornerRadius
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -364,11 +364,11 @@ Item {
|
|||||||
WindowBlur {
|
WindowBlur {
|
||||||
targetWindow: launcherWindow
|
targetWindow: launcherWindow
|
||||||
readonly property real s: Math.min(1, modalContainer.publishedScale)
|
readonly property real s: Math.min(1, modalContainer.publishedScale)
|
||||||
readonly property real op: Math.max(0, Math.min(1, (modalContainer.publishedOpacity - 0.06) * 2))
|
// Blur tracks the surface's scaled rect
|
||||||
blurX: modalContainer.x + modalContainer.width * (1 - s * op) * 0.5
|
blurX: modalContainer.x + modalContainer.width * (1 - s) * 0.5
|
||||||
blurY: modalContainer.y + modalContainer.height * (1 - s * op) * 0.5
|
blurY: modalContainer.y + modalContainer.height * (1 - s) * 0.5
|
||||||
blurWidth: contentVisible ? modalContainer.width * s * op : 0
|
blurWidth: contentVisible ? modalContainer.width * s : 0
|
||||||
blurHeight: contentVisible ? modalContainer.height * s * op : 0
|
blurHeight: contentVisible ? modalContainer.height * s : 0
|
||||||
blurRadius: root.cornerRadius
|
blurRadius: root.cornerRadius
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -154,10 +154,12 @@ Singleton {
|
|||||||
continue;
|
continue;
|
||||||
if (!x || !y)
|
if (!x || !y)
|
||||||
return false;
|
return false;
|
||||||
// Only niri's enriched snapshots support value comparison.
|
// Only niri/mango enriched snapshots support value comparison
|
||||||
if (x.niriWindowId === undefined || y.niriWindowId === undefined)
|
const xKey = x.niriWindowId !== undefined ? x.niriWindowId : x.mangoWindowId;
|
||||||
|
const yKey = y.niriWindowId !== undefined ? y.niriWindowId : y.mangoWindowId;
|
||||||
|
if (xKey === undefined || yKey === undefined)
|
||||||
return false;
|
return false;
|
||||||
if (x.niriWindowId !== y.niriWindowId || x.niriWorkspaceId !== y.niriWorkspaceId || x.appId !== y.appId || x.title !== y.title || !!x.activated !== !!y.activated || !!x.fullscreen !== !!y.fullscreen || !!x.maximized !== !!y.maximized || !!x.minimized !== !!y.minimized)
|
if (xKey !== yKey || x.niriWorkspaceId !== y.niriWorkspaceId || x.appId !== y.appId || x.title !== y.title || !!x.activated !== !!y.activated || !!x.fullscreen !== !!y.fullscreen || !!x.maximized !== !!y.maximized || !!x.minimized !== !!y.minimized)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ Item {
|
|||||||
property bool fullHeightSurface: false
|
property bool fullHeightSurface: false
|
||||||
property bool _primeContent: false
|
property bool _primeContent: false
|
||||||
property bool _contentWarm: false
|
property bool _contentWarm: false
|
||||||
|
// Keyboard focus grabbed one tick after emerge starts, to avoid stalling first frames.
|
||||||
|
property bool _keyboardReady: false
|
||||||
property bool _resizeActive: false
|
property bool _resizeActive: false
|
||||||
property real _chromeAnimTravelX: 1
|
property real _chromeAnimTravelX: 1
|
||||||
property real _chromeAnimTravelY: 1
|
property real _chromeAnimTravelY: 1
|
||||||
@@ -241,7 +243,8 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function _connectedChromeState(visibleOverride) {
|
function _connectedChromeState(visibleOverride) {
|
||||||
const visible = visibleOverride !== undefined ? !!visibleOverride : contentWindow.visible;
|
// Track intent rather than the transient wl_surface state during remap.
|
||||||
|
const visible = visibleOverride !== undefined ? !!visibleOverride : (contentWindow.visible || root.shouldBeVisible);
|
||||||
const presented = contentWindow.visible || root.shouldBeVisible;
|
const presented = contentWindow.visible || root.shouldBeVisible;
|
||||||
const phase = root.isClosing ? "closing" : (!presented ? "hidden" : (!contentWindow.visible && root.shouldBeVisible ? "opening" : "open"));
|
const phase = root.isClosing ? "closing" : (!presented ? "hidden" : (!contentWindow.visible && root.shouldBeVisible ? "opening" : "open"));
|
||||||
const bodyX = Theme.snap(root.pubBodyX, root.dpr);
|
const bodyX = Theme.snap(root.pubBodyX, root.dpr);
|
||||||
@@ -353,48 +356,26 @@ Item {
|
|||||||
_publishedBodyValid = false;
|
_publishedBodyValid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
property bool _animSyncQueued: false
|
|
||||||
property bool _bodySyncQueued: false
|
|
||||||
|
|
||||||
function _queueFullSync() {
|
function _queueFullSync() {
|
||||||
_fullSyncQueued = true;
|
_fullSyncQueued = true;
|
||||||
if (!_syncTimer.running)
|
if (!_syncTimer.running)
|
||||||
_syncTimer.restart();
|
_syncTimer.restart();
|
||||||
}
|
}
|
||||||
function _queueAnimSync() {
|
|
||||||
_animSyncQueued = true;
|
|
||||||
if (!_syncTimer.running)
|
|
||||||
_syncTimer.restart();
|
|
||||||
}
|
|
||||||
function _queueBodySync() {
|
|
||||||
_bodySyncQueued = true;
|
|
||||||
if (!_syncTimer.running)
|
|
||||||
_syncTimer.restart();
|
|
||||||
}
|
|
||||||
function _flushSync() {
|
function _flushSync() {
|
||||||
const fullDirty = _fullSyncQueued;
|
if (!_fullSyncQueued)
|
||||||
const animDirty = _animSyncQueued;
|
return;
|
||||||
const bodyDirty = _bodySyncQueued;
|
|
||||||
_fullSyncQueued = false;
|
_fullSyncQueued = false;
|
||||||
_animSyncQueued = false;
|
|
||||||
_bodySyncQueued = false;
|
|
||||||
if (fullDirty)
|
|
||||||
_syncPopoutChromeState();
|
_syncPopoutChromeState();
|
||||||
if (animDirty) {
|
|
||||||
_syncPopoutAnim("x");
|
|
||||||
_syncPopoutAnim("y");
|
|
||||||
}
|
|
||||||
if (bodyDirty)
|
|
||||||
_syncPopoutBody();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onAlignedXChanged: _queueFullSync()
|
onAlignedXChanged: _queueFullSync()
|
||||||
onAlignedYChanged: _queueFullSync()
|
onAlignedYChanged: _queueFullSync()
|
||||||
onAlignedWidthChanged: _queueFullSync()
|
onAlignedWidthChanged: _queueFullSync()
|
||||||
onContentAnimXChanged: _queueAnimSync()
|
// Cheap deduped scalar writes: publish synchronously to stay in the same frame.
|
||||||
onContentAnimYChanged: _queueAnimSync()
|
onContentAnimXChanged: _syncPopoutAnim("x")
|
||||||
onRenderedAlignedYChanged: _queueBodySync()
|
onContentAnimYChanged: _syncPopoutAnim("y")
|
||||||
onRenderedAlignedHeightChanged: _queueBodySync()
|
onRenderedAlignedYChanged: _syncPopoutBody()
|
||||||
|
onRenderedAlignedHeightChanged: _syncPopoutBody()
|
||||||
onScreenChanged: {
|
onScreenChanged: {
|
||||||
_resetPublishedBody();
|
_resetPublishedBody();
|
||||||
_queueFullSync();
|
_queueFullSync();
|
||||||
@@ -517,6 +498,10 @@ Item {
|
|||||||
|
|
||||||
animationsEnabled = true;
|
animationsEnabled = true;
|
||||||
shouldBeVisible = true;
|
shouldBeVisible = true;
|
||||||
|
Qt.callLater(() => {
|
||||||
|
if (root.shouldBeVisible)
|
||||||
|
root._keyboardReady = true;
|
||||||
|
});
|
||||||
if (shouldBeVisible && screen) {
|
if (shouldBeVisible && screen) {
|
||||||
opened();
|
opened();
|
||||||
}
|
}
|
||||||
@@ -530,6 +515,7 @@ Item {
|
|||||||
_resetPublishedBody();
|
_resetPublishedBody();
|
||||||
isClosing = true;
|
isClosing = true;
|
||||||
shouldBeVisible = false;
|
shouldBeVisible = false;
|
||||||
|
_keyboardReady = false;
|
||||||
_primeContent = false;
|
_primeContent = false;
|
||||||
PopoutManager.popoutChanged();
|
PopoutManager.popoutChanged();
|
||||||
closeTimer.restart();
|
closeTimer.restart();
|
||||||
@@ -743,9 +729,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
|
||||||
|
|
||||||
// One animation drives all four coordinates, so queue one coalesced state update
|
// One animation drives all four coordinates, so publish once per progress
|
||||||
// per progress tick instead of reacting independently to each derived property.
|
// tick instead of reacting independently to each derived property.
|
||||||
onMorphProgressChanged: _queueBodySync()
|
onMorphProgressChanged: _syncPopoutBody()
|
||||||
|
|
||||||
function _beginMorphTravel() {
|
function _beginMorphTravel() {
|
||||||
morphTravelEnabled = false;
|
morphTravelEnabled = false;
|
||||||
@@ -967,7 +953,7 @@ Item {
|
|||||||
WlrLayershell.namespace: root.layerNamespace
|
WlrLayershell.namespace: root.layerNamespace
|
||||||
WlrLayershell.layer: root.effectivePopoutLayer
|
WlrLayershell.layer: root.effectivePopoutLayer
|
||||||
WlrLayershell.exclusiveZone: -1
|
WlrLayershell.exclusiveZone: -1
|
||||||
WlrLayershell.keyboardFocus: KeyboardFocus.keyboardFocus(shouldBeVisible, customKeyboardFocus)
|
WlrLayershell.keyboardFocus: KeyboardFocus.keyboardFocus(shouldBeVisible && root._keyboardReady, customKeyboardFocus)
|
||||||
|
|
||||||
readonly property bool _fullHeight: root.fullHeightSurface
|
readonly property bool _fullHeight: root.fullHeightSurface
|
||||||
anchors {
|
anchors {
|
||||||
|
|||||||
@@ -620,13 +620,13 @@ Item {
|
|||||||
id: popoutBlur
|
id: popoutBlur
|
||||||
targetWindow: contentWindow
|
targetWindow: contentWindow
|
||||||
readonly property real s: Math.min(1, contentContainer.scaleValue)
|
readonly property real s: Math.min(1, contentContainer.scaleValue)
|
||||||
readonly property real op: Math.max(0, Math.min(1, (morph.openProgress - 0.08) * 1.6))
|
|
||||||
readonly property bool revealClipActive: root.fluidStandaloneActive
|
readonly property bool revealClipActive: root.fluidStandaloneActive
|
||||||
|
|
||||||
blurX: revealClipActive ? contentContainer.x : contentContainer.x + contentContainer.width * (1 - s * op) * 0.5 + Theme.snap(contentContainer.animX, root.dpr)
|
// Blur tracks the surface's scaled rect, matching the connected backend
|
||||||
blurY: revealClipActive ? contentContainer.y : contentContainer.y + contentContainer.height * (1 - s * op) * 0.5 + Theme.snap(contentContainer.animY, root.dpr)
|
blurX: revealClipActive ? contentContainer.x : contentContainer.x + contentContainer.width * (1 - s) * 0.5 + Theme.snap(contentContainer.animX, root.dpr)
|
||||||
blurWidth: root.shouldBeVisible ? (revealClipActive ? contentContainer.width : contentContainer.width * s * op) : 0
|
blurY: revealClipActive ? contentContainer.y : contentContainer.y + contentContainer.height * (1 - s) * 0.5 + Theme.snap(contentContainer.animY, root.dpr)
|
||||||
blurHeight: root.shouldBeVisible ? (revealClipActive ? contentContainer.height : contentContainer.height * s * op) : 0
|
blurWidth: root.shouldBeVisible ? (revealClipActive ? contentContainer.width : contentContainer.width * s) : 0
|
||||||
|
blurHeight: root.shouldBeVisible ? (revealClipActive ? contentContainer.height : contentContainer.height * s) : 0
|
||||||
blurRadius: Theme.cornerRadius
|
blurRadius: Theme.cornerRadius
|
||||||
clipEnabled: revealClipActive
|
clipEnabled: revealClipActive
|
||||||
clipX: contentContainer.x + contentContainer.revealX
|
clipX: contentContainer.x + contentContainer.revealX
|
||||||
|
|||||||
@@ -99,8 +99,9 @@ Item {
|
|||||||
root._clear();
|
root._clear();
|
||||||
}
|
}
|
||||||
function onResourcesLost() {
|
function onResourcesLost() {
|
||||||
lifecycleKickAction.cancel();
|
|
||||||
root._clear();
|
root._clear();
|
||||||
|
// Re-arm so blur self-heals since instances are no longer recreated per open
|
||||||
|
root._scheduleLifecycleKick();
|
||||||
}
|
}
|
||||||
function onWindowConnected() {
|
function onWindowConnected() {
|
||||||
root._scheduleLifecycleKick();
|
root._scheduleLifecycleKick();
|
||||||
|
|||||||
Reference in New Issue
Block a user