mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-05-03 11:02:08 -04:00
general fixes and audit
This commit is contained in:
@@ -200,8 +200,6 @@ Singleton {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─── Notification state (per screen, updated by NotificationSurface) ──────
|
|
||||||
|
|
||||||
readonly property var emptyNotificationState: ({
|
readonly property var emptyNotificationState: ({
|
||||||
"visible": false,
|
"visible": false,
|
||||||
"barSide": "top",
|
"barSide": "top",
|
||||||
@@ -369,8 +367,6 @@ Singleton {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─── Dock retract coordination ────────────────────────────────
|
|
||||||
|
|
||||||
property var dockRetractRequests: ({})
|
property var dockRetractRequests: ({})
|
||||||
|
|
||||||
function requestDockRetract(requesterId, screenName, side) {
|
function requestDockRetract(requesterId, screenName, side) {
|
||||||
@@ -407,4 +403,64 @@ Singleton {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Prune state for screens that are no longer connected. Stale entries
|
||||||
|
// accumulate across hotplug cycles otherwise — Frame's per-screen
|
||||||
|
// FrameInstance doesn't notice when its peer dicts go orphan.
|
||||||
|
function _pruneToLiveScreens() {
|
||||||
|
const live = {};
|
||||||
|
const screens = Quickshell.screens || [];
|
||||||
|
for (let i = 0; i < screens.length; i++) {
|
||||||
|
const s = screens[i];
|
||||||
|
if (s && s.name)
|
||||||
|
live[s.name] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function pruneKeyed(dict) {
|
||||||
|
let changed = false;
|
||||||
|
const next = {};
|
||||||
|
for (const k in dict) {
|
||||||
|
if (live[k])
|
||||||
|
next[k] = dict[k];
|
||||||
|
else
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
return changed ? next : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nextDock = pruneKeyed(dockStates);
|
||||||
|
if (nextDock !== null)
|
||||||
|
dockStates = nextDock;
|
||||||
|
const nextSlides = pruneKeyed(dockSlides);
|
||||||
|
if (nextSlides !== null)
|
||||||
|
dockSlides = nextSlides;
|
||||||
|
const nextNotif = pruneKeyed(notificationStates);
|
||||||
|
if (nextNotif !== null)
|
||||||
|
notificationStates = nextNotif;
|
||||||
|
const nextModal = pruneKeyed(modalStates);
|
||||||
|
if (nextModal !== null)
|
||||||
|
modalStates = nextModal;
|
||||||
|
|
||||||
|
let retractChanged = false;
|
||||||
|
const nextRetract = {};
|
||||||
|
for (const k in dockRetractRequests) {
|
||||||
|
const r = dockRetractRequests[k];
|
||||||
|
if (r && live[r.screenName])
|
||||||
|
nextRetract[k] = r;
|
||||||
|
else
|
||||||
|
retractChanged = true;
|
||||||
|
}
|
||||||
|
if (retractChanged)
|
||||||
|
dockRetractRequests = nextRetract;
|
||||||
|
|
||||||
|
if (popoutOwnerId && popoutScreen && !live[popoutScreen])
|
||||||
|
releasePopout(popoutOwnerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: Quickshell
|
||||||
|
function onScreensChanged() {
|
||||||
|
root._pruneToLiveScreens();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -986,7 +986,6 @@ Singleton {
|
|||||||
"expressiveEffects": [0.34, 0.8, 0.34, 1, 1, 1]
|
"expressiveEffects": [0.34, 0.8, 0.34, 1, 1, 1]
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─── Animation variant proxy ──────────────────────────────────────────────
|
|
||||||
// Theme is the canonical access point for animation variant state. The
|
// Theme is the canonical access point for animation variant state. The
|
||||||
// aliases below forward to AnimVariants.qml so consumers don't need two
|
// aliases below forward to AnimVariants.qml so consumers don't need two
|
||||||
// imports. ~200 call sites read through Theme.variantEnterCurve /
|
// imports. ~200 call sites read through Theme.variantEnterCurve /
|
||||||
|
|||||||
@@ -84,9 +84,31 @@ Item {
|
|||||||
impl.item.toggle();
|
impl.item.toggle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
readonly property var _desiredBackend: SettingsData.connectedFrameModeActive ? connectedComp : standaloneComp
|
||||||
|
property var _resolvedBackend: null
|
||||||
|
|
||||||
|
Component.onCompleted: _resolvedBackend = _desiredBackend
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: SettingsData
|
||||||
|
function onConnectedFrameModeActiveChanged() {
|
||||||
|
root._maybeResolveBackend();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Defer Loader source-component swap until impl is fully closed; avoids
|
||||||
|
// tearing down a modal mid-animation when frame mode is toggled.
|
||||||
|
function _maybeResolveBackend() {
|
||||||
|
if (_resolvedBackend === _desiredBackend)
|
||||||
|
return;
|
||||||
|
if (impl.item && (impl.item.shouldBeVisible || impl.item.isClosing))
|
||||||
|
return;
|
||||||
|
_resolvedBackend = _desiredBackend;
|
||||||
|
}
|
||||||
|
|
||||||
Loader {
|
Loader {
|
||||||
id: impl
|
id: impl
|
||||||
sourceComponent: SettingsData.connectedFrameModeActive ? connectedComp : standaloneComp
|
sourceComponent: root._resolvedBackend
|
||||||
onItemChanged: if (item)
|
onItemChanged: if (item)
|
||||||
root._wireBackend(item)
|
root._wireBackend(item)
|
||||||
}
|
}
|
||||||
@@ -137,20 +159,7 @@ Item {
|
|||||||
it.useOverlayLayer = Qt.binding(() => root.useOverlayLayer);
|
it.useOverlayLayer = Qt.binding(() => root.useOverlayLayer);
|
||||||
|
|
||||||
it.shouldBeVisible = root.shouldBeVisible;
|
it.shouldBeVisible = root.shouldBeVisible;
|
||||||
it.shouldBeVisibleChanged.connect(function () {
|
|
||||||
if (root.shouldBeVisible !== it.shouldBeVisible)
|
|
||||||
root.shouldBeVisible = it.shouldBeVisible;
|
|
||||||
});
|
|
||||||
|
|
||||||
it.shouldHaveFocus = root.shouldHaveFocus;
|
it.shouldHaveFocus = root.shouldHaveFocus;
|
||||||
it.shouldHaveFocusChanged.connect(function () {
|
|
||||||
if (root.shouldHaveFocus !== it.shouldHaveFocus)
|
|
||||||
root.shouldHaveFocus = it.shouldHaveFocus;
|
|
||||||
});
|
|
||||||
|
|
||||||
it.opened.connect(root.opened);
|
|
||||||
it.dialogClosed.connect(root.dialogClosed);
|
|
||||||
it.backgroundClicked.connect(root.backgroundClicked);
|
|
||||||
|
|
||||||
if (it.modalFocusScope)
|
if (it.modalFocusScope)
|
||||||
_modalFocusScope.parent = it.modalFocusScope;
|
_modalFocusScope.parent = it.modalFocusScope;
|
||||||
@@ -167,4 +176,32 @@ Item {
|
|||||||
impl.item.shouldHaveFocus = root.shouldHaveFocus;
|
impl.item.shouldHaveFocus = root.shouldHaveFocus;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: impl.item
|
||||||
|
ignoreUnknownSignals: true
|
||||||
|
|
||||||
|
function onShouldBeVisibleChanged() {
|
||||||
|
if (impl.item && root.shouldBeVisible !== impl.item.shouldBeVisible)
|
||||||
|
root.shouldBeVisible = impl.item.shouldBeVisible;
|
||||||
|
}
|
||||||
|
|
||||||
|
function onShouldHaveFocusChanged() {
|
||||||
|
if (impl.item && root.shouldHaveFocus !== impl.item.shouldHaveFocus)
|
||||||
|
root.shouldHaveFocus = impl.item.shouldHaveFocus;
|
||||||
|
}
|
||||||
|
|
||||||
|
function onOpened() {
|
||||||
|
root.opened();
|
||||||
|
}
|
||||||
|
|
||||||
|
function onDialogClosed() {
|
||||||
|
root.dialogClosed();
|
||||||
|
root._maybeResolveBackend();
|
||||||
|
}
|
||||||
|
|
||||||
|
function onBackgroundClicked() {
|
||||||
|
root.backgroundClicked();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -95,7 +95,6 @@ Item {
|
|||||||
|
|
||||||
property bool animationsEnabled: true
|
property bool animationsEnabled: true
|
||||||
|
|
||||||
// ─── Connected chrome sync ────────────────────────────────────────────────
|
|
||||||
property string _chromeClaimId: ""
|
property string _chromeClaimId: ""
|
||||||
property bool _fullSyncPending: false
|
property bool _fullSyncPending: false
|
||||||
|
|
||||||
@@ -341,8 +340,6 @@ Item {
|
|||||||
readonly property real shadowMotionPadding: {
|
readonly property real shadowMotionPadding: {
|
||||||
if (Theme.isConnectedEffect)
|
if (Theme.isConnectedEffect)
|
||||||
return 0;
|
return 0;
|
||||||
if (Theme.isDirectionalEffect)
|
|
||||||
return 0;
|
|
||||||
if (animationType === "slide")
|
if (animationType === "slide")
|
||||||
return 30;
|
return 30;
|
||||||
if (Theme.isDirectionalEffect)
|
if (Theme.isDirectionalEffect)
|
||||||
|
|||||||
@@ -60,9 +60,31 @@ Item {
|
|||||||
impl.item.toggleWithMode(mode);
|
impl.item.toggleWithMode(mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
readonly property var _desiredBackend: SettingsData.connectedFrameModeActive ? connectedComp : standaloneComp
|
||||||
|
property var _resolvedBackend: null
|
||||||
|
|
||||||
|
Component.onCompleted: _resolvedBackend = _desiredBackend
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: SettingsData
|
||||||
|
function onConnectedFrameModeActiveChanged() {
|
||||||
|
root._maybeResolveBackend();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Defer Loader source-component swap until impl is fully closed; avoids
|
||||||
|
// tearing down the launcher mid-animation when frame mode is toggled.
|
||||||
|
function _maybeResolveBackend() {
|
||||||
|
if (_resolvedBackend === _desiredBackend)
|
||||||
|
return;
|
||||||
|
if (impl.item && (impl.item.spotlightOpen || impl.item.isClosing))
|
||||||
|
return;
|
||||||
|
_resolvedBackend = _desiredBackend;
|
||||||
|
}
|
||||||
|
|
||||||
Loader {
|
Loader {
|
||||||
id: impl
|
id: impl
|
||||||
sourceComponent: SettingsData.connectedFrameModeActive ? connectedComp : standaloneComp
|
sourceComponent: root._resolvedBackend
|
||||||
onItemChanged: if (item)
|
onItemChanged: if (item)
|
||||||
root._wireBackend(item)
|
root._wireBackend(item)
|
||||||
}
|
}
|
||||||
@@ -81,6 +103,15 @@ Item {
|
|||||||
if (!it)
|
if (!it)
|
||||||
return;
|
return;
|
||||||
it.modalHandle = root;
|
it.modalHandle = root;
|
||||||
it.dialogClosed.connect(root.dialogClosed);
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: impl.item
|
||||||
|
ignoreUnknownSignals: true
|
||||||
|
|
||||||
|
function onDialogClosed() {
|
||||||
|
root.dialogClosed();
|
||||||
|
root._maybeResolveBackend();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -191,7 +191,6 @@ Item {
|
|||||||
|
|
||||||
signal dialogClosed
|
signal dialogClosed
|
||||||
|
|
||||||
// ─── Connected chrome sync ────────────────────────────────────────────────
|
|
||||||
property string _chromeClaimId: ""
|
property string _chromeClaimId: ""
|
||||||
property bool _fullSyncPending: false
|
property bool _fullSyncPending: false
|
||||||
|
|
||||||
@@ -558,7 +557,6 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Background window: fullscreen, handles darkening + click-to-dismiss ──
|
|
||||||
PanelWindow {
|
PanelWindow {
|
||||||
id: backgroundWindow
|
id: backgroundWindow
|
||||||
visible: false
|
visible: false
|
||||||
@@ -616,7 +614,6 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Content window: SMALL, positioned with margins — only renders the modal area ──
|
|
||||||
PanelWindow {
|
PanelWindow {
|
||||||
id: contentWindow
|
id: contentWindow
|
||||||
visible: false
|
visible: false
|
||||||
|
|||||||
@@ -145,7 +145,6 @@ Variants {
|
|||||||
return Math.round(v * _dpr) / _dpr;
|
return Math.round(v * _dpr) / _dpr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─── ConnectedModeState sync ────────────────────────────────────────
|
|
||||||
// Dock window origin in screen-relative coordinates (FrameWindow space).
|
// Dock window origin in screen-relative coordinates (FrameWindow space).
|
||||||
function _dockWindowOriginX() {
|
function _dockWindowOriginX() {
|
||||||
if (!dock.isVertical)
|
if (!dock.isVertical)
|
||||||
|
|||||||
@@ -49,7 +49,6 @@ PanelWindow {
|
|||||||
readonly property var _notifState: ConnectedModeState.notificationStates[win._screenName] || ConnectedModeState.emptyNotificationState
|
readonly property var _notifState: ConnectedModeState.notificationStates[win._screenName] || ConnectedModeState.emptyNotificationState
|
||||||
readonly property var _modalState: ConnectedModeState.modalStates[win._screenName] || ConnectedModeState.emptyModalState
|
readonly property var _modalState: ConnectedModeState.modalStates[win._screenName] || ConnectedModeState.emptyModalState
|
||||||
|
|
||||||
// ─── Connected chrome convenience properties ──────────────────────────────
|
|
||||||
readonly property bool _connectedActive: win._frameActive && SettingsData.connectedFrameModeActive
|
readonly property bool _connectedActive: win._frameActive && SettingsData.connectedFrameModeActive
|
||||||
readonly property string _barSide: {
|
readonly property string _barSide: {
|
||||||
const edges = win.barEdges;
|
const edges = win.barEdges;
|
||||||
@@ -780,7 +779,6 @@ PanelWindow {
|
|||||||
radius: win._blurCutoutRadius
|
radius: win._blurCutoutRadius
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Connected popout blur regions ──
|
|
||||||
Region {
|
Region {
|
||||||
item: _popoutBodyBlurAnchor
|
item: _popoutBodyBlurAnchor
|
||||||
radius: win._surfaceRadius
|
radius: win._surfaceRadius
|
||||||
@@ -827,7 +825,6 @@ PanelWindow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Connected dock blur regions ──
|
|
||||||
Region {
|
Region {
|
||||||
item: _dockBodyBlurAnchor
|
item: _dockBodyBlurAnchor
|
||||||
radius: win._dockBodyBlurRadius()
|
radius: win._dockBodyBlurRadius()
|
||||||
@@ -898,7 +895,6 @@ PanelWindow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Connected modal blur regions ──
|
|
||||||
Region {
|
Region {
|
||||||
item: _modalBodyBlurAnchor
|
item: _modalBodyBlurAnchor
|
||||||
radius: win._surfaceRadius
|
radius: win._surfaceRadius
|
||||||
@@ -946,8 +942,6 @@ PanelWindow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─── Connector position helpers ────────────────────────────────────────
|
|
||||||
|
|
||||||
function _dockBodyBlurRadius() {
|
function _dockBodyBlurRadius() {
|
||||||
return _dockBodyBlurAnchor._active ? Math.max(0, Math.min(win._surfaceRadius, _dockBodyBlurAnchor.width / 2, _dockBodyBlurAnchor.height / 2)) : win._surfaceRadius;
|
return _dockBodyBlurAnchor._active ? Math.max(0, Math.min(win._surfaceRadius, _dockBodyBlurAnchor.width / 2, _dockBodyBlurAnchor.height / 2)) : win._surfaceRadius;
|
||||||
}
|
}
|
||||||
@@ -1219,8 +1213,6 @@ PanelWindow {
|
|||||||
return (arcCorner === "topLeft" || arcCorner === "topRight") ? connectorY - r : connectorY + connectorHeight - r;
|
return (arcCorner === "topLeft" || arcCorner === "topRight") ? connectorY - r : connectorY + connectorHeight - r;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─── Blur build / teardown ────────────────────────────────────────────────
|
|
||||||
|
|
||||||
function _buildBlur() {
|
function _buildBlur() {
|
||||||
try {
|
try {
|
||||||
if (!BlurService.enabled || !SettingsData.frameBlurEnabled || !win._frameActive || !win.visible) {
|
if (!BlurService.enabled || !SettingsData.frameBlurEnabled || !win._frameActive || !win.visible) {
|
||||||
@@ -1297,8 +1289,6 @@ PanelWindow {
|
|||||||
Component.onCompleted: Qt.callLater(() => win._buildBlur())
|
Component.onCompleted: Qt.callLater(() => win._buildBlur())
|
||||||
Component.onDestruction: win._teardownBlur()
|
Component.onDestruction: win._teardownBlur()
|
||||||
|
|
||||||
// ─── Frame border ─────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
FrameBorder {
|
FrameBorder {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
visible: win._frameActive && !win._connectedActive
|
visible: win._frameActive && !win._connectedActive
|
||||||
@@ -1309,8 +1299,6 @@ PanelWindow {
|
|||||||
cutoutRadius: win.cutoutRadius
|
cutoutRadius: win.cutoutRadius
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─── Connected chrome fills ───────────────────────────────────────────────
|
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: _connectedSurfaceLayer
|
id: _connectedSurfaceLayer
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|||||||
@@ -130,8 +130,8 @@ Scope {
|
|||||||
MouseArea {
|
MouseArea {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
onClicked: mouse => {
|
onClicked: mouse => {
|
||||||
const localPos = mapToItem(contentContainer, mouse.x, mouse.y);
|
const localPos = mapToItem(contentAnchor, mouse.x, mouse.y);
|
||||||
if (localPos.x < 0 || localPos.x > contentContainer.width || localPos.y < 0 || localPos.y > contentContainer.height) {
|
if (localPos.x < 0 || localPos.x > contentAnchor.width || localPos.y < 0 || localPos.y > contentAnchor.height) {
|
||||||
overviewScope.overviewOpen = false;
|
overviewScope.overviewOpen = false;
|
||||||
closeTimer.restart();
|
closeTimer.restart();
|
||||||
}
|
}
|
||||||
@@ -140,47 +140,24 @@ Scope {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: contentContainer
|
id: contentAnchor
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.topMargin: 100
|
anchors.topMargin: 100
|
||||||
width: childrenRect.width
|
width: contentContainer.width
|
||||||
height: childrenRect.height
|
height: contentContainer.height
|
||||||
|
|
||||||
opacity: overviewScope.overviewOpen ? 1 : 0
|
Item {
|
||||||
transform: [scaleTransform, motionTransform]
|
id: contentContainer
|
||||||
|
width: childrenRect.width
|
||||||
|
height: childrenRect.height
|
||||||
|
transformOrigin: Item.Center
|
||||||
|
|
||||||
Scale {
|
opacity: overviewScope.overviewOpen ? 1 : 0
|
||||||
id: scaleTransform
|
scale: overviewScope.overviewOpen ? 1 : Theme.effectScaleCollapsed
|
||||||
origin.x: contentContainer.width / 2
|
|
||||||
origin.y: contentContainer.height / 2
|
|
||||||
xScale: overviewScope.overviewOpen ? 1 : Theme.effectScaleCollapsed
|
|
||||||
yScale: overviewScope.overviewOpen ? 1 : Theme.effectScaleCollapsed
|
|
||||||
|
|
||||||
Behavior on xScale {
|
|
||||||
NumberAnimation {
|
|
||||||
duration: Theme.variantDuration(Theme.expressiveDurations.expressiveDefaultSpatial, overviewScope.overviewOpen)
|
|
||||||
easing.type: Easing.BezierSpline
|
|
||||||
easing.bezierCurve: overviewScope.overviewOpen ? Theme.variantModalEnterCurve : Theme.variantModalExitCurve
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Behavior on yScale {
|
|
||||||
NumberAnimation {
|
|
||||||
duration: Theme.variantDuration(Theme.expressiveDurations.expressiveDefaultSpatial, overviewScope.overviewOpen)
|
|
||||||
easing.type: Easing.BezierSpline
|
|
||||||
easing.bezierCurve: overviewScope.overviewOpen ? Theme.variantModalEnterCurve : Theme.variantModalExitCurve
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Translate {
|
|
||||||
id: motionTransform
|
|
||||||
x: {
|
x: {
|
||||||
if (overviewScope.overviewOpen)
|
if (overviewScope.overviewOpen)
|
||||||
return 0;
|
return 0;
|
||||||
if (Theme.isDirectionalEffect)
|
|
||||||
return 0;
|
|
||||||
if (Theme.isDepthEffect)
|
if (Theme.isDepthEffect)
|
||||||
return Theme.effectAnimOffset * 0.25;
|
return Theme.effectAnimOffset * 0.25;
|
||||||
return 0;
|
return 0;
|
||||||
@@ -195,8 +172,24 @@ Scope {
|
|||||||
return Theme.effectAnimOffset;
|
return Theme.effectAnimOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Behavior on opacity {
|
||||||
|
OpacityAnimator {
|
||||||
|
duration: Theme.variantDuration(Theme.expressiveDurations.expressiveDefaultSpatial, overviewScope.overviewOpen)
|
||||||
|
easing.type: Easing.BezierSpline
|
||||||
|
easing.bezierCurve: overviewScope.overviewOpen ? Theme.variantModalEnterCurve : Theme.variantModalExitCurve
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Behavior on scale {
|
||||||
|
ScaleAnimator {
|
||||||
|
duration: Theme.variantDuration(Theme.expressiveDurations.expressiveDefaultSpatial, overviewScope.overviewOpen)
|
||||||
|
easing.type: Easing.BezierSpline
|
||||||
|
easing.bezierCurve: overviewScope.overviewOpen ? Theme.variantModalEnterCurve : Theme.variantModalExitCurve
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Behavior on x {
|
Behavior on x {
|
||||||
NumberAnimation {
|
XAnimator {
|
||||||
duration: Theme.variantDuration(Theme.expressiveDurations.expressiveDefaultSpatial, overviewScope.overviewOpen)
|
duration: Theme.variantDuration(Theme.expressiveDurations.expressiveDefaultSpatial, overviewScope.overviewOpen)
|
||||||
easing.type: Easing.BezierSpline
|
easing.type: Easing.BezierSpline
|
||||||
easing.bezierCurve: overviewScope.overviewOpen ? Theme.variantModalEnterCurve : Theme.variantModalExitCurve
|
easing.bezierCurve: overviewScope.overviewOpen ? Theme.variantModalEnterCurve : Theme.variantModalExitCurve
|
||||||
@@ -204,30 +197,22 @@ Scope {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Behavior on y {
|
Behavior on y {
|
||||||
NumberAnimation {
|
YAnimator {
|
||||||
duration: Theme.variantDuration(Theme.expressiveDurations.expressiveDefaultSpatial, overviewScope.overviewOpen)
|
duration: Theme.variantDuration(Theme.expressiveDurations.expressiveDefaultSpatial, overviewScope.overviewOpen)
|
||||||
easing.type: Easing.BezierSpline
|
easing.type: Easing.BezierSpline
|
||||||
easing.bezierCurve: overviewScope.overviewOpen ? Theme.variantModalEnterCurve : Theme.variantModalExitCurve
|
easing.bezierCurve: overviewScope.overviewOpen ? Theme.variantModalEnterCurve : Theme.variantModalExitCurve
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Behavior on opacity {
|
Loader {
|
||||||
OpacityAnimator {
|
id: overviewLoader
|
||||||
duration: Theme.variantDuration(Theme.expressiveDurations.expressiveDefaultSpatial, overviewScope.overviewOpen)
|
active: overviewScope.overviewOpen
|
||||||
easing.type: Easing.BezierSpline
|
asynchronous: false
|
||||||
easing.bezierCurve: overviewScope.overviewOpen ? Theme.variantModalEnterCurve : Theme.variantModalExitCurve
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Loader {
|
sourceComponent: OverviewWidget {
|
||||||
id: overviewLoader
|
panelWindow: root
|
||||||
active: overviewScope.overviewOpen
|
overviewOpen: overviewScope.overviewOpen
|
||||||
asynchronous: false
|
}
|
||||||
|
|
||||||
sourceComponent: OverviewWidget {
|
|
||||||
panelWindow: root
|
|
||||||
overviewOpen: overviewScope.overviewOpen
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ Item {
|
|||||||
|
|
||||||
property color fillColor: "transparent"
|
property color fillColor: "transparent"
|
||||||
|
|
||||||
// ── Derived layout ──
|
|
||||||
readonly property bool _horiz: barSide === "top" || barSide === "bottom"
|
readonly property bool _horiz: barSide === "top" || barSide === "bottom"
|
||||||
readonly property real _sc: Math.max(0, startConnectorRadius)
|
readonly property real _sc: Math.max(0, startConnectorRadius)
|
||||||
readonly property real _ec: Math.max(0, endConnectorRadius)
|
readonly property real _ec: Math.max(0, endConnectorRadius)
|
||||||
|
|||||||
@@ -75,6 +75,21 @@ Item {
|
|||||||
readonly property real barWidth: impl.item ? impl.item.barWidth : 0
|
readonly property real barWidth: impl.item ? impl.item.barWidth : 0
|
||||||
readonly property real barHeight: impl.item ? impl.item.barHeight : 0
|
readonly property real barHeight: impl.item ? impl.item.barHeight : 0
|
||||||
readonly property bool useConnectedBackend: SettingsData.connectedFrameModeActive && !!screen && SettingsData.isScreenInPreferences(screen, SettingsData.frameScreenPreferences)
|
readonly property bool useConnectedBackend: SettingsData.connectedFrameModeActive && !!screen && SettingsData.isScreenInPreferences(screen, SettingsData.frameScreenPreferences)
|
||||||
|
readonly property var _desiredBackend: useConnectedBackend ? connectedComp : standaloneComp
|
||||||
|
property var _resolvedBackend: null
|
||||||
|
|
||||||
|
onUseConnectedBackendChanged: _maybeResolveBackend()
|
||||||
|
Component.onCompleted: _resolvedBackend = _desiredBackend
|
||||||
|
|
||||||
|
// Defer Loader source-component swap until impl is fully closed; avoids
|
||||||
|
// tearing down a popout mid-animation when frame mode is toggled.
|
||||||
|
function _maybeResolveBackend() {
|
||||||
|
if (_resolvedBackend === _desiredBackend)
|
||||||
|
return;
|
||||||
|
if (impl.item && (impl.item.shouldBeVisible || impl.item.isClosing))
|
||||||
|
return;
|
||||||
|
_resolvedBackend = _desiredBackend;
|
||||||
|
}
|
||||||
|
|
||||||
function open() {
|
function open() {
|
||||||
if (impl.item)
|
if (impl.item)
|
||||||
@@ -121,7 +136,7 @@ Item {
|
|||||||
Loader {
|
Loader {
|
||||||
id: impl
|
id: impl
|
||||||
active: root.screen !== null
|
active: root.screen !== null
|
||||||
sourceComponent: root.useConnectedBackend ? connectedComp : standaloneComp
|
sourceComponent: root._resolvedBackend
|
||||||
onItemChanged: if (item)
|
onItemChanged: if (item)
|
||||||
root._wireBackend(item)
|
root._wireBackend(item)
|
||||||
}
|
}
|
||||||
@@ -207,6 +222,7 @@ Item {
|
|||||||
|
|
||||||
function onPopoutClosed() {
|
function onPopoutClosed() {
|
||||||
root.popoutClosed();
|
root.popoutClosed();
|
||||||
|
root._maybeResolveBackend();
|
||||||
}
|
}
|
||||||
|
|
||||||
function onBackgroundClicked() {
|
function onBackgroundClicked() {
|
||||||
|
|||||||
@@ -178,15 +178,40 @@ Item {
|
|||||||
setBarContext(pos, bottomGap);
|
setBarContext(pos, bottomGap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Briefly forces backgroundWindow.updatesEnabled true while the surface
|
||||||
|
// body changes, so the contentHoleRect mask carve-out commits to the
|
||||||
|
// compositor — otherwise the input region stays stuck at the popup's
|
||||||
|
// initial size and clicks in any newly-grown area dismiss the popup.
|
||||||
|
// Cleared by the frameSwapped Connections below as soon as the dirty
|
||||||
|
// frame ships, so the bg window goes back to skipping buffer updates.
|
||||||
|
property bool _bgCommitWindow: false
|
||||||
|
|
||||||
function _setSurfaceGeometry(bodyX, bodyY, bodyW, bodyH) {
|
function _setSurfaceGeometry(bodyX, bodyY, bodyW, bodyH) {
|
||||||
_surfaceBodyX = Theme.snap(bodyX, dpr);
|
const newX = Theme.snap(bodyX, dpr);
|
||||||
_surfaceBodyY = Theme.snap(bodyY, dpr);
|
const newY = Theme.snap(bodyY, dpr);
|
||||||
_surfaceBodyW = Theme.snap(bodyW, dpr);
|
const newW = Theme.snap(bodyW, dpr);
|
||||||
_surfaceBodyH = Theme.snap(bodyH, dpr);
|
const newH = Theme.snap(bodyH, dpr);
|
||||||
|
const changed = newX !== _surfaceBodyX || newY !== _surfaceBodyY || newW !== _surfaceBodyW || newH !== _surfaceBodyH;
|
||||||
|
_surfaceBodyX = newX;
|
||||||
|
_surfaceBodyY = newY;
|
||||||
|
_surfaceBodyW = newW;
|
||||||
|
_surfaceBodyH = newH;
|
||||||
_surfaceMarginLeft = _surfaceBodyX - shadowBuffer;
|
_surfaceMarginLeft = _surfaceBodyX - shadowBuffer;
|
||||||
_surfaceMarginTop = _surfaceBodyY - shadowBuffer;
|
_surfaceMarginTop = _surfaceBodyY - shadowBuffer;
|
||||||
_surfaceW = _surfaceBodyW + shadowBuffer * 2;
|
_surfaceW = _surfaceBodyW + shadowBuffer * 2;
|
||||||
_surfaceH = _surfaceBodyH + shadowBuffer * 2;
|
_surfaceH = _surfaceBodyH + shadowBuffer * 2;
|
||||||
|
if (changed && backgroundWindow.visible) {
|
||||||
|
_bgCommitWindow = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: backgroundWindow
|
||||||
|
ignoreUnknownSignals: true
|
||||||
|
function onFrameSwapped() {
|
||||||
|
if (root._bgCommitWindow)
|
||||||
|
root._bgCommitWindow = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function _setSettledSurfaceGeometry() {
|
function _setSettledSurfaceGeometry() {
|
||||||
@@ -455,9 +480,10 @@ Item {
|
|||||||
screen: root.screen
|
screen: root.screen
|
||||||
visible: false
|
visible: false
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
// When there's no overlay to render, skip buffer updates. Re-evaluates if
|
// Skip buffer updates when there's nothing to render. Briefly flipped
|
||||||
// overlayContent is assigned later (e.g., via a dispatcher forwarding it).
|
// true via _bgCommitWindow when _surfaceBodyW/H changes so the
|
||||||
updatesEnabled: root.overlayContent !== null
|
// contentHoleRect mask carve-out actually commits to the compositor.
|
||||||
|
updatesEnabled: root.overlayContent !== null || root._bgCommitWindow
|
||||||
|
|
||||||
WlrLayershell.namespace: root.layerNamespace + ":background"
|
WlrLayershell.namespace: root.layerNamespace + ":background"
|
||||||
WlrLayershell.layer: WlrLayershell.Top
|
WlrLayershell.layer: WlrLayershell.Top
|
||||||
|
|||||||
Reference in New Issue
Block a user