mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-08-01 19:18:28 -04:00
plugins: prevent churn of daemon plugins by not re-creating the entire map
fixes #2860 port 1.5
This commit is contained in:
@@ -41,29 +41,6 @@ Item {
|
||||
osdSurfaceReloadTimer.restart();
|
||||
}
|
||||
|
||||
Instantiator {
|
||||
id: daemonPluginInstantiator
|
||||
asynchronous: true
|
||||
model: Object.keys(PluginService.pluginDaemonComponents)
|
||||
|
||||
delegate: Loader {
|
||||
id: daemonLoader
|
||||
property string pluginId: modelData
|
||||
sourceComponent: PluginService.pluginDaemonComponents[pluginId]
|
||||
|
||||
onLoaded: {
|
||||
if (item) {
|
||||
item.pluginService = PluginService;
|
||||
if (item.popoutService !== undefined) {
|
||||
item.popoutService = PopoutService;
|
||||
}
|
||||
item.pluginId = pluginId;
|
||||
log.info("Daemon plugin loaded:", pluginId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: blurredWallpaperBackgroundLoader
|
||||
active: SettingsData.blurredWallpaperLayer && CompositorService.isNiri
|
||||
|
||||
@@ -27,6 +27,8 @@ Singleton {
|
||||
property var knownManifests: ({})
|
||||
property var pathToPluginId: ({})
|
||||
property var pluginInstances: ({})
|
||||
property var pluginDaemonInstances: ({})
|
||||
property var _daemonSpawnQueue: []
|
||||
property var globalVars: ({})
|
||||
property var pluginLoadErrors: ({})
|
||||
|
||||
@@ -59,6 +61,16 @@ Singleton {
|
||||
onTriggered: root._flushDirtyStates()
|
||||
}
|
||||
|
||||
// Zero-interval so daemons spawn on the next event-loop tick, after any
|
||||
// deferred destroy() of a previous generation has fully unregistered its
|
||||
// IpcHandlers (quickshell#898 leaves stale registrations otherwise)
|
||||
Timer {
|
||||
id: _daemonSpawnTimer
|
||||
interval: 0
|
||||
repeat: false
|
||||
onTriggered: root._drainDaemonSpawnQueue()
|
||||
}
|
||||
|
||||
Process {
|
||||
id: directoryCheckProcess
|
||||
command: ["test", "-d", root.pluginDirectory]
|
||||
@@ -368,14 +380,21 @@ Singleton {
|
||||
const newDaemons = Object.assign({}, pluginDaemonComponents);
|
||||
const newLaunchers = Object.assign({}, pluginLauncherComponents);
|
||||
const newInstances = Object.assign({}, pluginInstances);
|
||||
const newDaemonInstances = Object.assign({}, pluginDaemonInstances);
|
||||
|
||||
const prevInstance = newInstances[pluginId];
|
||||
if (prevInstance) {
|
||||
prevInstance.destroy();
|
||||
delete newInstances[pluginId];
|
||||
}
|
||||
const prevDaemon = newDaemonInstances[pluginId];
|
||||
if (prevDaemon) {
|
||||
prevDaemon.destroy();
|
||||
delete newDaemonInstances[pluginId];
|
||||
}
|
||||
|
||||
try {
|
||||
const comps = {};
|
||||
for (const surface of surfaces) {
|
||||
let url = "file://" + componentPaths[surface];
|
||||
if (bustCache)
|
||||
@@ -386,38 +405,39 @@ Singleton {
|
||||
pluginLoadFailed(pluginId, comp.errorString());
|
||||
return false;
|
||||
}
|
||||
comps[surface] = comp;
|
||||
}
|
||||
|
||||
switch (surface) {
|
||||
case "daemon":
|
||||
newDaemons[pluginId] = comp;
|
||||
break;
|
||||
case "desktop":
|
||||
newDesktop[pluginId] = comp;
|
||||
break;
|
||||
case "launcher": {
|
||||
const instance = comp.createObject(root, {
|
||||
if (comps.launcher) {
|
||||
const instance = comps.launcher.createObject(root, {
|
||||
"pluginService": root
|
||||
});
|
||||
if (!instance) {
|
||||
log.error("failed to instantiate launcher surface:", pluginId, comp.errorString());
|
||||
pluginLoadFailed(pluginId, comp.errorString());
|
||||
log.error("failed to instantiate launcher surface:", pluginId, comps.launcher.errorString());
|
||||
pluginLoadFailed(pluginId, comps.launcher.errorString());
|
||||
return false;
|
||||
}
|
||||
newInstances[pluginId] = instance;
|
||||
newLaunchers[pluginId] = comp;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
newWidgets[pluginId] = comp;
|
||||
break;
|
||||
newLaunchers[pluginId] = comps.launcher;
|
||||
}
|
||||
|
||||
if (comps.daemon) {
|
||||
newDaemons[pluginId] = comps.daemon;
|
||||
_daemonSpawnQueue.push(pluginId);
|
||||
_daemonSpawnTimer.restart();
|
||||
}
|
||||
|
||||
if (comps.widget)
|
||||
newWidgets[pluginId] = comps.widget;
|
||||
if (comps.desktop)
|
||||
newDesktop[pluginId] = comps.desktop;
|
||||
|
||||
pluginWidgetComponents = newWidgets;
|
||||
pluginDesktopComponents = newDesktop;
|
||||
pluginDaemonComponents = newDaemons;
|
||||
pluginLauncherComponents = newLaunchers;
|
||||
pluginInstances = newInstances;
|
||||
pluginDaemonInstances = newDaemonInstances;
|
||||
|
||||
plugin.loaded = true;
|
||||
const newLoaded = Object.assign({}, loadedPlugins);
|
||||
@@ -433,6 +453,36 @@ Singleton {
|
||||
}
|
||||
}
|
||||
|
||||
function _createDaemonInstance(pluginId, comp) {
|
||||
const instance = comp.createObject(root, {
|
||||
"pluginId": pluginId,
|
||||
"pluginService": root
|
||||
});
|
||||
if (!instance) {
|
||||
log.error("failed to instantiate daemon surface:", pluginId, comp.errorString());
|
||||
return null;
|
||||
}
|
||||
if (instance.popoutService !== undefined)
|
||||
instance.popoutService = PopoutService;
|
||||
log.info("Daemon plugin loaded:", pluginId);
|
||||
return instance;
|
||||
}
|
||||
|
||||
function _drainDaemonSpawnQueue() {
|
||||
const queue = _daemonSpawnQueue;
|
||||
_daemonSpawnQueue = [];
|
||||
const newDaemonInstances = Object.assign({}, pluginDaemonInstances);
|
||||
for (const pluginId of queue) {
|
||||
const comp = pluginDaemonComponents[pluginId];
|
||||
if (!comp || !isPluginLoaded(pluginId) || newDaemonInstances[pluginId])
|
||||
continue;
|
||||
const daemon = _createDaemonInstance(pluginId, comp);
|
||||
if (daemon)
|
||||
newDaemonInstances[pluginId] = daemon;
|
||||
}
|
||||
pluginDaemonInstances = newDaemonInstances;
|
||||
}
|
||||
|
||||
function unloadPlugin(pluginId) {
|
||||
const plugin = loadedPlugins[pluginId];
|
||||
if (!plugin) {
|
||||
@@ -449,6 +499,14 @@ Singleton {
|
||||
pluginInstances = newInstances;
|
||||
}
|
||||
|
||||
const daemonInstance = pluginDaemonInstances[pluginId];
|
||||
if (daemonInstance) {
|
||||
daemonInstance.destroy();
|
||||
const newDaemonInstances = Object.assign({}, pluginDaemonInstances);
|
||||
delete newDaemonInstances[pluginId];
|
||||
pluginDaemonInstances = newDaemonInstances;
|
||||
}
|
||||
|
||||
if (pluginDaemonComponents[pluginId]) {
|
||||
const newDaemons = Object.assign({}, pluginDaemonComponents);
|
||||
delete newDaemons[pluginId];
|
||||
@@ -757,31 +815,12 @@ Singleton {
|
||||
}
|
||||
|
||||
function togglePlugin(pluginId) {
|
||||
let instance = pluginInstances[pluginId];
|
||||
|
||||
// Lazy instantiate daemon plugins on first toggle
|
||||
// This respects the daemon lifecycle (not instantiated on load)
|
||||
// while supporting toggle functionality for slideout-capable daemons
|
||||
if (!instance && pluginDaemonComponents[pluginId]) {
|
||||
const comp = pluginDaemonComponents[pluginId];
|
||||
const newInstance = comp.createObject(root, {
|
||||
"pluginId": pluginId,
|
||||
"pluginService": root
|
||||
});
|
||||
if (newInstance) {
|
||||
const newInstances = Object.assign({}, pluginInstances);
|
||||
newInstances[pluginId] = newInstance;
|
||||
pluginInstances = newInstances;
|
||||
instance = newInstance;
|
||||
}
|
||||
}
|
||||
|
||||
if (instance && typeof instance.toggle === "function") {
|
||||
const instance = pluginInstances[pluginId] || pluginDaemonInstances[pluginId];
|
||||
if (!instance || typeof instance.toggle !== "function")
|
||||
return false;
|
||||
instance.toggle();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function savePluginData(pluginId, key, value) {
|
||||
SettingsData.setPluginSetting(pluginId, key, value);
|
||||
|
||||
Reference in New Issue
Block a user