1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-08-07 14:08:29 -04:00

refactor(compositor): reduce unnecessary UI updates

- Defer updates when window state hasn't actually changed
- Cache frame-blocked state per screen instead of recalculating constantly
- keep popouts cache so reopening them is instant & clean up otherwise
This commit is contained in:
purian23
2026-07-02 21:42:20 -04:00
parent 8b79d1dad3
commit 0c99e4b8d1
6 changed files with 218 additions and 77 deletions
+99 -5
View File
@@ -135,11 +135,34 @@ Singleton {
repeat: false repeat: false
onTriggered: { onTriggered: {
_sortScheduled = false; _sortScheduled = false;
sortedToplevels = computeSortedToplevels(); const next = computeSortedToplevels();
// Avoid reassigning (and invalidating bindings) when contents are equivalent.
if (!_toplevelListEquivalent(next, sortedToplevels))
sortedToplevels = next;
_recomputeFrameBlocked();
toplevelsChanged(); toplevelsChanged();
} }
} }
function _toplevelListEquivalent(a, b) {
if (!a || !b || a.length !== b.length)
return false;
for (let i = 0; i < a.length; i++) {
const x = a[i];
const y = b[i];
if (x === y)
continue;
if (!x || !y)
return false;
// Only niri's enriched snapshots support value comparison.
if (x.niriWindowId === undefined || y.niriWindowId === undefined)
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)
return false;
}
return true;
}
function scheduleSort() { function scheduleSort() {
if (_sortScheduled) if (_sortScheduled)
return; return;
@@ -164,8 +187,10 @@ Singleton {
if (event.name === "workspace" || event.name === "workspacev2" || event.name === "focusedmon" || event.name === "focusedmonv2" || event.name === "activespecial") if (event.name === "workspace" || event.name === "workspacev2" || event.name === "focusedmon" || event.name === "focusedmonv2" || event.name === "activespecial")
Hyprland.refreshMonitors(); Hyprland.refreshMonitors();
} catch (e) {} } catch (e) {}
if (event.name === "activespecial") if (event.name === "activespecial") {
root.updateHyprlandVisibleSpecialWorkspaces(event); root.updateHyprlandVisibleSpecialWorkspaces(event);
root._recomputeFrameBlocked();
}
root.scheduleSort(); root.scheduleSort();
} }
} }
@@ -175,6 +200,10 @@ Singleton {
function onWindowsChanged() { function onWindowsChanged() {
root.scheduleSort(); root.scheduleSort();
} }
// Workspace switches affect the fullscreen check's active workspace.
function onAllWorkspacesChanged() {
root._recomputeFrameBlocked();
}
} }
Component.onCompleted: { Component.onCompleted: {
@@ -182,6 +211,7 @@ Singleton {
detectCompositor(); detectCompositor();
updateHyprlandVisibleSpecialWorkspaces(null); updateHyprlandVisibleSpecialWorkspaces(null);
scheduleSort(); scheduleSort();
_recomputeFrameBlocked();
Qt.callLater(() => { Qt.callLater(() => {
NiriService.generateNiriLayoutConfig(); NiriService.generateNiriLayoutConfig();
HyprlandService.generateLayoutConfig(); HyprlandService.generateLayoutConfig();
@@ -592,10 +622,74 @@ Singleton {
return false; return false;
} }
function connectedFrameBlockedOnScreen(screenOrName) { // Per-screen cache for connectedFrameBlockedOnScreen to avoid recomputing on every consumer binding.
if (hasFullscreenToplevelOnScreen(screenOrName)) property var frameBlockedByScreen: ({})
function _computeConnectedFrameBlocked(screenName) {
if (hasFullscreenToplevelOnScreen(screenName))
return true; return true;
return hyprlandSpecialWorkspaceBlocksConnectedFrame(screenOrName); return hyprlandSpecialWorkspaceBlocksConnectedFrame(screenName);
}
function _recomputeFrameBlocked() {
const screens = Quickshell.screens || [];
const next = {};
let changed = false;
for (let i = 0; i < screens.length; i++) {
const name = screens[i]?.name;
if (!name)
continue;
const blocked = _computeConnectedFrameBlocked(name);
next[name] = blocked;
if (frameBlockedByScreen[name] !== blocked)
changed = true;
}
if (!changed) {
for (const name in frameBlockedByScreen) {
if (!(name in next)) {
changed = true;
break;
}
}
}
if (changed)
frameBlockedByScreen = next;
}
function connectedFrameBlockedOnScreen(screenOrName) {
const screenName = _screenName(screenOrName);
if (!screenName)
return false;
const cached = frameBlockedByScreen[screenName];
if (cached !== undefined)
return cached;
return _computeConnectedFrameBlocked(screenName);
}
Connections {
target: ToplevelManager
function onActiveToplevelChanged() {
root._recomputeFrameBlocked();
}
}
// Track active toplevel's fullscreen/activated state directly (no per-property signals from ToplevelManager).
Connections {
target: ToplevelManager.activeToplevel
ignoreUnknownSignals: true
function onFullscreenChanged() {
root._recomputeFrameBlocked();
}
function onActivatedChanged() {
root._recomputeFrameBlocked();
}
}
Connections {
target: Quickshell
function onScreensChanged() {
root._recomputeFrameBlocked();
}
} }
function _screenForName(screenOrName) { function _screenForName(screenOrName) {
+31 -23
View File
@@ -435,25 +435,30 @@ Singleton {
function handleWindowFocusChanged(data) { function handleWindowFocusChanged(data) {
const focusedWindowId = data.id; const focusedWindowId = data.id;
// Only clone windows whose focus flag changes; skip reassignment if nothing changed.
let focusedWindow = null; let focusedWindow = null;
const updatedWindows = []; let changed = false;
const updatedWindows = new Array(windows.length);
for (var i = 0; i < windows.length; i++) { for (var i = 0; i < windows.length; i++) {
const w = windows[i]; const w = windows[i];
const updatedWindow = {}; const isFocused = w.id === focusedWindowId;
if (!!w.is_focused === isFocused) {
for (let prop in w) { updatedWindows[i] = w;
updatedWindow[prop] = w[prop]; if (isFocused)
focusedWindow = w;
continue;
} }
const updatedWindow = Object.assign({}, w, {
updatedWindow.is_focused = (w.id === focusedWindowId); "is_focused": isFocused
if (updatedWindow.is_focused) { });
if (isFocused)
focusedWindow = updatedWindow; focusedWindow = updatedWindow;
updatedWindows[i] = updatedWindow;
changed = true;
} }
updatedWindows.push(updatedWindow); if (changed)
}
windows = updatedWindows; windows = updatedWindows;
if (focusedWindow) { if (focusedWindow) {
@@ -490,25 +495,28 @@ Singleton {
setWorkspaces(updatedWorkspaces); setWorkspaces(updatedWorkspaces);
} }
const updatedWindows = []; let changed = false;
const updatedWindows = new Array(windows.length);
for (var i = 0; i < windows.length; i++) { for (var i = 0; i < windows.length; i++) {
const w = windows[i]; const w = windows[i];
const updatedWindow = {}; let isFocused;
for (let prop in w) {
updatedWindow[prop] = w[prop];
}
if (data.active_window_id !== null && data.active_window_id !== undefined) { if (data.active_window_id !== null && data.active_window_id !== undefined) {
updatedWindow.is_focused = (w.id == data.active_window_id); isFocused = (w.id == data.active_window_id);
} else { } else {
updatedWindow.is_focused = w.workspace_id == data.workspace_id ? false : w.is_focused; isFocused = w.workspace_id == data.workspace_id ? false : !!w.is_focused;
} }
if (!!w.is_focused === isFocused) {
updatedWindows.push(updatedWindow); updatedWindows[i] = w;
continue;
}
updatedWindows[i] = Object.assign({}, w, {
"is_focused": isFocused
});
changed = true;
} }
if (changed)
windows = updatedWindows; windows = updatedWindows;
} }
+76 -38
View File
@@ -58,6 +58,65 @@ Singleton {
property string pendingThemeInstall: "" property string pendingThemeInstall: ""
property string pendingPluginInstall: "" property string pendingPluginInstall: ""
// Deferred unload: keep popouts warm while the session is active and reclaim them on lock/monitors-off.
property var _pendingUnloads: ({})
Connections {
target: SessionService
function onSessionLocked() {
root._flushPendingUnloads();
}
}
Connections {
target: IdleService
function onMonitorsOffChanged() {
if (IdleService.monitorsOff)
root._flushPendingUnloads();
}
}
function _scheduleUnload(key) {
_pendingUnloads[key] = true;
}
function _flushPendingUnloads() {
const keys = Object.keys(_pendingUnloads);
_pendingUnloads = ({});
for (let i = 0; i < keys.length; i++) {
const unload = _deferredUnloaders[keys[i]];
if (unload)
unload();
}
}
function _popoutStillPresented(popout) {
return !!popout && (popout.shouldBeVisible === true || popout.isClosing === true);
}
function _unloadPopoutNow(popoutName, loaderName) {
const loader = root[loaderName];
if (!loader)
return;
if (_popoutStillPresented(root[popoutName]))
return;
root[popoutName] = null;
loader.active = false;
}
readonly property var _deferredUnloaders: ({
"controlCenter": () => _unloadPopoutNow("controlCenterPopout", "controlCenterLoader"),
"notificationCenter": () => _unloadPopoutNow("notificationCenterPopout", "notificationCenterLoader"),
"appDrawer": () => _unloadPopoutNow("appDrawerPopout", "appDrawerLoader"),
"processList": () => _unloadPopoutNow("processListPopout", "processListPopoutLoader"),
"battery": () => _unloadPopoutNow("batteryPopout", "batteryPopoutLoader"),
"vpn": () => _unloadPopoutNow("vpnPopout", "vpnPopoutLoader"),
"systemUpdate": () => _unloadPopoutNow("systemUpdatePopout", "systemUpdateLoader"),
"layout": () => _unloadPopoutNow("layoutPopout", "layoutPopoutLoader"),
"clipboardHistory": () => _unloadPopoutNow("clipboardHistoryPopout", "clipboardHistoryPopoutLoader"),
"settings": () => _unloadSettingsNow()
})
function setPosition(popout, x, y, width, section, screen) { function setPosition(popout, x, y, width, section, screen) {
if (popout && popout.setTriggerPosition && arguments.length >= 6) { if (popout && popout.setTriggerPosition && arguments.length >= 6) {
popout.setTriggerPosition(x, y, width, section, screen); popout.setTriggerPosition(x, y, width, section, screen);
@@ -76,10 +135,7 @@ Singleton {
} }
function unloadControlCenter() { function unloadControlCenter() {
if (!controlCenterLoader) _scheduleUnload("controlCenter");
return;
controlCenterPopout = null;
controlCenterLoader.active = false;
} }
function toggleControlCenter(x, y, width, section, screen) { function toggleControlCenter(x, y, width, section, screen) {
@@ -101,10 +157,7 @@ Singleton {
} }
function unloadNotificationCenter() { function unloadNotificationCenter() {
if (!notificationCenterLoader) _scheduleUnload("notificationCenter");
return;
notificationCenterPopout = null;
notificationCenterLoader.active = false;
} }
function toggleNotificationCenter(x, y, width, section, screen) { function toggleNotificationCenter(x, y, width, section, screen) {
@@ -126,10 +179,7 @@ Singleton {
} }
function unloadAppDrawer() { function unloadAppDrawer() {
if (!appDrawerLoader) _scheduleUnload("appDrawer");
return;
appDrawerPopout = null;
appDrawerLoader.active = false;
} }
function toggleAppDrawer(x, y, width, section, screen) { function toggleAppDrawer(x, y, width, section, screen) {
@@ -151,10 +201,7 @@ Singleton {
} }
function unloadProcessListPopout() { function unloadProcessListPopout() {
if (!processListPopoutLoader) _scheduleUnload("processList");
return;
processListPopout = null;
processListPopoutLoader.active = false;
} }
function toggleProcessList(x, y, width, section, screen) { function toggleProcessList(x, y, width, section, screen) {
@@ -268,10 +315,7 @@ Singleton {
} }
function unloadBattery() { function unloadBattery() {
if (!batteryPopoutLoader) _scheduleUnload("battery");
return;
batteryPopout = null;
batteryPopoutLoader.active = false;
} }
function toggleBattery(x, y, width, section, screen) { function toggleBattery(x, y, width, section, screen) {
@@ -293,10 +337,7 @@ Singleton {
} }
function unloadVpn() { function unloadVpn() {
if (!vpnPopoutLoader) _scheduleUnload("vpn");
return;
vpnPopout = null;
vpnPopoutLoader.active = false;
} }
function toggleVpn(x, y, width, section, screen) { function toggleVpn(x, y, width, section, screen) {
@@ -319,10 +360,7 @@ Singleton {
} }
function unloadSystemUpdate() { function unloadSystemUpdate() {
if (!systemUpdateLoader) _scheduleUnload("systemUpdate");
return;
systemUpdatePopout = null;
systemUpdateLoader.active = false;
} }
function toggleSystemUpdate(x, y, width, section, screen) { function toggleSystemUpdate(x, y, width, section, screen) {
@@ -441,11 +479,17 @@ Singleton {
} }
function unloadSettings() { function unloadSettings() {
if (settingsModalLoader) { _scheduleUnload("settings");
}
function _unloadSettingsNow() {
if (!settingsModalLoader)
return;
if (settingsModal && settingsModal.visible)
return;
settingsModal = null; settingsModal = null;
settingsModalLoader.active = false; settingsModalLoader.active = false;
} }
}
function _onSettingsModalLoaded() { function _onSettingsModalLoaded() {
if (_settingsWantsOpen) { if (_settingsWantsOpen) {
@@ -484,17 +528,11 @@ Singleton {
} }
function unloadClipboardHistoryPopout() { function unloadClipboardHistoryPopout() {
if (!clipboardHistoryPopoutLoader) _scheduleUnload("clipboardHistory");
return;
clipboardHistoryPopout = null;
clipboardHistoryPopoutLoader.active = false;
} }
function unloadLayoutPopout() { function unloadLayoutPopout() {
if (!layoutPopoutLoader) _scheduleUnload("layout");
return;
layoutPopout = null;
layoutPopoutLoader.active = false;
} }
property bool _dankLauncherV2WantsOpen: false property bool _dankLauncherV2WantsOpen: false
+1 -6
View File
@@ -134,12 +134,7 @@ Item {
} }
} }
Connections { // Backend re-resolution on toplevel activity is covered by CompositorService.frameBlockedByScreen.
target: CompositorService
function onToplevelsChanged() {
root._maybeResolveBackend();
}
}
function _usesConnectedBackendForScreen(targetScreen) { function _usesConnectedBackendForScreen(targetScreen) {
return CompositorService.usesConnectedFrameChromeForScreen(targetScreen); return CompositorService.usesConnectedFrameChromeForScreen(targetScreen);
+4 -1
View File
@@ -38,6 +38,7 @@ Item {
property bool contentHandlesKeys: false property bool contentHandlesKeys: false
property bool fullHeightSurface: false property bool fullHeightSurface: false
property bool _primeContent: false property bool _primeContent: false
property bool _contentWarm: 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
@@ -472,6 +473,7 @@ Item {
isClosing = false; isClosing = false;
animationsEnabled = false; animationsEnabled = false;
_primeContent = true; _primeContent = true;
_contentWarm = true;
_supersededClose = false; _supersededClose = false;
const screenChanged = _lastOpenedScreen !== null && _lastOpenedScreen !== screen; const screenChanged = _lastOpenedScreen !== null && _lastOpenedScreen !== screen;
@@ -1334,7 +1336,8 @@ Item {
Loader { Loader {
id: contentLoader id: contentLoader
anchors.fill: parent anchors.fill: parent
active: root._primeContent || shouldBeVisible || contentWindow.visible // _contentWarm keeps the tree loaded across close for fast re-open; reclaimed by PopoutService on lock/idle.
active: root._primeContent || shouldBeVisible || contentWindow.visible || root._contentWarm
asynchronous: false asynchronous: false
} }
} }
+4 -1
View File
@@ -57,6 +57,7 @@ Item {
property bool contentHandlesKeys: false property bool contentHandlesKeys: false
property bool fullHeightSurface: false property bool fullHeightSurface: false
property bool _primeContent: false property bool _primeContent: false
property bool _contentWarm: false
property bool _resizeActive: false property bool _resizeActive: false
property real _surfaceMarginLeft: 0 property real _surfaceMarginLeft: 0
property real _surfaceMarginTop: 0 property real _surfaceMarginTop: 0
@@ -305,6 +306,7 @@ Item {
isClosing = false; isClosing = false;
animationsEnabled = false; animationsEnabled = false;
_primeContent = true; _primeContent = true;
_contentWarm = true;
_frozenMaskX = maskX; _frozenMaskX = maskX;
_frozenMaskY = maskY; _frozenMaskY = maskY;
@@ -891,7 +893,8 @@ Item {
Loader { Loader {
id: contentLoader id: contentLoader
anchors.fill: parent anchors.fill: parent
active: root._primeContent || shouldBeVisible || contentWindow.visible // _contentWarm keeps the tree loaded across close for fast re-open; reclaimed by PopoutService on lock/idle.
active: root._primeContent || shouldBeVisible || contentWindow.visible || root._contentWarm
asynchronous: false asynchronous: false
} }
} }