mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-06-07 19:59:14 -04:00
fix(DankBar): Resolve tray freeze and wallpaper loss after DPMS resume (#2457)
Fixes #2354 Root cause (tray freeze): In clickThrough mode, the PanelWindow mask uses sectionRect() with mapToItem() to compute input regions. After DPMS resume, the PanelWindow is recreated with width=0, and mapToItem() returns wrong positions. The right section's implicitWidth doesn't change after creation (fixed-size tray icons), so the mask binding is never re-evaluated when the compositor sets the actual screen width. Adding barWindow.width as a binding dependency ensures the mask recalculates on resize. Root cause (wallpaper loss): Wallpaper PanelWindows are recreated by Variants during screen reconnection before the compositor finishes output initialization. The wallpaper Image renders at 0x0 dimensions, resulting in a black screen. Changes: - DankBarWindow: add barWindow.width dependency to clickThrough mask bindings - DMSShell: add surface recovery mechanism (screen reconnect + session resume) with progressive 2-pass timer (800ms + 2800ms) that recreates bar, Frame, wallpaper, and dock surfaces after the compositor is ready - WlrOutputService: re-request output state on session resume
This commit is contained in:
+111
-3
@@ -63,15 +63,27 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
property bool wallpaperSurfacesLoaded: true
|
||||||
|
|
||||||
Loader {
|
Loader {
|
||||||
id: blurredWallpaperBackgroundLoader
|
id: blurredWallpaperBackgroundLoader
|
||||||
active: SettingsData.blurredWallpaperLayer && CompositorService.isNiri
|
active: root.wallpaperSurfacesLoaded && SettingsData.blurredWallpaperLayer && CompositorService.isNiri
|
||||||
asynchronous: false
|
asynchronous: false
|
||||||
|
|
||||||
sourceComponent: BlurredWallpaperBackground {}
|
sourceComponent: BlurredWallpaperBackground {}
|
||||||
}
|
}
|
||||||
|
|
||||||
WallpaperBackground {}
|
DeferredAction {
|
||||||
|
id: wallpaperSurfaceReloadAction
|
||||||
|
onTriggered: root.wallpaperSurfacesLoaded = true
|
||||||
|
}
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
id: wallpaperBackgroundLoader
|
||||||
|
active: root.wallpaperSurfacesLoaded
|
||||||
|
asynchronous: false
|
||||||
|
sourceComponent: WallpaperBackground {}
|
||||||
|
}
|
||||||
|
|
||||||
DesktopWidgetLayer {}
|
DesktopWidgetLayer {}
|
||||||
|
|
||||||
@@ -168,6 +180,8 @@ Item {
|
|||||||
property bool barSurfacesLoaded: true
|
property bool barSurfacesLoaded: true
|
||||||
|
|
||||||
function recreateBarSurfaces() {
|
function recreateBarSurfaces() {
|
||||||
|
log.info("Recreating bar surfaces, screens:", Quickshell.screens.length,
|
||||||
|
Quickshell.screens.map(s => s.name).join(","));
|
||||||
if (barSurfacesLoaded)
|
if (barSurfacesLoaded)
|
||||||
barSurfacesLoaded = false;
|
barSurfacesLoaded = false;
|
||||||
barSurfaceReloadAction.schedule();
|
barSurfaceReloadAction.schedule();
|
||||||
@@ -217,7 +231,18 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Frame {}
|
property bool frameSurfacesLoaded: true
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
active: root.frameSurfacesLoaded
|
||||||
|
asynchronous: false
|
||||||
|
sourceComponent: Frame {}
|
||||||
|
}
|
||||||
|
|
||||||
|
DeferredAction {
|
||||||
|
id: frameSurfaceReloadAction
|
||||||
|
onTriggered: root.frameSurfacesLoaded = true
|
||||||
|
}
|
||||||
|
|
||||||
Repeater {
|
Repeater {
|
||||||
id: dankBarRepeater
|
id: dankBarRepeater
|
||||||
@@ -301,6 +326,81 @@ Item {
|
|||||||
onTriggered: root.osdSurfacesLoaded = true
|
onTriggered: root.osdSurfacesLoaded = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
property bool hadRealScreen: true
|
||||||
|
|
||||||
|
function _hasRealScreen() {
|
||||||
|
for (let i = 0; i < Quickshell.screens.length; i++) {
|
||||||
|
if (Quickshell.screens[i].name.length > 0)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function triggerSurfaceRecovery(source) {
|
||||||
|
log.info("Surface recovery triggered by:", source,
|
||||||
|
"screens:", Quickshell.screens.length,
|
||||||
|
Quickshell.screens.map(s => s.name).join(","),
|
||||||
|
"barLoaded:", root.barSurfacesLoaded,
|
||||||
|
"frameLoaded:", root.frameSurfacesLoaded,
|
||||||
|
"dockEnabled:", root.dockEnabled);
|
||||||
|
surfaceResumeRecoveryTimer.pass = 0;
|
||||||
|
surfaceResumeRecoveryTimer.interval = 800;
|
||||||
|
surfaceResumeRecoveryTimer.restart();
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: Quickshell
|
||||||
|
function onScreensChanged() {
|
||||||
|
const hasReal = root._hasRealScreen();
|
||||||
|
log.info("Screens changed:", Quickshell.screens.length,
|
||||||
|
Quickshell.screens.map(s => "'" + s.name + "'").join(","),
|
||||||
|
"hasReal:", hasReal, "hadReal:", root.hadRealScreen);
|
||||||
|
if (!root.hadRealScreen && hasReal) {
|
||||||
|
log.info("Real screen reappeared after placeholder state, triggering surface recovery");
|
||||||
|
root.triggerSurfaceRecovery("screen-reconnect");
|
||||||
|
}
|
||||||
|
root.hadRealScreen = hasReal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Timer {
|
||||||
|
id: surfaceResumeRecoveryTimer
|
||||||
|
interval: 800
|
||||||
|
repeat: false
|
||||||
|
property int pass: 0
|
||||||
|
onTriggered: {
|
||||||
|
pass++;
|
||||||
|
log.info("Surface recovery pass", pass,
|
||||||
|
"screens:", Quickshell.screens.length,
|
||||||
|
Quickshell.screens.map(s => s.name).join(","));
|
||||||
|
|
||||||
|
root.recreateBarSurfaces();
|
||||||
|
|
||||||
|
if (root.frameSurfacesLoaded) {
|
||||||
|
root.frameSurfacesLoaded = false;
|
||||||
|
frameSurfaceReloadAction.schedule();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (root.wallpaperSurfacesLoaded) {
|
||||||
|
root.wallpaperSurfacesLoaded = false;
|
||||||
|
wallpaperSurfaceReloadAction.schedule();
|
||||||
|
}
|
||||||
|
|
||||||
|
root.dockEnabled = false;
|
||||||
|
Qt.callLater(() => {
|
||||||
|
root.dockEnabled = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (pass < 2) {
|
||||||
|
interval = 2000;
|
||||||
|
restart();
|
||||||
|
} else {
|
||||||
|
pass = 0;
|
||||||
|
interval = 800;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
dockRecreateDebounce.start();
|
dockRecreateDebounce.start();
|
||||||
// Force PolkitService singleton to initialize
|
// Force PolkitService singleton to initialize
|
||||||
@@ -887,9 +987,17 @@ Item {
|
|||||||
target: SessionService
|
target: SessionService
|
||||||
|
|
||||||
function onSessionResumed() {
|
function onSessionResumed() {
|
||||||
|
log.info("Session resumed: screens:", Quickshell.screens.length,
|
||||||
|
Quickshell.screens.map(s => s.name).join(","),
|
||||||
|
"barLoaded:", root.barSurfacesLoaded,
|
||||||
|
"frameLoaded:", root.frameSurfacesLoaded,
|
||||||
|
"dockEnabled:", root.dockEnabled);
|
||||||
|
|
||||||
root.pendingOsdResumeReloads = 2;
|
root.pendingOsdResumeReloads = 2;
|
||||||
osdResumeRecreateTimer.interval = 400;
|
osdResumeRecreateTimer.interval = 400;
|
||||||
osdResumeRecreateTimer.restart();
|
osdResumeRecreateTimer.restart();
|
||||||
|
|
||||||
|
root.triggerSurfaceRecovery("sessionResumed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -726,7 +726,7 @@ PanelWindow {
|
|||||||
item: clickThroughEnabled ? null : inputMask
|
item: clickThroughEnabled ? null : inputMask
|
||||||
|
|
||||||
Region {
|
Region {
|
||||||
readonly property var r: barWindow.clickThroughEnabled ? barWindow.sectionRect(barWindow._leftSection, false, barWindow._revealProgress) : {
|
readonly property var r: barWindow.clickThroughEnabled ? barWindow.sectionRect(barWindow._leftSection, false, barWindow._revealProgress + barWindow.width * 0) : {
|
||||||
"x": 0,
|
"x": 0,
|
||||||
"y": 0,
|
"y": 0,
|
||||||
"w": 0,
|
"w": 0,
|
||||||
@@ -739,7 +739,7 @@ PanelWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Region {
|
Region {
|
||||||
readonly property var r: barWindow.clickThroughEnabled ? barWindow.sectionRect(barWindow._centerSection, true, barWindow._revealProgress) : {
|
readonly property var r: barWindow.clickThroughEnabled ? barWindow.sectionRect(barWindow._centerSection, true, barWindow._revealProgress + barWindow.width * 0) : {
|
||||||
"x": 0,
|
"x": 0,
|
||||||
"y": 0,
|
"y": 0,
|
||||||
"w": 0,
|
"w": 0,
|
||||||
@@ -752,7 +752,7 @@ PanelWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Region {
|
Region {
|
||||||
readonly property var r: barWindow.clickThroughEnabled ? barWindow.sectionRect(barWindow._rightSection, false, barWindow._revealProgress) : {
|
readonly property var r: barWindow.clickThroughEnabled ? barWindow.sectionRect(barWindow._rightSection, false, barWindow._revealProgress + barWindow.width * 0) : {
|
||||||
"x": 0,
|
"x": 0,
|
||||||
"y": 0,
|
"y": 0,
|
||||||
"w": 0,
|
"w": 0,
|
||||||
|
|||||||
@@ -345,4 +345,13 @@ Singleton {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: SessionService
|
||||||
|
|
||||||
|
function onSessionResumed() {
|
||||||
|
log.info("Session resumed, re-requesting output state, current outputs:", outputs.length);
|
||||||
|
requestState();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user