pragma Singleton import QtQuick import Quickshell import Quickshell.Io QtObject { id: root // Qt platform theme: respects qt6ct, KDE, qgnomeplatform, etc. property SystemPalette _palette: SystemPalette { colorGroup: SystemPalette.Active } // Portal-reported state. Defaults match "prefer dark, neutral accent". // 0 = no preference, 1 = dark, 2 = light (per xdg-desktop-portal spec). property int colorScheme: 1 property color portalAccent: "#5e9eff" property bool _portalLoaded: false readonly property bool dark: colorScheme !== 2 // Foreground is locked to the same dark/light axis as the panel // background — mixing portal color-scheme with SystemPalette text led to // unreadable combinations (dark bg + dark text) when the Qt platform // theme disagrees with the portal. readonly property color accent: Config.accentColor.length > 0 ? Config.accentColor : portalAccent readonly property color foreground: Config.foregroundColor.length > 0 ? Config.foregroundColor : (dark ? "#e6e6e6" : "#1a1a1a") readonly property color idle: Config.idleColor.length > 0 ? Config.idleColor : (dark ? Qt.rgba(1, 1, 1, 0.55) : Qt.rgba(0, 0, 0, 0.55)) readonly property color opaque_background: Config.backgroundColor.length > 0 ? Config.backgroundColor : (dark ? Qt.rgba(0, 0, 0, 0.8) : Qt.rgba(1, 1, 1, 0.9)) readonly property color overlay_strong: Config.overlayStrongColor.length > 0 ? Config.overlayStrongColor : (dark ? Qt.rgba(1, 1, 1, 0.14) : Qt.rgba(0, 0, 0, 0.10)) readonly property color overlay_weak: Config.overlayWeakColor.length > 0 ? Config.overlayWeakColor : (dark ? Qt.rgba(1, 1, 1, 0.06) : Qt.rgba(0, 0, 0, 0.04)) readonly property color border_subtle: Config.borderColor.length > 0 ? Config.borderColor : (dark ? Qt.rgba(1, 1, 1, 0.10) : Qt.rgba(0, 0, 0, 0.10)) readonly property string fontFamily: Config.fontFamily readonly property int fontSize: Config.fontSize readonly property int padding: Config.padding readonly property int spacing: Config.spacing readonly property int radius: Config.radius // Read the portal once at startup. The portal also emits a SettingChanged // signal we could subscribe to, but a one-shot read keeps us out of a // long-lived dbus monitor for a feature this rarely changes mid-session. property Process _portalProc: Process { running: true command: ["gdbus", "call", "--session", "--dest", "org.freedesktop.portal.Desktop", "--object-path", "/org/freedesktop/portal/desktop", "--method", "org.freedesktop.portal.Settings.ReadAll", "[\"org.freedesktop.appearance\"]"] stdout: StdioCollector { onStreamFinished: { // Output shape: // ({'org.freedesktop.appearance': {'color-scheme': , // 'accent-color': <(0.37, 0.62, 1.0)>}},) const text = this.text || ""; const cs = text.match(/'color-scheme':\s*/); if (cs) root.colorScheme = parseInt(cs[1], 10); const ac = text.match(/'accent-color':\s*<\(([-\d.eE+]+),\s*([-\d.eE+]+),\s*([-\d.eE+]+)\)>/); if (ac) { const r = parseFloat(ac[1]), g = parseFloat(ac[2]), b = parseFloat(ac[3]); if (r >= 0 && g >= 0 && b >= 0) root.portalAccent = Qt.rgba(r, g, b, 1); } root._portalLoaded = true; } } } }