From 5594ec27ffc5c8ea4d3ada397355cbf0f11d0e93 Mon Sep 17 00:00:00 2001 From: purian23 Date: Thu, 2 Jul 2026 14:08:52 -0400 Subject: [PATCH] fix(xray): fix dbar autohide w/xray blur Fixes #2733 --- quickshell/Common/SettingsData.qml | 17 ++++++++++++++++- quickshell/Services/HyprlandService.qml | 2 +- quickshell/Services/NiriService.qml | 2 +- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/quickshell/Common/SettingsData.qml b/quickshell/Common/SettingsData.qml index e6a21ccf7..b5ad22b66 100644 --- a/quickshell/Common/SettingsData.qml +++ b/quickshell/Common/SettingsData.qml @@ -1016,6 +1016,17 @@ Singleton { } ] + // Standalone bar xray is unsafe when windows can render beneath its surface + function _standaloneBarXrayAvailable(configs) { + const list = configs || []; + const activeBars = list.filter(c => c && c.enabled && (c.visible ?? true)); + const gapsOverride = (typeof CompositorService !== "undefined" && CompositorService.isHyprland) ? hyprlandLayoutGapsOverride : niriLayoutGapsOverride; + const layoutGaps = gapsOverride >= 0 ? gapsOverride : Math.max(4, (list[0]?.spacing ?? 4)); + return activeBars.every(c => !c.autoHide && !(c.useOverlayLayer ?? false) && (c.spacing ?? 4) + (c.bottomGap ?? 0) + layoutGaps >= 0); + } + + readonly property bool standaloneBarXrayAvailable: _standaloneBarXrayAvailable(barConfigs) + property bool desktopClockEnabled: false property string desktopClockStyle: "analog" property real desktopClockTransparency: 0.8 @@ -2418,13 +2429,17 @@ Singleton { if (index === -1) return; const positionChanged = updates.position !== undefined && configs[index].position !== updates.position; + const barXrayTargetWasAvailable = _standaloneBarXrayAvailable(configs); if (updates.autoHide === false || updates.visible === false) setBarIpcReveal(barId, false); Object.assign(configs[index], updates); - barConfigs = _sanitizeBarConfigsForConnectedFrame(configs).configs; + const sanitizedConfigs = _sanitizeBarConfigsForConnectedFrame(configs).configs; + barConfigs = sanitizedConfigs; updateBarConfigs(); + if (!frameEnabled && _standaloneBarXrayAvailable(sanitizedConfigs) !== barXrayTargetWasAvailable) + updateCompositorLayout(); if (positionChanged) { NotificationService.dismissAllPopups(); } diff --git a/quickshell/Services/HyprlandService.qml b/quickshell/Services/HyprlandService.qml index b10427ae0..70ef7b969 100644 --- a/quickshell/Services/HyprlandService.qml +++ b/quickshell/Services/HyprlandService.qml @@ -339,7 +339,7 @@ Singleton { const frameConnectedMode = frameEnabled && SettingsData.frameMode === "connected"; // Hyprland `xray = false` is still early-development; unset already samples real content, so only force xray=true // Connected frame mode has no separate bar/frame surface to target - const barFrameTargetNamespace = !frameEnabled ? "dms:bar" : (frameConnectedMode ? null : "dms:frame"); + const barFrameTargetNamespace = !frameEnabled ? (SettingsData.standaloneBarXrayAvailable ? "dms:bar" : null) : (frameConnectedMode ? null : "dms:frame"); let content = `-- Auto-generated by DMS — do not edit manually diff --git a/quickshell/Services/NiriService.qml b/quickshell/Services/NiriService.qml index e11bc50bf..3b97bee8c 100644 --- a/quickshell/Services/NiriService.qml +++ b/quickshell/Services/NiriService.qml @@ -1161,7 +1161,7 @@ Singleton { const frameEnabled = typeof SettingsData !== "undefined" && SettingsData.frameEnabled; const frameConnectedMode = frameEnabled && SettingsData.frameMode === "connected"; // Connected frame mode has no separate bar/frame surface to target - const barFrameTargetNamespace = !frameEnabled ? "dms:bar" : (frameConnectedMode ? null : "dms:frame"); + const barFrameTargetNamespace = !frameEnabled ? (SettingsData.standaloneBarXrayAvailable ? "dms:bar" : null) : (frameConnectedMode ? null : "dms:frame"); // Xray is niri's default blur, so only the off state needs a rule let xrayRules = "";