1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-04-30 09:32:05 -04:00

fix(quickshell): restore night mode and OSD surfaces after resume (#2254)

This commit is contained in:
Kristijan Ribarić
2026-04-22 16:08:50 +02:00
committed by GitHub
parent c6ed64b24e
commit b87c36d29e
4 changed files with 250 additions and 73 deletions

View File

@@ -346,12 +346,11 @@ Singleton {
function onLoginctlEvent(event) {
if (!SessionData.themeModeAutoEnabled)
return;
if (event.event === "unlock" || event.event === "resume") {
if (!themeAutoBackendAvailable()) {
root.evaluateThemeMode();
return;
}
DMSService.sendRequest("theme.auto.trigger", {});
if (typeof SettingsData !== "undefined" && SettingsData.loginctlLockIntegration)
return;
const eventType = String(event?.type || event?.event || "").toLowerCase();
if (eventType === "unlock") {
root.triggerThemeAutomationRefresh();
}
}
@@ -414,6 +413,27 @@ Singleton {
}
}
Connections {
target: SessionService
enabled: typeof SessionService !== "undefined" && typeof SessionData !== "undefined" && SessionData.themeModeAutoEnabled
function onSessionUnlocked() {
root.triggerThemeAutomationRefresh();
}
function onSessionResumed() {
root.triggerThemeAutomationRefresh();
}
}
function triggerThemeAutomationRefresh() {
if (!themeAutoBackendAvailable()) {
root.evaluateThemeMode();
return;
}
DMSService.sendRequest("theme.auto.trigger", {});
}
function applyGreeterTheme(themeName) {
switchTheme(themeName, false, false);
if (themeName === dynamic && dynamicColorsFileView.path) {

View File

@@ -27,6 +27,15 @@ import qs.Services
Item {
id: root
property bool osdSurfacesLoaded: true
property int pendingOsdResumeReloads: 0
function recreateOsdSurfaces() {
OSDManager.currentOSDsByScreen = ({});
osdSurfacesLoaded = false;
osdSurfaceReloadTimer.restart();
}
Instantiator {
id: daemonPluginInstantiator
asynchronous: true
@@ -232,6 +241,32 @@ Item {
}
}
Timer {
id: osdResumeRecreateTimer
interval: 400
repeat: false
onTriggered: {
root.recreateOsdSurfaces();
if (root.pendingOsdResumeReloads > 1) {
root.pendingOsdResumeReloads--;
interval = 1400;
restart();
return;
}
root.pendingOsdResumeReloads = 0;
interval = 400;
}
}
Timer {
id: osdSurfaceReloadTimer
interval: 120
repeat: false
onTriggered: root.osdSurfacesLoaded = true
}
Component.onCompleted: {
dockRecreateDebounce.start();
// Force PolkitService singleton to initialize
@@ -749,6 +784,16 @@ Item {
}
}
Connections {
target: SessionService
function onSessionResumed() {
root.pendingOsdResumeReloads = 2;
osdResumeRecreateTimer.interval = 400;
osdResumeRecreateTimer.restart();
}
}
DankColorPickerModal {
id: colorPickerModal
@@ -923,51 +968,85 @@ Item {
}
}
Variants {
model: SettingsData.getFilteredScreens("osd")
Loader {
id: osdSurfacesLoader
active: root.osdSurfacesLoaded
asynchronous: false
delegate: VolumeOSD {
modelData: item
}
}
sourceComponent: Component {
Item {
Variants {
model: SettingsData.getFilteredScreens("osd")
Variants {
model: SettingsData.getFilteredScreens("osd")
delegate: VolumeOSD {
modelData: item
}
}
delegate: MediaVolumeOSD {
modelData: item
}
}
Variants {
model: SettingsData.getFilteredScreens("osd")
Variants {
model: SettingsData.getFilteredScreens("osd")
delegate: MediaVolumeOSD {
modelData: item
}
}
delegate: MediaPlaybackOSD {
modelData: item
}
}
Variants {
model: SettingsData.getFilteredScreens("osd")
Variants {
model: SettingsData.getFilteredScreens("osd")
delegate: MediaPlaybackOSD {
modelData: item
}
}
delegate: MicMuteOSD {
modelData: item
}
}
Variants {
model: SettingsData.getFilteredScreens("osd")
Variants {
model: SettingsData.getFilteredScreens("osd")
delegate: MicMuteOSD {
modelData: item
}
}
delegate: BrightnessOSD {
modelData: item
}
}
Variants {
model: SettingsData.getFilteredScreens("osd")
Variants {
model: SettingsData.getFilteredScreens("osd")
delegate: BrightnessOSD {
modelData: item
}
}
delegate: IdleInhibitorOSD {
modelData: item
Variants {
model: SettingsData.getFilteredScreens("osd")
delegate: IdleInhibitorOSD {
modelData: item
}
}
Variants {
model: SettingsData.osdPowerProfileEnabled ? SettingsData.getFilteredScreens("osd") : []
delegate: PowerProfileOSD {
modelData: item
}
}
Variants {
model: SettingsData.getFilteredScreens("osd")
delegate: CapsLockOSD {
modelData: item
}
}
Variants {
model: SettingsData.getFilteredScreens("osd")
delegate: AudioOutputOSD {
modelData: item
}
}
}
}
}
@@ -977,30 +1056,6 @@ Item {
source: "Services/PowerProfileWatcher.qml"
}
Variants {
model: SettingsData.osdPowerProfileEnabled ? SettingsData.getFilteredScreens("osd") : []
delegate: PowerProfileOSD {
modelData: item
}
}
Variants {
model: SettingsData.getFilteredScreens("osd")
delegate: CapsLockOSD {
modelData: item
}
}
Variants {
model: SettingsData.getFilteredScreens("osd")
delegate: AudioOutputOSD {
modelData: item
}
}
LazyLoader {
id: hyprlandOverviewLoader
active: CompositorService.isHyprland

View File

@@ -40,6 +40,7 @@ Singleton {
property bool nightModeEnabled: false
property bool automationAvailable: false
property bool gammaControlAvailable: false
property int resumeRecoveryAttempt: 0
property var gammaState: ({})
property int gammaCurrentTemp: gammaState?.currentTemp ?? 0
@@ -672,6 +673,15 @@ Singleton {
}
}
function runResumeRecoveryPass() {
checkGammaControlAvailability();
rescanDevices();
if (nightModeEnabled) {
evaluateNightMode();
}
}
function checkGammaControlAvailability() {
if (!DMSService.isConnected) {
return;
@@ -730,6 +740,26 @@ Singleton {
}
}
Timer {
id: resumeRecoveryTimer
interval: 400
repeat: false
onTriggered: {
runResumeRecoveryPass();
resumeRecoveryAttempt++;
if (resumeRecoveryAttempt < 3) {
interval = resumeRecoveryAttempt === 1 ? 1400 : 2600;
restart();
return;
}
resumeRecoveryAttempt = 0;
interval = 400;
}
}
function rescanDevices() {
if (!DMSService.isConnected) {
return;
@@ -815,19 +845,23 @@ Singleton {
updateSingleDevice(device);
}
function onLoginctlEvent(event) {
if (event.event === "unlock" || event.event === "resume") {
suppressOsd = true;
osdSuppressTimer.restart();
evaluateNightMode();
}
}
function onGammaStateUpdate(data) {
root.gammaState = data;
}
}
Connections {
target: SessionService
function onSessionResumed() {
suppressOsd = true;
osdSuppressTimer.restart();
resumeRecoveryAttempt = 0;
resumeRecoveryTimer.interval = 400;
resumeRecoveryTimer.restart();
}
}
// Session Data Connections
Connections {
target: SessionData

View File

@@ -48,6 +48,9 @@ Singleton {
signal loginctlStateChanged
property bool stateInitialized: false
property string prepareForSleepSubscriptionId: ""
property bool prepareForSleepSubscriptionPending: false
property double lastResumeSignalTimestamp: 0
readonly property string socketPath: Quickshell.env("DMS_SOCKET")
@@ -463,10 +466,13 @@ Singleton {
function onConnectionStateChanged() {
if (DMSService.isConnected) {
checkDMSCapabilities();
} else {
clearPrepareForSleepSubscriptionState();
}
}
function onCapabilitiesReceived() {
checkDMSCapabilities();
syncSleepInhibitor();
}
}
@@ -478,6 +484,13 @@ Singleton {
function onCapabilitiesChanged() {
checkDMSCapabilities();
}
function onDbusSignalReceived(subscriptionId, data) {
if (subscriptionId !== prepareForSleepSubscriptionId) {
return;
}
handlePrepareForSleepSignal(data);
}
}
Connections {
@@ -539,6 +552,61 @@ Singleton {
loginctlAvailable = false;
console.log("SessionService: loginctl capability not available in DMS");
}
if (DMSService.capabilities.includes("dbus")) {
ensurePrepareForSleepSubscription();
} else {
clearPrepareForSleepSubscriptionState();
}
}
function clearPrepareForSleepSubscriptionState() {
prepareForSleepSubscriptionId = "";
prepareForSleepSubscriptionPending = false;
}
function ensurePrepareForSleepSubscription() {
if (!DMSService.isConnected || !DMSService.capabilities.includes("dbus")) {
return;
}
if (prepareForSleepSubscriptionId || prepareForSleepSubscriptionPending) {
return;
}
prepareForSleepSubscriptionPending = true;
DMSService.dbusSubscribe("system", "org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", "PrepareForSleep", response => {
prepareForSleepSubscriptionPending = false;
if (response.error) {
console.warn("SessionService: Failed to subscribe to PrepareForSleep:", response.error);
return;
}
prepareForSleepSubscriptionId = response.result?.subscriptionId || "";
});
}
function emitSessionResumedOnce() {
const now = Date.now();
if ((now - lastResumeSignalTimestamp) < 1000) {
return;
}
lastResumeSignalTimestamp = now;
sessionResumed();
}
function handlePrepareForSleepSignal(data) {
if (!data?.body || data.body.length === 0) {
return;
}
const wasSleeping = preparingForSleep;
preparingForSleep = data.body[0] === true;
if (wasSleeping && !preparingForSleep) {
emitSessionResumedOnce();
}
}
function getLoginctlState() {
@@ -604,7 +672,7 @@ Singleton {
}
if (wasSleeping && !preparingForSleep) {
sessionResumed();
emitSessionResumedOnce();
}
loginctlStateChanged();