1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-08-02 03:28:28 -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
onTriggered: {
_sortScheduled = false;
sortedToplevels = computeSortedToplevels();
const next = computeSortedToplevels();
// Avoid reassigning (and invalidating bindings) when contents are equivalent.
if (!_toplevelListEquivalent(next, sortedToplevels))
sortedToplevels = next;
_recomputeFrameBlocked();
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() {
if (_sortScheduled)
return;
@@ -164,8 +187,10 @@ Singleton {
if (event.name === "workspace" || event.name === "workspacev2" || event.name === "focusedmon" || event.name === "focusedmonv2" || event.name === "activespecial")
Hyprland.refreshMonitors();
} catch (e) {}
if (event.name === "activespecial")
if (event.name === "activespecial") {
root.updateHyprlandVisibleSpecialWorkspaces(event);
root._recomputeFrameBlocked();
}
root.scheduleSort();
}
}
@@ -175,6 +200,10 @@ Singleton {
function onWindowsChanged() {
root.scheduleSort();
}
// Workspace switches affect the fullscreen check's active workspace.
function onAllWorkspacesChanged() {
root._recomputeFrameBlocked();
}
}
Component.onCompleted: {
@@ -182,6 +211,7 @@ Singleton {
detectCompositor();
updateHyprlandVisibleSpecialWorkspaces(null);
scheduleSort();
_recomputeFrameBlocked();
Qt.callLater(() => {
NiriService.generateNiriLayoutConfig();
HyprlandService.generateLayoutConfig();
@@ -592,10 +622,74 @@ Singleton {
return false;
}
function connectedFrameBlockedOnScreen(screenOrName) {
if (hasFullscreenToplevelOnScreen(screenOrName))
// Per-screen cache for connectedFrameBlockedOnScreen to avoid recomputing on every consumer binding.
property var frameBlockedByScreen: ({})
function _computeConnectedFrameBlocked(screenName) {
if (hasFullscreenToplevelOnScreen(screenName))
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) {
+32 -24
View File
@@ -435,26 +435,31 @@ Singleton {
function handleWindowFocusChanged(data) {
const focusedWindowId = data.id;
// Only clone windows whose focus flag changes; skip reassignment if nothing changed.
let focusedWindow = null;
const updatedWindows = [];
let changed = false;
const updatedWindows = new Array(windows.length);
for (var i = 0; i < windows.length; i++) {
const w = windows[i];
const updatedWindow = {};
for (let prop in w) {
updatedWindow[prop] = w[prop];
const isFocused = w.id === focusedWindowId;
if (!!w.is_focused === isFocused) {
updatedWindows[i] = w;
if (isFocused)
focusedWindow = w;
continue;
}
updatedWindow.is_focused = (w.id === focusedWindowId);
if (updatedWindow.is_focused) {
const updatedWindow = Object.assign({}, w, {
"is_focused": isFocused
});
if (isFocused)
focusedWindow = updatedWindow;
}
updatedWindows.push(updatedWindow);
updatedWindows[i] = updatedWindow;
changed = true;
}
windows = updatedWindows;
if (changed)
windows = updatedWindows;
if (focusedWindow) {
const ws = root.workspaces[focusedWindow.workspace_id];
@@ -490,26 +495,29 @@ Singleton {
setWorkspaces(updatedWorkspaces);
}
const updatedWindows = [];
let changed = false;
const updatedWindows = new Array(windows.length);
for (var i = 0; i < windows.length; i++) {
const w = windows[i];
const updatedWindow = {};
for (let prop in w) {
updatedWindow[prop] = w[prop];
}
let isFocused;
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 {
updatedWindow.is_focused = w.workspace_id == data.workspace_id ? false : w.is_focused;
isFocused = w.workspace_id == data.workspace_id ? false : !!w.is_focused;
}
updatedWindows.push(updatedWindow);
if (!!w.is_focused === isFocused) {
updatedWindows[i] = w;
continue;
}
updatedWindows[i] = Object.assign({}, w, {
"is_focused": isFocused
});
changed = true;
}
windows = updatedWindows;
if (changed)
windows = updatedWindows;
}
function handleWindowsChanged(data) {
+78 -40
View File
@@ -58,6 +58,65 @@ Singleton {
property string pendingThemeInstall: ""
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) {
if (popout && popout.setTriggerPosition && arguments.length >= 6) {
popout.setTriggerPosition(x, y, width, section, screen);
@@ -76,10 +135,7 @@ Singleton {
}
function unloadControlCenter() {
if (!controlCenterLoader)
return;
controlCenterPopout = null;
controlCenterLoader.active = false;
_scheduleUnload("controlCenter");
}
function toggleControlCenter(x, y, width, section, screen) {
@@ -101,10 +157,7 @@ Singleton {
}
function unloadNotificationCenter() {
if (!notificationCenterLoader)
return;
notificationCenterPopout = null;
notificationCenterLoader.active = false;
_scheduleUnload("notificationCenter");
}
function toggleNotificationCenter(x, y, width, section, screen) {
@@ -126,10 +179,7 @@ Singleton {
}
function unloadAppDrawer() {
if (!appDrawerLoader)
return;
appDrawerPopout = null;
appDrawerLoader.active = false;
_scheduleUnload("appDrawer");
}
function toggleAppDrawer(x, y, width, section, screen) {
@@ -151,10 +201,7 @@ Singleton {
}
function unloadProcessListPopout() {
if (!processListPopoutLoader)
return;
processListPopout = null;
processListPopoutLoader.active = false;
_scheduleUnload("processList");
}
function toggleProcessList(x, y, width, section, screen) {
@@ -268,10 +315,7 @@ Singleton {
}
function unloadBattery() {
if (!batteryPopoutLoader)
return;
batteryPopout = null;
batteryPopoutLoader.active = false;
_scheduleUnload("battery");
}
function toggleBattery(x, y, width, section, screen) {
@@ -293,10 +337,7 @@ Singleton {
}
function unloadVpn() {
if (!vpnPopoutLoader)
return;
vpnPopout = null;
vpnPopoutLoader.active = false;
_scheduleUnload("vpn");
}
function toggleVpn(x, y, width, section, screen) {
@@ -319,10 +360,7 @@ Singleton {
}
function unloadSystemUpdate() {
if (!systemUpdateLoader)
return;
systemUpdatePopout = null;
systemUpdateLoader.active = false;
_scheduleUnload("systemUpdate");
}
function toggleSystemUpdate(x, y, width, section, screen) {
@@ -441,10 +479,16 @@ Singleton {
}
function unloadSettings() {
if (settingsModalLoader) {
settingsModal = null;
settingsModalLoader.active = false;
}
_scheduleUnload("settings");
}
function _unloadSettingsNow() {
if (!settingsModalLoader)
return;
if (settingsModal && settingsModal.visible)
return;
settingsModal = null;
settingsModalLoader.active = false;
}
function _onSettingsModalLoaded() {
@@ -484,17 +528,11 @@ Singleton {
}
function unloadClipboardHistoryPopout() {
if (!clipboardHistoryPopoutLoader)
return;
clipboardHistoryPopout = null;
clipboardHistoryPopoutLoader.active = false;
_scheduleUnload("clipboardHistory");
}
function unloadLayoutPopout() {
if (!layoutPopoutLoader)
return;
layoutPopout = null;
layoutPopoutLoader.active = false;
_scheduleUnload("layout");
}
property bool _dankLauncherV2WantsOpen: false
+1 -6
View File
@@ -134,12 +134,7 @@ Item {
}
}
Connections {
target: CompositorService
function onToplevelsChanged() {
root._maybeResolveBackend();
}
}
// Backend re-resolution on toplevel activity is covered by CompositorService.frameBlockedByScreen.
function _usesConnectedBackendForScreen(targetScreen) {
return CompositorService.usesConnectedFrameChromeForScreen(targetScreen);
+4 -1
View File
@@ -38,6 +38,7 @@ Item {
property bool contentHandlesKeys: false
property bool fullHeightSurface: false
property bool _primeContent: false
property bool _contentWarm: false
property bool _resizeActive: false
property real _chromeAnimTravelX: 1
property real _chromeAnimTravelY: 1
@@ -472,6 +473,7 @@ Item {
isClosing = false;
animationsEnabled = false;
_primeContent = true;
_contentWarm = true;
_supersededClose = false;
const screenChanged = _lastOpenedScreen !== null && _lastOpenedScreen !== screen;
@@ -1334,7 +1336,8 @@ Item {
Loader {
id: contentLoader
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
}
}
+4 -1
View File
@@ -57,6 +57,7 @@ Item {
property bool contentHandlesKeys: false
property bool fullHeightSurface: false
property bool _primeContent: false
property bool _contentWarm: false
property bool _resizeActive: false
property real _surfaceMarginLeft: 0
property real _surfaceMarginTop: 0
@@ -305,6 +306,7 @@ Item {
isClosing = false;
animationsEnabled = false;
_primeContent = true;
_contentWarm = true;
_frozenMaskX = maskX;
_frozenMaskY = maskY;
@@ -891,7 +893,8 @@ Item {
Loader {
id: contentLoader
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
}
}