From 88447fbcef961e266a899e256867054d7ba26fae Mon Sep 17 00:00:00 2001 From: Ly-sec Date: Thu, 21 Aug 2025 16:29:42 +0200 Subject: [PATCH] Possible fix for QS crash on single monitor wake --- Commons/Icons.qml | 42 +++++++++++++++++++++++++++ Modules/Background/ScreenCorners.qml | 4 +-- Modules/Bar/ActiveWindow.qml | 8 +---- Modules/Bar/Brightness.qml | 34 ++++++++++++++-------- Modules/Dock/Dock.qml | 3 +- Modules/Launcher/Launcher.qml | 2 +- Modules/SettingsPanel/Tabs/BarTab.qml | 2 +- 7 files changed, 70 insertions(+), 25 deletions(-) create mode 100644 Commons/Icons.qml diff --git a/Commons/Icons.qml b/Commons/Icons.qml new file mode 100644 index 0000000..463fa78 --- /dev/null +++ b/Commons/Icons.qml @@ -0,0 +1,42 @@ +pragma Singleton + +import QtQuick +import Quickshell + +Singleton { + id: icons + + function iconFromName(iconName, fallbackName) { + const fallback = fallbackName || "application-x-executable" + try { + if (iconName && typeof Quickshell !== 'undefined' && Quickshell.iconPath) { + const p = Quickshell.iconPath(iconName, fallback) + if (p && p !== "") return p + } + } catch (e) { + // ignore and fall back + } + try { + return Quickshell.iconPath ? (Quickshell.iconPath(fallback, true) || "") : "" + } catch (e2) { + return "" + } + } + + // Resolve icon path for a DesktopEntries appId - safe on missing entries + function iconForAppId(appId, fallbackName) { + const fallback = fallbackName || "application-x-executable" + if (!appId) return iconFromName(fallback, fallback) + try { + if (typeof DesktopEntries === 'undefined' || !DesktopEntries.byId) + return iconFromName(fallback, fallback) + const entry = DesktopEntries.byId(appId) + const name = entry && entry.icon ? entry.icon : "" + return iconFromName(name || fallback, fallback) + } catch (e) { + return iconFromName(fallback, fallback) + } + } +} + + diff --git a/Modules/Background/ScreenCorners.qml b/Modules/Background/ScreenCorners.qml index ce984a7..e10ba45 100644 --- a/Modules/Background/ScreenCorners.qml +++ b/Modules/Background/ScreenCorners.qml @@ -43,9 +43,9 @@ Loader { } margins { - top: (Settings.data.bar.monitors.includes(modelData.name) || (Settings.data.bar.monitors.length === 0)) + top: ((modelData && Settings.data.bar.monitors.includes(modelData.name)) || (Settings.data.bar.monitors.length === 0)) && Settings.data.bar.position === "top" ? Math.floor(Style.barHeight * scaling) : 0 - bottom: (Settings.data.bar.monitors.includes(modelData.name) || (Settings.data.bar.monitors.length === 0)) + bottom: ((modelData && Settings.data.bar.monitors.includes(modelData.name)) || (Settings.data.bar.monitors.length === 0)) && Settings.data.bar.position === "bottom" ? Math.floor(Style.barHeight * scaling) : 0 } diff --git a/Modules/Bar/ActiveWindow.qml b/Modules/Bar/ActiveWindow.qml index 257f47b..ec7b42b 100644 --- a/Modules/Bar/ActiveWindow.qml +++ b/Modules/Bar/ActiveWindow.qml @@ -49,13 +49,7 @@ Row { if (!focusedWindow || !focusedWindow.appId) return "" - // DesktopEntries.byId may return null for unknown apps; guard accordingly - if (typeof DesktopEntries === 'undefined' || !DesktopEntries.byId) - return "" - const entry = DesktopEntries.byId(focusedWindow.appId) - const iconName = entry && entry.icon ? entry.icon : "" - const iconPath = iconName ? Quickshell.iconPath(iconName) : "" - return iconPath || "" + return Icons.iconForAppId(focusedWindow.appId) } // A hidden text element to safely measure the full title width diff --git a/Modules/Bar/Brightness.qml b/Modules/Bar/Brightness.qml index 2388f42..c6a40aa 100644 --- a/Modules/Bar/Brightness.qml +++ b/Modules/Bar/Brightness.qml @@ -10,24 +10,30 @@ Item { width: pill.width height: pill.height - visible: Settings.data.bar.showBrightness && firstBrightnessReceived + visible: Settings.data.bar.showBrightness && firstBrightnessReceived && getMonitor() !== null // Used to avoid opening the pill on Quickshell startup property bool firstBrightnessReceived: false + function getMonitor() { + return BrightnessService.getMonitorForScreen(screen) || null + } + function getIcon() { - var brightness = BrightnessService.getMonitorForScreen(screen).brightness - return brightness <= 0 ? "brightness_1" : brightness < 0.33 ? "brightness_low" : brightness - < 0.66 ? "brightness_medium" : "brightness_high" + var monitor = getMonitor() + var brightness = monitor ? monitor.brightness : 0 + return brightness <= 0 ? "brightness_1" : brightness < 0.33 ? "brightness_low" : brightness < 0.66 ? "brightness_medium" : "brightness_high" } // Connection used to open the pill when brightness changes Connections { - target: BrightnessService.getMonitorForScreen(screen) + target: getMonitor() + ignoreUnknownSignals: true function onBrightnessUpdated() { Logger.log("Bar-Brightness", "OnBrightnessUpdated") - - var monitor = BrightnessService.getMonitorForScreen(screen) + var monitor = getMonitor() + if (!monitor) + return var currentBrightness = monitor.brightness // Ignore if this is the first time or if brightness hasn't actually changed @@ -52,15 +58,19 @@ Item { iconCircleColor: Color.mPrimary collapsedIconColor: Color.mOnSurface autoHide: false // Important to be false so we can hover as long as we want - text: Math.round(BrightnessService.getMonitorForScreen(screen).brightness * 100) + "%" + text: { + var monitor = getMonitor() + return monitor ? (Math.round(monitor.brightness * 100) + "%") : "" + } tooltipText: { - var monitor = BrightnessService.getMonitorForScreen(screen) - return "Brightness: " + Math.round(monitor.brightness * 100) + "%\nMethod: " + monitor.method - + "\nLeft click for advanced settings.\nScroll up/down to change brightness." + var monitor = getMonitor() + if (!monitor) return "" + return "Brightness: " + Math.round(monitor.brightness * 100) + "%\nMethod: " + monitor.method + "\nLeft click for advanced settings.\nScroll up/down to change brightness." } onWheel: function (angle) { - var monitor = BrightnessService.getMonitorForScreen(screen) + var monitor = getMonitor() + if (!monitor) return if (angle > 0) { monitor.increaseBrightness() } else if (angle < 0) { diff --git a/Modules/Dock/Dock.qml b/Modules/Dock/Dock.qml index e27b389..450ef81 100644 --- a/Modules/Dock/Dock.qml +++ b/Modules/Dock/Dock.qml @@ -159,8 +159,7 @@ Loader { function getAppIcon(toplevel: Toplevel): string { if (!toplevel) return "" - let icon = Quickshell.iconPath(DesktopEntries.byId(toplevel.appId?.toLowerCase()).icon) - return icon || Quickshell.iconPath("application-x-executable", true) + return Icons.iconForAppId(toplevel.appId?.toLowerCase()) } Row { diff --git a/Modules/Launcher/Launcher.qml b/Modules/Launcher/Launcher.qml index 9991f1a..3913126 100644 --- a/Modules/Launcher/Launcher.qml +++ b/Modules/Launcher/Launcher.qml @@ -418,7 +418,7 @@ NPanel { anchors.fill: parent anchors.margins: Style.marginXS * scaling asynchronous: true - source: modelData.isCalculator ? "" : modelData.isClipboard ? "" : modelData.isCommand ? modelData.icon : (modelData.icon ? Quickshell.iconPath(modelData.icon, "application-x-executable") : "") + source: modelData.isCalculator ? "" : modelData.isClipboard ? "" : modelData.isCommand ? modelData.icon : Icons.iconFromName(modelData.icon, "application-x-executable") visible: (modelData.isCalculator || modelData.isClipboard || modelData.isCommand || parent.iconLoaded) && modelData.type !== 'image' } diff --git a/Modules/SettingsPanel/Tabs/BarTab.qml b/Modules/SettingsPanel/Tabs/BarTab.qml index 9a8a030..8c85081 100644 --- a/Modules/SettingsPanel/Tabs/BarTab.qml +++ b/Modules/SettingsPanel/Tabs/BarTab.qml @@ -134,7 +134,7 @@ ColumnLayout { NToggle { label: "Show Battery Percentage" - description: "Show battery percentage at all times (otherwise only when charging or low)." + description: "Show battery percentage at all times." checked: Settings.data.bar.alwaysShowBatteryPercentage onToggled: checked => { Settings.data.bar.alwaysShowBatteryPercentage = checked