From 1ed4abd347f276b648ca1d491001aa9a588df6ce Mon Sep 17 00:00:00 2001 From: bbedward Date: Wed, 8 Oct 2025 10:02:54 -0400 Subject: [PATCH] Attempts to improve startup time --- DMSGreeter.qml | 2 +- DMSShell.qml | 295 ++---------- DMSShellIPC.qml | 265 +++++++++++ Modules/DankBar/DankBar.qml | 13 +- Modules/WallpaperBackground.qml | 776 ++++++++++++++++---------------- Services/CompositorService.qml | 12 +- Services/SessionService.qml | 16 +- shell.qml | 17 +- 8 files changed, 716 insertions(+), 680 deletions(-) create mode 100644 DMSShellIPC.qml diff --git a/DMSGreeter.qml b/DMSGreeter.qml index a0049265..0f833539 100644 --- a/DMSGreeter.qml +++ b/DMSGreeter.qml @@ -5,7 +5,7 @@ import Quickshell.Services.Greetd import qs.Common import qs.Modules.Greetd -ShellRoot { +Item { id: root WlSessionLock { diff --git a/DMSShell.qml b/DMSShell.qml index 5ee6c567..d9523007 100644 --- a/DMSShell.qml +++ b/DMSShell.qml @@ -1,6 +1,3 @@ -//@ pragma Env QSG_RENDER_LOOP=threaded -//@ pragma UseQApplication - import QtQuick import Quickshell import Quickshell.Io @@ -29,24 +26,13 @@ import qs.Modules.Plugins import qs.Services -ShellRoot { +Item { id: root - property bool servicesReady: false - - Component.onCompleted: { - PortalService.init() - DisplayService.nightModeEnabled - WallpaperCyclingService.cyclingActive - PluginService.pluginDirectory - Qt.callLater(() => { - servicesReady = true - }) - } - Instantiator { id: daemonPluginInstantiator - model: servicesReady ? Object.keys(PluginService.pluginDaemonComponents) : [] + asynchronous: true + model: Object.keys(PluginService.pluginDaemonComponents) delegate: Loader { id: daemonLoader @@ -68,10 +54,26 @@ ShellRoot { WallpaperBackground {} - Lock { - id: lock + LazyLoader { + id: lockLoader + active: false - anchors.fill: parent + Lock { + id: lock + anchors.fill: parent + + Component.onCompleted: { + IdleService.lockComponent = lock + } + } + } + + Timer { + id: lockInitTimer + interval: 100 + running: true + repeat: false + onTriggered: lockLoader.active = true } Loader { @@ -471,253 +473,12 @@ ShellRoot { } } - IpcHandler { - function open() { - powerMenuModalLoader.active = true - if (powerMenuModalLoader.item) - powerMenuModalLoader.item.openCentered() - - return "POWERMENU_OPEN_SUCCESS" - } - - function close() { - if (powerMenuModalLoader.item) - powerMenuModalLoader.item.close() - - return "POWERMENU_CLOSE_SUCCESS" - } - - function toggle() { - powerMenuModalLoader.active = true - if (powerMenuModalLoader.item) { - if (powerMenuModalLoader.item.shouldBeVisible) { - powerMenuModalLoader.item.close() - } else { - powerMenuModalLoader.item.openCentered() - } - } - - return "POWERMENU_TOGGLE_SUCCESS" - } - - target: "powermenu" - } - - IpcHandler { - function open(): string { - processListModalLoader.active = true - if (processListModalLoader.item) - processListModalLoader.item.show() - - return "PROCESSLIST_OPEN_SUCCESS" - } - - function close(): string { - if (processListModalLoader.item) - processListModalLoader.item.hide() - - return "PROCESSLIST_CLOSE_SUCCESS" - } - - function toggle(): string { - processListModalLoader.active = true - if (processListModalLoader.item) - processListModalLoader.item.toggle() - - return "PROCESSLIST_TOGGLE_SUCCESS" - } - - target: "processlist" - } - - IpcHandler { - function open(): string { - controlCenterLoader.active = true - if (controlCenterLoader.item) { - controlCenterLoader.item.open() - return "CONTROL_CENTER_OPEN_SUCCESS" - } - return "CONTROL_CENTER_OPEN_FAILED" - } - - function close(): string { - if (controlCenterLoader.item) { - controlCenterLoader.item.close() - return "CONTROL_CENTER_CLOSE_SUCCESS" - } - return "CONTROL_CENTER_CLOSE_FAILED" - } - - function toggle(): string { - controlCenterLoader.active = true - if (controlCenterLoader.item) { - controlCenterLoader.item.toggle() - return "CONTROL_CENTER_TOGGLE_SUCCESS" - } - return "CONTROL_CENTER_TOGGLE_FAILED" - } - - target: "control-center" - } - - IpcHandler { - function open(tab: string): string { - dankDashPopoutLoader.active = true - if (dankDashPopoutLoader.item) { - switch (tab.toLowerCase()) { - case "media": - dankDashPopoutLoader.item.currentTabIndex = 1 - break - case "weather": - dankDashPopoutLoader.item.currentTabIndex = SettingsData.weatherEnabled ? 2 : 0 - break - default: - dankDashPopoutLoader.item.currentTabIndex = 0 - break - } - dankDashPopoutLoader.item.setTriggerPosition(Screen.width / 2, Theme.barHeight + Theme.spacingS, 100, "center", Screen) - dankDashPopoutLoader.item.dashVisible = true - return "DASH_OPEN_SUCCESS" - } - return "DASH_OPEN_FAILED" - } - - function close(): string { - if (dankDashPopoutLoader.item) { - dankDashPopoutLoader.item.dashVisible = false - return "DASH_CLOSE_SUCCESS" - } - return "DASH_CLOSE_FAILED" - } - - function toggle(tab: string): string { - dankDashPopoutLoader.active = true - if (dankDashPopoutLoader.item) { - if (dankDashPopoutLoader.item.dashVisible) { - dankDashPopoutLoader.item.dashVisible = false - } else { - switch (tab.toLowerCase()) { - case "media": - dankDashPopoutLoader.item.currentTabIndex = 1 - break - case "weather": - dankDashPopoutLoader.item.currentTabIndex = SettingsData.weatherEnabled ? 2 : 0 - break - default: - dankDashPopoutLoader.item.currentTabIndex = 0 - break - } - dankDashPopoutLoader.item.setTriggerPosition(Screen.width / 2, Theme.barHeight + Theme.spacingS, 100, "center", Screen) - dankDashPopoutLoader.item.dashVisible = true - } - return "DASH_TOGGLE_SUCCESS" - } - return "DASH_TOGGLE_FAILED" - } - - target: "dash" - } - - IpcHandler { - function getFocusedScreenName() { - if (CompositorService.isHyprland && Hyprland.focusedWorkspace && Hyprland.focusedWorkspace.monitor) { - return Hyprland.focusedWorkspace.monitor.name - } - if (CompositorService.isNiri && NiriService.currentOutput) { - return NiriService.currentOutput - } - return "" - } - - function getActiveNotepadInstance() { - if (notepadSlideoutVariants.instances.length === 0) { - return null - } - - if (notepadSlideoutVariants.instances.length === 1) { - return notepadSlideoutVariants.instances[0] - } - - var focusedScreen = getFocusedScreenName() - if (focusedScreen && notepadSlideoutVariants.instances.length > 0) { - for (var i = 0; i < notepadSlideoutVariants.instances.length; i++) { - var slideout = notepadSlideoutVariants.instances[i] - if (slideout.modelData && slideout.modelData.name === focusedScreen) { - return slideout - } - } - } - - for (var i = 0; i < notepadSlideoutVariants.instances.length; i++) { - var slideout = notepadSlideoutVariants.instances[i] - if (slideout.isVisible) { - return slideout - } - } - - return notepadSlideoutVariants.instances[0] - } - - function open(): string { - var instance = getActiveNotepadInstance() - if (instance) { - instance.show() - return "NOTEPAD_OPEN_SUCCESS" - } - return "NOTEPAD_OPEN_FAILED" - } - - function close(): string { - var instance = getActiveNotepadInstance() - if (instance) { - instance.hide() - return "NOTEPAD_CLOSE_SUCCESS" - } - return "NOTEPAD_CLOSE_FAILED" - } - - function toggle(): string { - var instance = getActiveNotepadInstance() - if (instance) { - instance.toggle() - return "NOTEPAD_TOGGLE_SUCCESS" - } - return "NOTEPAD_TOGGLE_FAILED" - } - - target: "notepad" - } - - IpcHandler { - function toggle(): string { - SessionService.toggleIdleInhibit() - return SessionService.idleInhibited ? "Idle inhibit enabled" : "Idle inhibit disabled" - } - - function enable(): string { - SessionService.enableIdleInhibit() - return "Idle inhibit enabled" - } - - function disable(): string { - SessionService.disableIdleInhibit() - return "Idle inhibit disabled" - } - - function status(): string { - return SessionService.idleInhibited ? "Idle inhibit is enabled" : "Idle inhibit is disabled" - } - - function reason(newReason: string): string { - if (!newReason) { - return `Current reason: ${SessionService.inhibitReason}` - } - - SessionService.setInhibitReason(newReason) - return `Inhibit reason set to: ${newReason}` - } - - target: "inhibit" + DMSShellIPC { + powerMenuModalLoader: powerMenuModalLoader + processListModalLoader: processListModalLoader + controlCenterLoader: controlCenterLoader + dankDashPopoutLoader: dankDashPopoutLoader + notepadSlideoutVariants: notepadSlideoutVariants } Variants { diff --git a/DMSShellIPC.qml b/DMSShellIPC.qml new file mode 100644 index 00000000..3743aa34 --- /dev/null +++ b/DMSShellIPC.qml @@ -0,0 +1,265 @@ +import QtQuick +import Quickshell +import Quickshell.Io +import Quickshell.Hyprland +import qs.Common +import qs.Services + +Item { + id: root + + required property var powerMenuModalLoader + required property var processListModalLoader + required property var controlCenterLoader + required property var dankDashPopoutLoader + required property var notepadSlideoutVariants + + IpcHandler { + function open() { + root.powerMenuModalLoader.active = true + if (root.powerMenuModalLoader.item) + root.powerMenuModalLoader.item.openCentered() + + return "POWERMENU_OPEN_SUCCESS" + } + + function close() { + if (root.powerMenuModalLoader.item) + root.powerMenuModalLoader.item.close() + + return "POWERMENU_CLOSE_SUCCESS" + } + + function toggle() { + root.powerMenuModalLoader.active = true + if (root.powerMenuModalLoader.item) { + if (root.powerMenuModalLoader.item.shouldBeVisible) { + root.powerMenuModalLoader.item.close() + } else { + root.powerMenuModalLoader.item.openCentered() + } + } + + return "POWERMENU_TOGGLE_SUCCESS" + } + + target: "powermenu" + } + + IpcHandler { + function open(): string { + root.processListModalLoader.active = true + if (root.processListModalLoader.item) + root.processListModalLoader.item.show() + + return "PROCESSLIST_OPEN_SUCCESS" + } + + function close(): string { + if (root.processListModalLoader.item) + root.processListModalLoader.item.hide() + + return "PROCESSLIST_CLOSE_SUCCESS" + } + + function toggle(): string { + root.processListModalLoader.active = true + if (root.processListModalLoader.item) + root.processListModalLoader.item.toggle() + + return "PROCESSLIST_TOGGLE_SUCCESS" + } + + target: "processlist" + } + + IpcHandler { + function open(): string { + root.controlCenterLoader.active = true + if (root.controlCenterLoader.item) { + root.controlCenterLoader.item.open() + return "CONTROL_CENTER_OPEN_SUCCESS" + } + return "CONTROL_CENTER_OPEN_FAILED" + } + + function close(): string { + if (root.controlCenterLoader.item) { + root.controlCenterLoader.item.close() + return "CONTROL_CENTER_CLOSE_SUCCESS" + } + return "CONTROL_CENTER_CLOSE_FAILED" + } + + function toggle(): string { + root.controlCenterLoader.active = true + if (root.controlCenterLoader.item) { + root.controlCenterLoader.item.toggle() + return "CONTROL_CENTER_TOGGLE_SUCCESS" + } + return "CONTROL_CENTER_TOGGLE_FAILED" + } + + target: "control-center" + } + + IpcHandler { + function open(tab: string): string { + root.dankDashPopoutLoader.active = true + if (root.dankDashPopoutLoader.item) { + switch (tab.toLowerCase()) { + case "media": + root.dankDashPopoutLoader.item.currentTabIndex = 1 + break + case "weather": + root.dankDashPopoutLoader.item.currentTabIndex = SettingsData.weatherEnabled ? 2 : 0 + break + default: + root.dankDashPopoutLoader.item.currentTabIndex = 0 + break + } + root.dankDashPopoutLoader.item.setTriggerPosition(Screen.width / 2, Theme.barHeight + Theme.spacingS, 100, "center", Screen) + root.dankDashPopoutLoader.item.dashVisible = true + return "DASH_OPEN_SUCCESS" + } + return "DASH_OPEN_FAILED" + } + + function close(): string { + if (root.dankDashPopoutLoader.item) { + root.dankDashPopoutLoader.item.dashVisible = false + return "DASH_CLOSE_SUCCESS" + } + return "DASH_CLOSE_FAILED" + } + + function toggle(tab: string): string { + root.dankDashPopoutLoader.active = true + if (root.dankDashPopoutLoader.item) { + if (root.dankDashPopoutLoader.item.dashVisible) { + root.dankDashPopoutLoader.item.dashVisible = false + } else { + switch (tab.toLowerCase()) { + case "media": + root.dankDashPopoutLoader.item.currentTabIndex = 1 + break + case "weather": + root.dankDashPopoutLoader.item.currentTabIndex = SettingsData.weatherEnabled ? 2 : 0 + break + default: + root.dankDashPopoutLoader.item.currentTabIndex = 0 + break + } + root.dankDashPopoutLoader.item.setTriggerPosition(Screen.width / 2, Theme.barHeight + Theme.spacingS, 100, "center", Screen) + root.dankDashPopoutLoader.item.dashVisible = true + } + return "DASH_TOGGLE_SUCCESS" + } + return "DASH_TOGGLE_FAILED" + } + + target: "dash" + } + + IpcHandler { + function getFocusedScreenName() { + if (CompositorService.isHyprland && Hyprland.focusedWorkspace && Hyprland.focusedWorkspace.monitor) { + return Hyprland.focusedWorkspace.monitor.name + } + if (CompositorService.isNiri && NiriService.currentOutput) { + return NiriService.currentOutput + } + return "" + } + + function getActiveNotepadInstance() { + if (root.notepadSlideoutVariants.instances.length === 0) { + return null + } + + if (root.notepadSlideoutVariants.instances.length === 1) { + return root.notepadSlideoutVariants.instances[0] + } + + var focusedScreen = getFocusedScreenName() + if (focusedScreen && root.notepadSlideoutVariants.instances.length > 0) { + for (var i = 0; i < root.notepadSlideoutVariants.instances.length; i++) { + var slideout = root.notepadSlideoutVariants.instances[i] + if (slideout.modelData && slideout.modelData.name === focusedScreen) { + return slideout + } + } + } + + for (var i = 0; i < root.notepadSlideoutVariants.instances.length; i++) { + var slideout = root.notepadSlideoutVariants.instances[i] + if (slideout.isVisible) { + return slideout + } + } + + return root.notepadSlideoutVariants.instances[0] + } + + function open(): string { + var instance = getActiveNotepadInstance() + if (instance) { + instance.show() + return "NOTEPAD_OPEN_SUCCESS" + } + return "NOTEPAD_OPEN_FAILED" + } + + function close(): string { + var instance = getActiveNotepadInstance() + if (instance) { + instance.hide() + return "NOTEPAD_CLOSE_SUCCESS" + } + return "NOTEPAD_CLOSE_FAILED" + } + + function toggle(): string { + var instance = getActiveNotepadInstance() + if (instance) { + instance.toggle() + return "NOTEPAD_TOGGLE_SUCCESS" + } + return "NOTEPAD_TOGGLE_FAILED" + } + + target: "notepad" + } + + IpcHandler { + function toggle(): string { + SessionService.toggleIdleInhibit() + return SessionService.idleInhibited ? "Idle inhibit enabled" : "Idle inhibit disabled" + } + + function enable(): string { + SessionService.enableIdleInhibit() + return "Idle inhibit enabled" + } + + function disable(): string { + SessionService.disableIdleInhibit() + return "Idle inhibit disabled" + } + + function status(): string { + return SessionService.idleInhibited ? "Idle inhibit is enabled" : "Idle inhibit is disabled" + } + + function reason(newReason: string): string { + if (!newReason) { + return `Current reason: ${SessionService.inhibitReason}` + } + + SessionService.setInhibitReason(newReason) + return `Inhibit reason set to: ${newReason}` + } + + target: "inhibit" + } +} diff --git a/Modules/DankBar/DankBar.qml b/Modules/DankBar/DankBar.qml index a5b8c1b8..a72bb209 100644 --- a/Modules/DankBar/DankBar.qml +++ b/Modules/DankBar/DankBar.qml @@ -96,8 +96,17 @@ Item { updateGpuTempConfig() Qt.callLater(() => Qt.callLater(forceWidgetRefresh)) - if (SessionService.nativeInhibitorAvailable) { - createNativeInhibitor() + inhibitorInitTimer.start() + } + + Timer { + id: inhibitorInitTimer + interval: 300 + repeat: false + onTriggered: { + if (SessionService.nativeInhibitorAvailable) { + createNativeInhibitor() + } } } diff --git a/Modules/WallpaperBackground.qml b/Modules/WallpaperBackground.qml index 8cf1ebf2..ffe4b11c 100644 --- a/Modules/WallpaperBackground.qml +++ b/Modules/WallpaperBackground.qml @@ -7,444 +7,440 @@ import qs.Common import qs.Widgets import qs.Modules -LazyLoader { - active: true - - Variants { - model: { - if (SessionData.isGreeterMode) { - return Quickshell.screens - } - return SettingsData.getFilteredScreens("wallpaper") +Variants { + model: { + if (SessionData.isGreeterMode) { + return Quickshell.screens } + return SettingsData.getFilteredScreens("wallpaper") + } - PanelWindow { - id: wallpaperWindow + PanelWindow { + id: wallpaperWindow - required property var modelData + required property var modelData - screen: modelData + screen: modelData - WlrLayershell.layer: WlrLayer.Background - WlrLayershell.exclusionMode: ExclusionMode.Ignore + WlrLayershell.layer: WlrLayer.Background + WlrLayershell.exclusionMode: ExclusionMode.Ignore - anchors.top: true - anchors.bottom: true - anchors.left: true - anchors.right: true + anchors.top: true + anchors.bottom: true + anchors.left: true + anchors.right: true - color: "transparent" + color: "transparent" - Item { - id: root - anchors.fill: parent + Item { + id: root + anchors.fill: parent - property string source: SessionData.getMonitorWallpaper(modelData.name) || "" - property bool isColorSource: source.startsWith("#") - property string transitionType: SessionData.wallpaperTransition - property string actualTransitionType: transitionType + property string source: SessionData.getMonitorWallpaper(modelData.name) || "" + property bool isColorSource: source.startsWith("#") + property string transitionType: SessionData.wallpaperTransition + property string actualTransitionType: transitionType - Connections { - target: SessionData - function onIsLightModeChanged() { - if (SessionData.perModeWallpaper) { - var newSource = SessionData.getMonitorWallpaper(modelData.name) || "" - if (newSource !== root.source) { - root.source = newSource - } + Connections { + target: SessionData + function onIsLightModeChanged() { + if (SessionData.perModeWallpaper) { + var newSource = SessionData.getMonitorWallpaper(modelData.name) || "" + if (newSource !== root.source) { + root.source = newSource } } } - onTransitionTypeChanged: { - if (transitionType === "random") { - if (SessionData.includedTransitions.length === 0) { - actualTransitionType = "none" - } else { - actualTransitionType = SessionData.includedTransitions[Math.floor(Math.random() * SessionData.includedTransitions.length)] - } + } + onTransitionTypeChanged: { + if (transitionType === "random") { + if (SessionData.includedTransitions.length === 0) { + actualTransitionType = "none" } else { - actualTransitionType = transitionType + actualTransitionType = SessionData.includedTransitions[Math.floor(Math.random() * SessionData.includedTransitions.length)] } + } else { + actualTransitionType = transitionType } + } - onActualTransitionTypeChanged: { - if (actualTransitionType === "none") { - currentWallpaper.visible = true - nextWallpaper.visible = false - } - } - property real transitionProgress: 0 - property real fillMode: 1.0 - property vector4d fillColor: Qt.vector4d(0, 0, 0, 1) - property real edgeSmoothness: 0.1 - - property real wipeDirection: 0 - property real discCenterX: 0.5 - property real discCenterY: 0.5 - property real stripesCount: 16 - property real stripesAngle: 0 - - readonly property bool transitioning: transitionAnimation.running - - property bool hasCurrent: currentWallpaper.status === Image.Ready && !!currentWallpaper.source - property bool booting: !hasCurrent && nextWallpaper.status === Image.Ready - - WallpaperEngineProc { - id: weProc - monitor: modelData.name - } - - Component.onDestruction: { - weProc.stop() - } - - onSourceChanged: { - const isWE = source.startsWith("we:") - const isColor = source.startsWith("#") - - if (isWE) { - setWallpaperImmediate("") - weProc.start(source.substring(3)) - } else { - weProc.stop() - if (!source) { - setWallpaperImmediate("") - } else if (isColor) { - setWallpaperImmediate("") - } else { - // Always set immediately if there's no current wallpaper (startup) - if (!currentWallpaper.source) { - setWallpaperImmediate(source.startsWith("file://") ? source : "file://" + source) - } else { - changeWallpaper(source.startsWith("file://") ? source : "file://" + source) - } - } - } - } - - function setWallpaperImmediate(newSource) { - transitionAnimation.stop() - root.transitionProgress = 0.0 - currentWallpaper.source = newSource - nextWallpaper.source = "" + onActualTransitionTypeChanged: { + if (actualTransitionType === "none") { currentWallpaper.visible = true nextWallpaper.visible = false } + } + property real transitionProgress: 0 + property real fillMode: 1.0 + property vector4d fillColor: Qt.vector4d(0, 0, 0, 1) + property real edgeSmoothness: 0.1 - function changeWallpaper(newPath, force) { - if (!force && newPath === currentWallpaper.source) - return - if (!newPath || newPath.startsWith("#")) - return + property real wipeDirection: 0 + property real discCenterX: 0.5 + property real discCenterY: 0.5 + property real stripesCount: 16 + property real stripesAngle: 0 - if (root.transitioning) { - transitionAnimation.stop() - root.transitionProgress = 0 - currentWallpaper.source = nextWallpaper.source - nextWallpaper.source = "" - } + readonly property bool transitioning: transitionAnimation.running - // If no current wallpaper, set immediately to avoid scaling issues - if (!currentWallpaper.source) { - setWallpaperImmediate(newPath) - return - } + property bool hasCurrent: currentWallpaper.status === Image.Ready && !!currentWallpaper.source + property bool booting: !hasCurrent && nextWallpaper.status === Image.Ready - // If transition is "none", set immediately - if (root.transitionType === "random") { - if (SessionData.includedTransitions.length === 0) { - root.actualTransitionType = "none" + WallpaperEngineProc { + id: weProc + monitor: modelData.name + } + + Component.onDestruction: { + weProc.stop() + } + + onSourceChanged: { + const isWE = source.startsWith("we:") + const isColor = source.startsWith("#") + + if (isWE) { + setWallpaperImmediate("") + weProc.start(source.substring(3)) + } else { + weProc.stop() + if (!source) { + setWallpaperImmediate("") + } else if (isColor) { + setWallpaperImmediate("") + } else { + // Always set immediately if there's no current wallpaper (startup) + if (!currentWallpaper.source) { + setWallpaperImmediate(source.startsWith("file://") ? source : "file://" + source) } else { - root.actualTransitionType = SessionData.includedTransitions[Math.floor(Math.random() * SessionData.includedTransitions.length)] + changeWallpaper(source.startsWith("file://") ? source : "file://" + source) } } + } + } + + function setWallpaperImmediate(newSource) { + transitionAnimation.stop() + root.transitionProgress = 0.0 + currentWallpaper.source = newSource + nextWallpaper.source = "" + currentWallpaper.visible = true + nextWallpaper.visible = false + } + + function changeWallpaper(newPath, force) { + if (!force && newPath === currentWallpaper.source) + return + if (!newPath || newPath.startsWith("#")) + return + + if (root.transitioning) { + transitionAnimation.stop() + root.transitionProgress = 0 + currentWallpaper.source = nextWallpaper.source + nextWallpaper.source = "" + } + + // If no current wallpaper, set immediately to avoid scaling issues + if (!currentWallpaper.source) { + setWallpaperImmediate(newPath) + return + } + + // If transition is "none", set immediately + if (root.transitionType === "random") { + if (SessionData.includedTransitions.length === 0) { + root.actualTransitionType = "none" + } else { + root.actualTransitionType = SessionData.includedTransitions[Math.floor(Math.random() * SessionData.includedTransitions.length)] + } + } + + if (root.actualTransitionType === "none") { + setWallpaperImmediate(newPath) + return + } + + if (root.actualTransitionType === "wipe") { + root.wipeDirection = Math.random() * 4 + } else if (root.actualTransitionType === "disc") { + root.discCenterX = Math.random() + root.discCenterY = Math.random() + } else if (root.actualTransitionType === "stripes") { + root.stripesCount = Math.round(Math.random() * 20 + 4) + root.stripesAngle = Math.random() * 360 + } + + nextWallpaper.source = newPath + + if (nextWallpaper.status === Image.Ready) { + transitionAnimation.start() + } + } + + Loader { + anchors.fill: parent + active: !root.source || root.isColorSource + asynchronous: true + + sourceComponent: DankBackdrop { + screenName: modelData.name + } + } + + Rectangle { + id: transparentRect + anchors.fill: parent + color: "transparent" + visible: false + } + + ShaderEffectSource { + id: transparentSource + sourceItem: transparentRect + hideSource: true + live: false + } + + Image { + id: currentWallpaper + anchors.fill: parent + visible: root.actualTransitionType === "none" + opacity: 1 + layer.enabled: false + asynchronous: true + smooth: true + cache: true + fillMode: Image.PreserveAspectCrop + } + + Image { + id: nextWallpaper + anchors.fill: parent + visible: false + opacity: 0 + layer.enabled: false + asynchronous: true + smooth: true + cache: true + fillMode: Image.PreserveAspectCrop + + onStatusChanged: { + if (status !== Image.Ready) + return if (root.actualTransitionType === "none") { - setWallpaperImmediate(newPath) - return - } - - if (root.actualTransitionType === "wipe") { - root.wipeDirection = Math.random() * 4 - } else if (root.actualTransitionType === "disc") { - root.discCenterX = Math.random() - root.discCenterY = Math.random() - } else if (root.actualTransitionType === "stripes") { - root.stripesCount = Math.round(Math.random() * 20 + 4) - root.stripesAngle = Math.random() * 360 - } - - nextWallpaper.source = newPath - - if (nextWallpaper.status === Image.Ready) { - transitionAnimation.start() - } - } - - Loader { - anchors.fill: parent - active: !root.source || root.isColorSource - asynchronous: true - - sourceComponent: DankBackdrop { - screenName: modelData.name - } - } - - Rectangle { - id: transparentRect - anchors.fill: parent - color: "transparent" - visible: false - } - - ShaderEffectSource { - id: transparentSource - sourceItem: transparentRect - hideSource: true - live: false - } - - Image { - id: currentWallpaper - anchors.fill: parent - visible: root.actualTransitionType === "none" - opacity: 1 - layer.enabled: false - asynchronous: true - smooth: true - cache: true - fillMode: Image.PreserveAspectCrop - } - - Image { - id: nextWallpaper - anchors.fill: parent - visible: false - opacity: 0 - layer.enabled: false - asynchronous: true - smooth: true - cache: true - fillMode: Image.PreserveAspectCrop - - onStatusChanged: { - if (status !== Image.Ready) - return - - if (root.actualTransitionType === "none") { - currentWallpaper.source = source - nextWallpaper.source = "" - root.transitionProgress = 0.0 - } else { - visible = true - if (!root.transitioning) { - transitionAnimation.start() - } + currentWallpaper.source = source + nextWallpaper.source = "" + root.transitionProgress = 0.0 + } else { + visible = true + if (!root.transitioning) { + transitionAnimation.start() } } } + } - Loader { - id: effectLoader + Loader { + id: effectLoader + anchors.fill: parent + active: root.actualTransitionType !== "none" && (root.hasCurrent || root.booting) + sourceComponent: { + switch (root.actualTransitionType) { + case "fade": + return fadeComp + case "wipe": + return wipeComp + case "disc": + return discComp + case "stripes": + return stripesComp + case "iris bloom": + return irisComp + case "pixelate": + return pixelateComp + case "portal": + return portalComp + default: + return null + } + } + } + + Component { + id: fadeComp + ShaderEffect { anchors.fill: parent - active: root.actualTransitionType !== "none" && (root.hasCurrent || root.booting) - sourceComponent: { - switch (root.actualTransitionType) { - case "fade": - return fadeComp - case "wipe": - return wipeComp - case "disc": - return discComp - case "stripes": - return stripesComp - case "iris bloom": - return irisComp - case "pixelate": - return pixelateComp - case "portal": - return portalComp - default: - return null - } - } + property variant source1: root.hasCurrent ? currentWallpaper : transparentSource + property variant source2: nextWallpaper + property real progress: root.transitionProgress + property real fillMode: root.fillMode + property vector4d fillColor: root.fillColor + property real imageWidth1: Math.max(1, root.hasCurrent ? source1.sourceSize.width : modelData.width) + property real imageHeight1: Math.max(1, root.hasCurrent ? source1.sourceSize.height : modelData.height) + property real imageWidth2: Math.max(1, source2.sourceSize.width) + property real imageHeight2: Math.max(1, source2.sourceSize.height) + property real screenWidth: modelData.width + property real screenHeight: modelData.height + fragmentShader: Qt.resolvedUrl("../Shaders/qsb/wp_fade.frag.qsb") } + } - Component { - id: fadeComp - ShaderEffect { - anchors.fill: parent - property variant source1: root.hasCurrent ? currentWallpaper : transparentSource - property variant source2: nextWallpaper - property real progress: root.transitionProgress - property real fillMode: root.fillMode - property vector4d fillColor: root.fillColor - property real imageWidth1: Math.max(1, root.hasCurrent ? source1.sourceSize.width : modelData.width) - property real imageHeight1: Math.max(1, root.hasCurrent ? source1.sourceSize.height : modelData.height) - property real imageWidth2: Math.max(1, source2.sourceSize.width) - property real imageHeight2: Math.max(1, source2.sourceSize.height) - property real screenWidth: modelData.width - property real screenHeight: modelData.height - fragmentShader: Qt.resolvedUrl("../Shaders/qsb/wp_fade.frag.qsb") - } + Component { + id: wipeComp + ShaderEffect { + anchors.fill: parent + property variant source1: root.hasCurrent ? currentWallpaper : transparentSource + property variant source2: nextWallpaper + property real progress: root.transitionProgress + property real smoothness: root.edgeSmoothness + property real direction: root.wipeDirection + property real fillMode: root.fillMode + property vector4d fillColor: root.fillColor + property real imageWidth1: Math.max(1, root.hasCurrent ? source1.sourceSize.width : modelData.width) + property real imageHeight1: Math.max(1, root.hasCurrent ? source1.sourceSize.height : modelData.height) + property real imageWidth2: Math.max(1, source2.sourceSize.width) + property real imageHeight2: Math.max(1, source2.sourceSize.height) + property real screenWidth: modelData.width + property real screenHeight: modelData.height + fragmentShader: Qt.resolvedUrl("../Shaders/qsb/wp_wipe.frag.qsb") } + } - Component { - id: wipeComp - ShaderEffect { - anchors.fill: parent - property variant source1: root.hasCurrent ? currentWallpaper : transparentSource - property variant source2: nextWallpaper - property real progress: root.transitionProgress - property real smoothness: root.edgeSmoothness - property real direction: root.wipeDirection - property real fillMode: root.fillMode - property vector4d fillColor: root.fillColor - property real imageWidth1: Math.max(1, root.hasCurrent ? source1.sourceSize.width : modelData.width) - property real imageHeight1: Math.max(1, root.hasCurrent ? source1.sourceSize.height : modelData.height) - property real imageWidth2: Math.max(1, source2.sourceSize.width) - property real imageHeight2: Math.max(1, source2.sourceSize.height) - property real screenWidth: modelData.width - property real screenHeight: modelData.height - fragmentShader: Qt.resolvedUrl("../Shaders/qsb/wp_wipe.frag.qsb") - } + Component { + id: discComp + ShaderEffect { + anchors.fill: parent + property variant source1: root.hasCurrent ? currentWallpaper : transparentSource + property variant source2: nextWallpaper + property real progress: root.transitionProgress + property real smoothness: root.edgeSmoothness + property real aspectRatio: root.width / root.height + property real centerX: root.discCenterX + property real centerY: root.discCenterY + property real fillMode: root.fillMode + property vector4d fillColor: root.fillColor + property real imageWidth1: Math.max(1, root.hasCurrent ? source1.sourceSize.width : modelData.width) + property real imageHeight1: Math.max(1, root.hasCurrent ? source1.sourceSize.height : modelData.height) + property real imageWidth2: Math.max(1, source2.sourceSize.width) + property real imageHeight2: Math.max(1, source2.sourceSize.height) + property real screenWidth: modelData.width + property real screenHeight: modelData.height + fragmentShader: Qt.resolvedUrl("../Shaders/qsb/wp_disc.frag.qsb") } + } - Component { - id: discComp - ShaderEffect { - anchors.fill: parent - property variant source1: root.hasCurrent ? currentWallpaper : transparentSource - property variant source2: nextWallpaper - property real progress: root.transitionProgress - property real smoothness: root.edgeSmoothness - property real aspectRatio: root.width / root.height - property real centerX: root.discCenterX - property real centerY: root.discCenterY - property real fillMode: root.fillMode - property vector4d fillColor: root.fillColor - property real imageWidth1: Math.max(1, root.hasCurrent ? source1.sourceSize.width : modelData.width) - property real imageHeight1: Math.max(1, root.hasCurrent ? source1.sourceSize.height : modelData.height) - property real imageWidth2: Math.max(1, source2.sourceSize.width) - property real imageHeight2: Math.max(1, source2.sourceSize.height) - property real screenWidth: modelData.width - property real screenHeight: modelData.height - fragmentShader: Qt.resolvedUrl("../Shaders/qsb/wp_disc.frag.qsb") - } + Component { + id: stripesComp + ShaderEffect { + anchors.fill: parent + property variant source1: root.hasCurrent ? currentWallpaper : transparentSource + property variant source2: nextWallpaper + property real progress: root.transitionProgress + property real smoothness: root.edgeSmoothness + property real aspectRatio: root.width / root.height + property real stripeCount: root.stripesCount + property real angle: root.stripesAngle + property real fillMode: root.fillMode + property vector4d fillColor: root.fillColor + property real imageWidth1: Math.max(1, root.hasCurrent ? source1.sourceSize.width : modelData.width) + property real imageHeight1: Math.max(1, root.hasCurrent ? source1.sourceSize.height : modelData.height) + property real imageWidth2: Math.max(1, source2.sourceSize.width) + property real imageHeight2: Math.max(1, source2.sourceSize.height) + property real screenWidth: modelData.width + property real screenHeight: modelData.height + fragmentShader: Qt.resolvedUrl("../Shaders/qsb/wp_stripes.frag.qsb") } + } - Component { - id: stripesComp - ShaderEffect { - anchors.fill: parent - property variant source1: root.hasCurrent ? currentWallpaper : transparentSource - property variant source2: nextWallpaper - property real progress: root.transitionProgress - property real smoothness: root.edgeSmoothness - property real aspectRatio: root.width / root.height - property real stripeCount: root.stripesCount - property real angle: root.stripesAngle - property real fillMode: root.fillMode - property vector4d fillColor: root.fillColor - property real imageWidth1: Math.max(1, root.hasCurrent ? source1.sourceSize.width : modelData.width) - property real imageHeight1: Math.max(1, root.hasCurrent ? source1.sourceSize.height : modelData.height) - property real imageWidth2: Math.max(1, source2.sourceSize.width) - property real imageHeight2: Math.max(1, source2.sourceSize.height) - property real screenWidth: modelData.width - property real screenHeight: modelData.height - fragmentShader: Qt.resolvedUrl("../Shaders/qsb/wp_stripes.frag.qsb") - } + Component { + id: irisComp + ShaderEffect { + anchors.fill: parent + property variant source1: root.hasCurrent ? currentWallpaper : transparentSource + property variant source2: nextWallpaper + property real progress: root.transitionProgress + property real smoothness: root.edgeSmoothness + property real centerX: 0.5 + property real centerY: 0.5 + property real aspectRatio: root.width / root.height + property real fillMode: root.fillMode + property vector4d fillColor: root.fillColor + property real imageWidth1: Math.max(1, root.hasCurrent ? source1.sourceSize.width : modelData.width) + property real imageHeight1: Math.max(1, root.hasCurrent ? source1.sourceSize.height : modelData.height) + property real imageWidth2: Math.max(1, source2.sourceSize.width) + property real imageHeight2: Math.max(1, source2.sourceSize.height) + property real screenWidth: modelData.width + property real screenHeight: modelData.height + fragmentShader: Qt.resolvedUrl("../Shaders/qsb/wp_iris_bloom.frag.qsb") } + } - Component { - id: irisComp - ShaderEffect { - anchors.fill: parent - property variant source1: root.hasCurrent ? currentWallpaper : transparentSource - property variant source2: nextWallpaper - property real progress: root.transitionProgress - property real smoothness: root.edgeSmoothness - property real centerX: 0.5 - property real centerY: 0.5 - property real aspectRatio: root.width / root.height - property real fillMode: root.fillMode - property vector4d fillColor: root.fillColor - property real imageWidth1: Math.max(1, root.hasCurrent ? source1.sourceSize.width : modelData.width) - property real imageHeight1: Math.max(1, root.hasCurrent ? source1.sourceSize.height : modelData.height) - property real imageWidth2: Math.max(1, source2.sourceSize.width) - property real imageHeight2: Math.max(1, source2.sourceSize.height) - property real screenWidth: modelData.width - property real screenHeight: modelData.height - fragmentShader: Qt.resolvedUrl("../Shaders/qsb/wp_iris_bloom.frag.qsb") - } + Component { + id: pixelateComp + ShaderEffect { + anchors.fill: parent + property variant source1: root.hasCurrent ? currentWallpaper : transparentSource + property variant source2: nextWallpaper + property real progress: root.transitionProgress + property real smoothness: root.edgeSmoothness + property real fillMode: root.fillMode + property vector4d fillColor: root.fillColor + property real imageWidth1: Math.max(1, root.hasCurrent ? source1.sourceSize.width : modelData.width) + property real imageHeight1: Math.max(1, root.hasCurrent ? source1.sourceSize.height : modelData.height) + property real imageWidth2: Math.max(1, source2.sourceSize.width) + property real imageHeight2: Math.max(1, source2.sourceSize.height) + property real screenWidth: modelData.width + property real screenHeight: modelData.height + property real centerX: root.discCenterX + property real centerY: root.discCenterY + property real aspectRatio: root.width / root.height + fragmentShader: Qt.resolvedUrl("../Shaders/qsb/wp_pixelate.frag.qsb") } + } - Component { - id: pixelateComp - ShaderEffect { - anchors.fill: parent - property variant source1: root.hasCurrent ? currentWallpaper : transparentSource - property variant source2: nextWallpaper - property real progress: root.transitionProgress - property real smoothness: root.edgeSmoothness - property real fillMode: root.fillMode - property vector4d fillColor: root.fillColor - property real imageWidth1: Math.max(1, root.hasCurrent ? source1.sourceSize.width : modelData.width) - property real imageHeight1: Math.max(1, root.hasCurrent ? source1.sourceSize.height : modelData.height) - property real imageWidth2: Math.max(1, source2.sourceSize.width) - property real imageHeight2: Math.max(1, source2.sourceSize.height) - property real screenWidth: modelData.width - property real screenHeight: modelData.height - property real centerX: root.discCenterX - property real centerY: root.discCenterY - property real aspectRatio: root.width / root.height - fragmentShader: Qt.resolvedUrl("../Shaders/qsb/wp_pixelate.frag.qsb") - } + Component { + id: portalComp + ShaderEffect { + anchors.fill: parent + property variant source1: root.hasCurrent ? currentWallpaper : transparentSource + property variant source2: nextWallpaper + property real progress: root.transitionProgress + property real smoothness: root.edgeSmoothness + property real aspectRatio: root.width / root.height + property real centerX: root.discCenterX + property real centerY: root.discCenterY + property real fillMode: root.fillMode + property vector4d fillColor: root.fillColor + property real imageWidth1: Math.max(1, root.hasCurrent ? source1.sourceSize.width : modelData.width) + property real imageHeight1: Math.max(1, root.hasCurrent ? source1.sourceSize.height : modelData.height) + property real imageWidth2: Math.max(1, source2.sourceSize.width) + property real imageHeight2: Math.max(1, source2.sourceSize.height) + property real screenWidth: modelData.width + property real screenHeight: modelData.height + fragmentShader: Qt.resolvedUrl("../Shaders/qsb/wp_portal.frag.qsb") } + } - Component { - id: portalComp - ShaderEffect { - anchors.fill: parent - property variant source1: root.hasCurrent ? currentWallpaper : transparentSource - property variant source2: nextWallpaper - property real progress: root.transitionProgress - property real smoothness: root.edgeSmoothness - property real aspectRatio: root.width / root.height - property real centerX: root.discCenterX - property real centerY: root.discCenterY - property real fillMode: root.fillMode - property vector4d fillColor: root.fillColor - property real imageWidth1: Math.max(1, root.hasCurrent ? source1.sourceSize.width : modelData.width) - property real imageHeight1: Math.max(1, root.hasCurrent ? source1.sourceSize.height : modelData.height) - property real imageWidth2: Math.max(1, source2.sourceSize.width) - property real imageHeight2: Math.max(1, source2.sourceSize.height) - property real screenWidth: modelData.width - property real screenHeight: modelData.height - fragmentShader: Qt.resolvedUrl("../Shaders/qsb/wp_portal.frag.qsb") - } - } - - NumberAnimation { - id: transitionAnimation - target: root - property: "transitionProgress" - from: 0.0 - to: 1.0 - duration: root.actualTransitionType === "none" ? 0 : 1000 - easing.type: Easing.InOutCubic - onFinished: { - Qt.callLater(() => { - if (nextWallpaper.source && nextWallpaper.status === Image.Ready && !nextWallpaper.source.toString().startsWith("#")) { - currentWallpaper.source = nextWallpaper.source - } - nextWallpaper.source = "" - nextWallpaper.visible = false - currentWallpaper.visible = root.actualTransitionType === "none" - root.transitionProgress = 0.0 - }) - } + NumberAnimation { + id: transitionAnimation + target: root + property: "transitionProgress" + from: 0.0 + to: 1.0 + duration: root.actualTransitionType === "none" ? 0 : 1000 + easing.type: Easing.InOutCubic + onFinished: { + Qt.callLater(() => { + if (nextWallpaper.source && nextWallpaper.status === Image.Ready && !nextWallpaper.source.toString().startsWith("#")) { + currentWallpaper.source = nextWallpaper.source + } + nextWallpaper.source = "" + nextWallpaper.visible = false + currentWallpaper.visible = root.actualTransitionType === "none" + root.transitionProgress = 0.0 + }) } } } diff --git a/Services/CompositorService.qml b/Services/CompositorService.qml index ee5416c8..37b6b1be 100644 --- a/Services/CompositorService.qml +++ b/Services/CompositorService.qml @@ -80,9 +80,15 @@ Singleton { return ToplevelManager.toplevels.values } - Component.onCompleted: { - detectCompositor() - NiriService.generateNiriLayoutConfig() + Timer { + id: compositorInitTimer + interval: 100 + running: true + repeat: false + onTriggered: { + detectCompositor() + Qt.callLater(() => NiriService.generateNiriLayoutConfig()) + } } function filterCurrentWorkspace(toplevels, screen) { diff --git a/Services/SessionService.qml b/Services/SessionService.qml index 256a3a45..3ce0ee59 100644 --- a/Services/SessionService.qml +++ b/Services/SessionService.qml @@ -28,11 +28,17 @@ Singleton { } } - Component.onCompleted: { - detectElogindProcess.running = true - detectHibernateProcess.running = true - detectPrimeRunProcess.running = true - console.log("SessionService: Native inhibitor available:", nativeInhibitorAvailable) + Timer { + id: sessionInitTimer + interval: 200 + running: true + repeat: false + onTriggered: { + detectElogindProcess.running = true + detectHibernateProcess.running = true + detectPrimeRunProcess.running = true + console.log("SessionService: Native inhibitor available:", nativeInhibitorAvailable) + } } diff --git a/shell.qml b/shell.qml index dcbb2b2d..8a667a8b 100644 --- a/shell.qml +++ b/shell.qml @@ -1,3 +1,6 @@ +//@ pragma Env QSG_RENDER_LOOP=threaded +//@ pragma UseQApplication + import QtQuick import Quickshell @@ -6,27 +9,17 @@ ShellRoot { readonly property bool runGreeter: Quickshell.env("DMS_RUN_GREETER") === "1" || Quickshell.env("DMS_RUN_GREETER") === "true" - Component { - id: shellComponent - DMSShell {} - } - - Component { - id: greeterComponent - DMSGreeter {} - } - Loader { id: dmsShellLoader asynchronous: false - sourceComponent: shellComponent + sourceComponent: DMSShell {} active: !entrypoint.runGreeter } Loader { id: dmsGreeterLoader asynchronous: false - sourceComponent: greeterComponent + sourceComponent: DMSGreeter {} active: entrypoint.runGreeter } }