1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2025-12-05 21:15:38 -05:00

Attempts to improve startup time

This commit is contained in:
bbedward
2025-10-08 10:02:54 -04:00
parent f71dd1ed54
commit 1ed4abd347
8 changed files with 716 additions and 680 deletions

View File

@@ -5,7 +5,7 @@ import Quickshell.Services.Greetd
import qs.Common import qs.Common
import qs.Modules.Greetd import qs.Modules.Greetd
ShellRoot { Item {
id: root id: root
WlSessionLock { WlSessionLock {

View File

@@ -1,6 +1,3 @@
//@ pragma Env QSG_RENDER_LOOP=threaded
//@ pragma UseQApplication
import QtQuick import QtQuick
import Quickshell import Quickshell
import Quickshell.Io import Quickshell.Io
@@ -29,24 +26,13 @@ import qs.Modules.Plugins
import qs.Services import qs.Services
ShellRoot { Item {
id: root id: root
property bool servicesReady: false
Component.onCompleted: {
PortalService.init()
DisplayService.nightModeEnabled
WallpaperCyclingService.cyclingActive
PluginService.pluginDirectory
Qt.callLater(() => {
servicesReady = true
})
}
Instantiator { Instantiator {
id: daemonPluginInstantiator id: daemonPluginInstantiator
model: servicesReady ? Object.keys(PluginService.pluginDaemonComponents) : [] asynchronous: true
model: Object.keys(PluginService.pluginDaemonComponents)
delegate: Loader { delegate: Loader {
id: daemonLoader id: daemonLoader
@@ -68,10 +54,26 @@ ShellRoot {
WallpaperBackground {} WallpaperBackground {}
Lock { LazyLoader {
id: lock 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 { Loader {
@@ -471,253 +473,12 @@ ShellRoot {
} }
} }
IpcHandler { DMSShellIPC {
function open() { powerMenuModalLoader: powerMenuModalLoader
powerMenuModalLoader.active = true processListModalLoader: processListModalLoader
if (powerMenuModalLoader.item) controlCenterLoader: controlCenterLoader
powerMenuModalLoader.item.openCentered() dankDashPopoutLoader: dankDashPopoutLoader
notepadSlideoutVariants: notepadSlideoutVariants
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"
} }
Variants { Variants {

265
DMSShellIPC.qml Normal file
View File

@@ -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"
}
}

View File

@@ -96,8 +96,17 @@ Item {
updateGpuTempConfig() updateGpuTempConfig()
Qt.callLater(() => Qt.callLater(forceWidgetRefresh)) Qt.callLater(() => Qt.callLater(forceWidgetRefresh))
if (SessionService.nativeInhibitorAvailable) { inhibitorInitTimer.start()
createNativeInhibitor() }
Timer {
id: inhibitorInitTimer
interval: 300
repeat: false
onTriggered: {
if (SessionService.nativeInhibitorAvailable) {
createNativeInhibitor()
}
} }
} }

View File

@@ -7,444 +7,440 @@ import qs.Common
import qs.Widgets import qs.Widgets
import qs.Modules import qs.Modules
LazyLoader { Variants {
active: true model: {
if (SessionData.isGreeterMode) {
Variants { return Quickshell.screens
model: {
if (SessionData.isGreeterMode) {
return Quickshell.screens
}
return SettingsData.getFilteredScreens("wallpaper")
} }
return SettingsData.getFilteredScreens("wallpaper")
}
PanelWindow { PanelWindow {
id: wallpaperWindow id: wallpaperWindow
required property var modelData required property var modelData
screen: modelData screen: modelData
WlrLayershell.layer: WlrLayer.Background WlrLayershell.layer: WlrLayer.Background
WlrLayershell.exclusionMode: ExclusionMode.Ignore WlrLayershell.exclusionMode: ExclusionMode.Ignore
anchors.top: true anchors.top: true
anchors.bottom: true anchors.bottom: true
anchors.left: true anchors.left: true
anchors.right: true anchors.right: true
color: "transparent" color: "transparent"
Item { Item {
id: root id: root
anchors.fill: parent anchors.fill: parent
property string source: SessionData.getMonitorWallpaper(modelData.name) || "" property string source: SessionData.getMonitorWallpaper(modelData.name) || ""
property bool isColorSource: source.startsWith("#") property bool isColorSource: source.startsWith("#")
property string transitionType: SessionData.wallpaperTransition property string transitionType: SessionData.wallpaperTransition
property string actualTransitionType: transitionType property string actualTransitionType: transitionType
Connections { Connections {
target: SessionData target: SessionData
function onIsLightModeChanged() { function onIsLightModeChanged() {
if (SessionData.perModeWallpaper) { if (SessionData.perModeWallpaper) {
var newSource = SessionData.getMonitorWallpaper(modelData.name) || "" var newSource = SessionData.getMonitorWallpaper(modelData.name) || ""
if (newSource !== root.source) { if (newSource !== root.source) {
root.source = newSource root.source = newSource
}
} }
} }
} }
onTransitionTypeChanged: { }
if (transitionType === "random") { onTransitionTypeChanged: {
if (SessionData.includedTransitions.length === 0) { if (transitionType === "random") {
actualTransitionType = "none" if (SessionData.includedTransitions.length === 0) {
} else { actualTransitionType = "none"
actualTransitionType = SessionData.includedTransitions[Math.floor(Math.random() * SessionData.includedTransitions.length)]
}
} else { } else {
actualTransitionType = transitionType actualTransitionType = SessionData.includedTransitions[Math.floor(Math.random() * SessionData.includedTransitions.length)]
} }
} else {
actualTransitionType = transitionType
} }
}
onActualTransitionTypeChanged: { onActualTransitionTypeChanged: {
if (actualTransitionType === "none") { 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 = ""
currentWallpaper.visible = true currentWallpaper.visible = true
nextWallpaper.visible = false 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) { property real wipeDirection: 0
if (!force && newPath === currentWallpaper.source) property real discCenterX: 0.5
return property real discCenterY: 0.5
if (!newPath || newPath.startsWith("#")) property real stripesCount: 16
return property real stripesAngle: 0
if (root.transitioning) { readonly property bool transitioning: transitionAnimation.running
transitionAnimation.stop()
root.transitionProgress = 0
currentWallpaper.source = nextWallpaper.source
nextWallpaper.source = ""
}
// If no current wallpaper, set immediately to avoid scaling issues property bool hasCurrent: currentWallpaper.status === Image.Ready && !!currentWallpaper.source
if (!currentWallpaper.source) { property bool booting: !hasCurrent && nextWallpaper.status === Image.Ready
setWallpaperImmediate(newPath)
return
}
// If transition is "none", set immediately WallpaperEngineProc {
if (root.transitionType === "random") { id: weProc
if (SessionData.includedTransitions.length === 0) { monitor: modelData.name
root.actualTransitionType = "none" }
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 { } 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") { if (root.actualTransitionType === "none") {
setWallpaperImmediate(newPath) currentWallpaper.source = source
return nextWallpaper.source = ""
} root.transitionProgress = 0.0
} else {
if (root.actualTransitionType === "wipe") { visible = true
root.wipeDirection = Math.random() * 4 if (!root.transitioning) {
} else if (root.actualTransitionType === "disc") { transitionAnimation.start()
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()
}
} }
} }
} }
}
Loader { Loader {
id: effectLoader 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 anchors.fill: parent
active: root.actualTransitionType !== "none" && (root.hasCurrent || root.booting) property variant source1: root.hasCurrent ? currentWallpaper : transparentSource
sourceComponent: { property variant source2: nextWallpaper
switch (root.actualTransitionType) { property real progress: root.transitionProgress
case "fade": property real fillMode: root.fillMode
return fadeComp property vector4d fillColor: root.fillColor
case "wipe": property real imageWidth1: Math.max(1, root.hasCurrent ? source1.sourceSize.width : modelData.width)
return wipeComp property real imageHeight1: Math.max(1, root.hasCurrent ? source1.sourceSize.height : modelData.height)
case "disc": property real imageWidth2: Math.max(1, source2.sourceSize.width)
return discComp property real imageHeight2: Math.max(1, source2.sourceSize.height)
case "stripes": property real screenWidth: modelData.width
return stripesComp property real screenHeight: modelData.height
case "iris bloom": fragmentShader: Qt.resolvedUrl("../Shaders/qsb/wp_fade.frag.qsb")
return irisComp
case "pixelate":
return pixelateComp
case "portal":
return portalComp
default:
return null
}
}
} }
}
Component { Component {
id: fadeComp id: wipeComp
ShaderEffect { ShaderEffect {
anchors.fill: parent anchors.fill: parent
property variant source1: root.hasCurrent ? currentWallpaper : transparentSource property variant source1: root.hasCurrent ? currentWallpaper : transparentSource
property variant source2: nextWallpaper property variant source2: nextWallpaper
property real progress: root.transitionProgress property real progress: root.transitionProgress
property real fillMode: root.fillMode property real smoothness: root.edgeSmoothness
property vector4d fillColor: root.fillColor property real direction: root.wipeDirection
property real imageWidth1: Math.max(1, root.hasCurrent ? source1.sourceSize.width : modelData.width) property real fillMode: root.fillMode
property real imageHeight1: Math.max(1, root.hasCurrent ? source1.sourceSize.height : modelData.height) property vector4d fillColor: root.fillColor
property real imageWidth2: Math.max(1, source2.sourceSize.width) property real imageWidth1: Math.max(1, root.hasCurrent ? source1.sourceSize.width : modelData.width)
property real imageHeight2: Math.max(1, source2.sourceSize.height) property real imageHeight1: Math.max(1, root.hasCurrent ? source1.sourceSize.height : modelData.height)
property real screenWidth: modelData.width property real imageWidth2: Math.max(1, source2.sourceSize.width)
property real screenHeight: modelData.height property real imageHeight2: Math.max(1, source2.sourceSize.height)
fragmentShader: Qt.resolvedUrl("../Shaders/qsb/wp_fade.frag.qsb") property real screenWidth: modelData.width
} property real screenHeight: modelData.height
fragmentShader: Qt.resolvedUrl("../Shaders/qsb/wp_wipe.frag.qsb")
} }
}
Component { Component {
id: wipeComp id: discComp
ShaderEffect { ShaderEffect {
anchors.fill: parent anchors.fill: parent
property variant source1: root.hasCurrent ? currentWallpaper : transparentSource property variant source1: root.hasCurrent ? currentWallpaper : transparentSource
property variant source2: nextWallpaper property variant source2: nextWallpaper
property real progress: root.transitionProgress property real progress: root.transitionProgress
property real smoothness: root.edgeSmoothness property real smoothness: root.edgeSmoothness
property real direction: root.wipeDirection property real aspectRatio: root.width / root.height
property real fillMode: root.fillMode property real centerX: root.discCenterX
property vector4d fillColor: root.fillColor property real centerY: root.discCenterY
property real imageWidth1: Math.max(1, root.hasCurrent ? source1.sourceSize.width : modelData.width) property real fillMode: root.fillMode
property real imageHeight1: Math.max(1, root.hasCurrent ? source1.sourceSize.height : modelData.height) property vector4d fillColor: root.fillColor
property real imageWidth2: Math.max(1, source2.sourceSize.width) property real imageWidth1: Math.max(1, root.hasCurrent ? source1.sourceSize.width : modelData.width)
property real imageHeight2: Math.max(1, source2.sourceSize.height) property real imageHeight1: Math.max(1, root.hasCurrent ? source1.sourceSize.height : modelData.height)
property real screenWidth: modelData.width property real imageWidth2: Math.max(1, source2.sourceSize.width)
property real screenHeight: modelData.height property real imageHeight2: Math.max(1, source2.sourceSize.height)
fragmentShader: Qt.resolvedUrl("../Shaders/qsb/wp_wipe.frag.qsb") property real screenWidth: modelData.width
} property real screenHeight: modelData.height
fragmentShader: Qt.resolvedUrl("../Shaders/qsb/wp_disc.frag.qsb")
} }
}
Component { Component {
id: discComp id: stripesComp
ShaderEffect { ShaderEffect {
anchors.fill: parent anchors.fill: parent
property variant source1: root.hasCurrent ? currentWallpaper : transparentSource property variant source1: root.hasCurrent ? currentWallpaper : transparentSource
property variant source2: nextWallpaper property variant source2: nextWallpaper
property real progress: root.transitionProgress property real progress: root.transitionProgress
property real smoothness: root.edgeSmoothness property real smoothness: root.edgeSmoothness
property real aspectRatio: root.width / root.height property real aspectRatio: root.width / root.height
property real centerX: root.discCenterX property real stripeCount: root.stripesCount
property real centerY: root.discCenterY property real angle: root.stripesAngle
property real fillMode: root.fillMode property real fillMode: root.fillMode
property vector4d fillColor: root.fillColor property vector4d fillColor: root.fillColor
property real imageWidth1: Math.max(1, root.hasCurrent ? source1.sourceSize.width : modelData.width) 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 imageHeight1: Math.max(1, root.hasCurrent ? source1.sourceSize.height : modelData.height)
property real imageWidth2: Math.max(1, source2.sourceSize.width) property real imageWidth2: Math.max(1, source2.sourceSize.width)
property real imageHeight2: Math.max(1, source2.sourceSize.height) property real imageHeight2: Math.max(1, source2.sourceSize.height)
property real screenWidth: modelData.width property real screenWidth: modelData.width
property real screenHeight: modelData.height property real screenHeight: modelData.height
fragmentShader: Qt.resolvedUrl("../Shaders/qsb/wp_disc.frag.qsb") fragmentShader: Qt.resolvedUrl("../Shaders/qsb/wp_stripes.frag.qsb")
}
} }
}
Component { Component {
id: stripesComp id: irisComp
ShaderEffect { ShaderEffect {
anchors.fill: parent anchors.fill: parent
property variant source1: root.hasCurrent ? currentWallpaper : transparentSource property variant source1: root.hasCurrent ? currentWallpaper : transparentSource
property variant source2: nextWallpaper property variant source2: nextWallpaper
property real progress: root.transitionProgress property real progress: root.transitionProgress
property real smoothness: root.edgeSmoothness property real smoothness: root.edgeSmoothness
property real aspectRatio: root.width / root.height property real centerX: 0.5
property real stripeCount: root.stripesCount property real centerY: 0.5
property real angle: root.stripesAngle property real aspectRatio: root.width / root.height
property real fillMode: root.fillMode property real fillMode: root.fillMode
property vector4d fillColor: root.fillColor property vector4d fillColor: root.fillColor
property real imageWidth1: Math.max(1, root.hasCurrent ? source1.sourceSize.width : modelData.width) 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 imageHeight1: Math.max(1, root.hasCurrent ? source1.sourceSize.height : modelData.height)
property real imageWidth2: Math.max(1, source2.sourceSize.width) property real imageWidth2: Math.max(1, source2.sourceSize.width)
property real imageHeight2: Math.max(1, source2.sourceSize.height) property real imageHeight2: Math.max(1, source2.sourceSize.height)
property real screenWidth: modelData.width property real screenWidth: modelData.width
property real screenHeight: modelData.height property real screenHeight: modelData.height
fragmentShader: Qt.resolvedUrl("../Shaders/qsb/wp_stripes.frag.qsb") fragmentShader: Qt.resolvedUrl("../Shaders/qsb/wp_iris_bloom.frag.qsb")
}
} }
}
Component { Component {
id: irisComp id: pixelateComp
ShaderEffect { ShaderEffect {
anchors.fill: parent anchors.fill: parent
property variant source1: root.hasCurrent ? currentWallpaper : transparentSource property variant source1: root.hasCurrent ? currentWallpaper : transparentSource
property variant source2: nextWallpaper property variant source2: nextWallpaper
property real progress: root.transitionProgress property real progress: root.transitionProgress
property real smoothness: root.edgeSmoothness property real smoothness: root.edgeSmoothness
property real centerX: 0.5 property real fillMode: root.fillMode
property real centerY: 0.5 property vector4d fillColor: root.fillColor
property real aspectRatio: root.width / root.height property real imageWidth1: Math.max(1, root.hasCurrent ? source1.sourceSize.width : modelData.width)
property real fillMode: root.fillMode property real imageHeight1: Math.max(1, root.hasCurrent ? source1.sourceSize.height : modelData.height)
property vector4d fillColor: root.fillColor property real imageWidth2: Math.max(1, source2.sourceSize.width)
property real imageWidth1: Math.max(1, root.hasCurrent ? source1.sourceSize.width : modelData.width) property real imageHeight2: Math.max(1, source2.sourceSize.height)
property real imageHeight1: Math.max(1, root.hasCurrent ? source1.sourceSize.height : modelData.height) property real screenWidth: modelData.width
property real imageWidth2: Math.max(1, source2.sourceSize.width) property real screenHeight: modelData.height
property real imageHeight2: Math.max(1, source2.sourceSize.height) property real centerX: root.discCenterX
property real screenWidth: modelData.width property real centerY: root.discCenterY
property real screenHeight: modelData.height property real aspectRatio: root.width / root.height
fragmentShader: Qt.resolvedUrl("../Shaders/qsb/wp_iris_bloom.frag.qsb") fragmentShader: Qt.resolvedUrl("../Shaders/qsb/wp_pixelate.frag.qsb")
}
} }
}
Component { Component {
id: pixelateComp id: portalComp
ShaderEffect { ShaderEffect {
anchors.fill: parent anchors.fill: parent
property variant source1: root.hasCurrent ? currentWallpaper : transparentSource property variant source1: root.hasCurrent ? currentWallpaper : transparentSource
property variant source2: nextWallpaper property variant source2: nextWallpaper
property real progress: root.transitionProgress property real progress: root.transitionProgress
property real smoothness: root.edgeSmoothness property real smoothness: root.edgeSmoothness
property real fillMode: root.fillMode property real aspectRatio: root.width / root.height
property vector4d fillColor: root.fillColor property real centerX: root.discCenterX
property real imageWidth1: Math.max(1, root.hasCurrent ? source1.sourceSize.width : modelData.width) property real centerY: root.discCenterY
property real imageHeight1: Math.max(1, root.hasCurrent ? source1.sourceSize.height : modelData.height) property real fillMode: root.fillMode
property real imageWidth2: Math.max(1, source2.sourceSize.width) property vector4d fillColor: root.fillColor
property real imageHeight2: Math.max(1, source2.sourceSize.height) property real imageWidth1: Math.max(1, root.hasCurrent ? source1.sourceSize.width : modelData.width)
property real screenWidth: modelData.width property real imageHeight1: Math.max(1, root.hasCurrent ? source1.sourceSize.height : modelData.height)
property real screenHeight: modelData.height property real imageWidth2: Math.max(1, source2.sourceSize.width)
property real centerX: root.discCenterX property real imageHeight2: Math.max(1, source2.sourceSize.height)
property real centerY: root.discCenterY property real screenWidth: modelData.width
property real aspectRatio: root.width / root.height property real screenHeight: modelData.height
fragmentShader: Qt.resolvedUrl("../Shaders/qsb/wp_pixelate.frag.qsb") fragmentShader: Qt.resolvedUrl("../Shaders/qsb/wp_portal.frag.qsb")
}
} }
}
Component { NumberAnimation {
id: portalComp id: transitionAnimation
ShaderEffect { target: root
anchors.fill: parent property: "transitionProgress"
property variant source1: root.hasCurrent ? currentWallpaper : transparentSource from: 0.0
property variant source2: nextWallpaper to: 1.0
property real progress: root.transitionProgress duration: root.actualTransitionType === "none" ? 0 : 1000
property real smoothness: root.edgeSmoothness easing.type: Easing.InOutCubic
property real aspectRatio: root.width / root.height onFinished: {
property real centerX: root.discCenterX Qt.callLater(() => {
property real centerY: root.discCenterY if (nextWallpaper.source && nextWallpaper.status === Image.Ready && !nextWallpaper.source.toString().startsWith("#")) {
property real fillMode: root.fillMode currentWallpaper.source = nextWallpaper.source
property vector4d fillColor: root.fillColor }
property real imageWidth1: Math.max(1, root.hasCurrent ? source1.sourceSize.width : modelData.width) nextWallpaper.source = ""
property real imageHeight1: Math.max(1, root.hasCurrent ? source1.sourceSize.height : modelData.height) nextWallpaper.visible = false
property real imageWidth2: Math.max(1, source2.sourceSize.width) currentWallpaper.visible = root.actualTransitionType === "none"
property real imageHeight2: Math.max(1, source2.sourceSize.height) root.transitionProgress = 0.0
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
})
}
} }
} }
} }

View File

@@ -80,9 +80,15 @@ Singleton {
return ToplevelManager.toplevels.values return ToplevelManager.toplevels.values
} }
Component.onCompleted: { Timer {
detectCompositor() id: compositorInitTimer
NiriService.generateNiriLayoutConfig() interval: 100
running: true
repeat: false
onTriggered: {
detectCompositor()
Qt.callLater(() => NiriService.generateNiriLayoutConfig())
}
} }
function filterCurrentWorkspace(toplevels, screen) { function filterCurrentWorkspace(toplevels, screen) {

View File

@@ -28,11 +28,17 @@ Singleton {
} }
} }
Component.onCompleted: { Timer {
detectElogindProcess.running = true id: sessionInitTimer
detectHibernateProcess.running = true interval: 200
detectPrimeRunProcess.running = true running: true
console.log("SessionService: Native inhibitor available:", nativeInhibitorAvailable) repeat: false
onTriggered: {
detectElogindProcess.running = true
detectHibernateProcess.running = true
detectPrimeRunProcess.running = true
console.log("SessionService: Native inhibitor available:", nativeInhibitorAvailable)
}
} }

View File

@@ -1,3 +1,6 @@
//@ pragma Env QSG_RENDER_LOOP=threaded
//@ pragma UseQApplication
import QtQuick import QtQuick
import Quickshell import Quickshell
@@ -6,27 +9,17 @@ ShellRoot {
readonly property bool runGreeter: Quickshell.env("DMS_RUN_GREETER") === "1" || Quickshell.env("DMS_RUN_GREETER") === "true" 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 { Loader {
id: dmsShellLoader id: dmsShellLoader
asynchronous: false asynchronous: false
sourceComponent: shellComponent sourceComponent: DMSShell {}
active: !entrypoint.runGreeter active: !entrypoint.runGreeter
} }
Loader { Loader {
id: dmsGreeterLoader id: dmsGreeterLoader
asynchronous: false asynchronous: false
sourceComponent: greeterComponent sourceComponent: DMSGreeter {}
active: entrypoint.runGreeter active: entrypoint.runGreeter
} }
} }