mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-08-07 05:58: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();
|
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 {
|
Loader {
|
||||||
id: blurredWallpaperBackgroundLoader
|
id: blurredWallpaperBackgroundLoader
|
||||||
active: SettingsData.blurredWallpaperLayer && CompositorService.isNiri
|
active: SettingsData.blurredWallpaperLayer && CompositorService.isNiri
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ Singleton {
|
|||||||
property var knownManifests: ({})
|
property var knownManifests: ({})
|
||||||
property var pathToPluginId: ({})
|
property var pathToPluginId: ({})
|
||||||
property var pluginInstances: ({})
|
property var pluginInstances: ({})
|
||||||
|
property var pluginDaemonInstances: ({})
|
||||||
|
property var _daemonSpawnQueue: []
|
||||||
property var globalVars: ({})
|
property var globalVars: ({})
|
||||||
property var pluginLoadErrors: ({})
|
property var pluginLoadErrors: ({})
|
||||||
|
|
||||||
@@ -59,6 +61,16 @@ Singleton {
|
|||||||
onTriggered: root._flushDirtyStates()
|
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 {
|
Process {
|
||||||
id: directoryCheckProcess
|
id: directoryCheckProcess
|
||||||
command: ["test", "-d", root.pluginDirectory]
|
command: ["test", "-d", root.pluginDirectory]
|
||||||
@@ -368,14 +380,21 @@ Singleton {
|
|||||||
const newDaemons = Object.assign({}, pluginDaemonComponents);
|
const newDaemons = Object.assign({}, pluginDaemonComponents);
|
||||||
const newLaunchers = Object.assign({}, pluginLauncherComponents);
|
const newLaunchers = Object.assign({}, pluginLauncherComponents);
|
||||||
const newInstances = Object.assign({}, pluginInstances);
|
const newInstances = Object.assign({}, pluginInstances);
|
||||||
|
const newDaemonInstances = Object.assign({}, pluginDaemonInstances);
|
||||||
|
|
||||||
const prevInstance = newInstances[pluginId];
|
const prevInstance = newInstances[pluginId];
|
||||||
if (prevInstance) {
|
if (prevInstance) {
|
||||||
prevInstance.destroy();
|
prevInstance.destroy();
|
||||||
delete newInstances[pluginId];
|
delete newInstances[pluginId];
|
||||||
}
|
}
|
||||||
|
const prevDaemon = newDaemonInstances[pluginId];
|
||||||
|
if (prevDaemon) {
|
||||||
|
prevDaemon.destroy();
|
||||||
|
delete newDaemonInstances[pluginId];
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
const comps = {};
|
||||||
for (const surface of surfaces) {
|
for (const surface of surfaces) {
|
||||||
let url = "file://" + componentPaths[surface];
|
let url = "file://" + componentPaths[surface];
|
||||||
if (bustCache)
|
if (bustCache)
|
||||||
@@ -386,38 +405,39 @@ Singleton {
|
|||||||
pluginLoadFailed(pluginId, comp.errorString());
|
pluginLoadFailed(pluginId, comp.errorString());
|
||||||
return false;
|
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, {
|
|
||||||
"pluginService": root
|
|
||||||
});
|
|
||||||
if (!instance) {
|
|
||||||
log.error("failed to instantiate launcher surface:", pluginId, comp.errorString());
|
|
||||||
pluginLoadFailed(pluginId, comp.errorString());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
newInstances[pluginId] = instance;
|
|
||||||
newLaunchers[pluginId] = comp;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
newWidgets[pluginId] = comp;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (comps.launcher) {
|
||||||
|
const instance = comps.launcher.createObject(root, {
|
||||||
|
"pluginService": root
|
||||||
|
});
|
||||||
|
if (!instance) {
|
||||||
|
log.error("failed to instantiate launcher surface:", pluginId, comps.launcher.errorString());
|
||||||
|
pluginLoadFailed(pluginId, comps.launcher.errorString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
newInstances[pluginId] = instance;
|
||||||
|
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;
|
pluginWidgetComponents = newWidgets;
|
||||||
pluginDesktopComponents = newDesktop;
|
pluginDesktopComponents = newDesktop;
|
||||||
pluginDaemonComponents = newDaemons;
|
pluginDaemonComponents = newDaemons;
|
||||||
pluginLauncherComponents = newLaunchers;
|
pluginLauncherComponents = newLaunchers;
|
||||||
pluginInstances = newInstances;
|
pluginInstances = newInstances;
|
||||||
|
pluginDaemonInstances = newDaemonInstances;
|
||||||
|
|
||||||
plugin.loaded = true;
|
plugin.loaded = true;
|
||||||
const newLoaded = Object.assign({}, loadedPlugins);
|
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) {
|
function unloadPlugin(pluginId) {
|
||||||
const plugin = loadedPlugins[pluginId];
|
const plugin = loadedPlugins[pluginId];
|
||||||
if (!plugin) {
|
if (!plugin) {
|
||||||
@@ -449,6 +499,14 @@ Singleton {
|
|||||||
pluginInstances = newInstances;
|
pluginInstances = newInstances;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const daemonInstance = pluginDaemonInstances[pluginId];
|
||||||
|
if (daemonInstance) {
|
||||||
|
daemonInstance.destroy();
|
||||||
|
const newDaemonInstances = Object.assign({}, pluginDaemonInstances);
|
||||||
|
delete newDaemonInstances[pluginId];
|
||||||
|
pluginDaemonInstances = newDaemonInstances;
|
||||||
|
}
|
||||||
|
|
||||||
if (pluginDaemonComponents[pluginId]) {
|
if (pluginDaemonComponents[pluginId]) {
|
||||||
const newDaemons = Object.assign({}, pluginDaemonComponents);
|
const newDaemons = Object.assign({}, pluginDaemonComponents);
|
||||||
delete newDaemons[pluginId];
|
delete newDaemons[pluginId];
|
||||||
@@ -757,30 +815,11 @@ Singleton {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function togglePlugin(pluginId) {
|
function togglePlugin(pluginId) {
|
||||||
let instance = pluginInstances[pluginId];
|
const instance = pluginInstances[pluginId] || pluginDaemonInstances[pluginId];
|
||||||
|
if (!instance || typeof instance.toggle !== "function")
|
||||||
// Lazy instantiate daemon plugins on first toggle
|
return false;
|
||||||
// This respects the daemon lifecycle (not instantiated on load)
|
instance.toggle();
|
||||||
// while supporting toggle functionality for slideout-capable daemons
|
return true;
|
||||||
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") {
|
|
||||||
instance.toggle();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function savePluginData(pluginId, key, value) {
|
function savePluginData(pluginId, key, value) {
|
||||||
|
|||||||
Reference in New Issue
Block a user