From 31e60a3df5e0412dcb197afa9d5521485b22ba0d Mon Sep 17 00:00:00 2001 From: purian23 Date: Sun, 3 May 2026 22:03:02 -0400 Subject: [PATCH] fix(FrameMode): Update logic to hide the dbar/dock upon maximized windows/apps/games --- quickshell/Modules/DankBar/DankBarWindow.qml | 50 ++++++++--------- quickshell/Modules/Dock/Dock.qml | 20 ++++++- quickshell/Services/CompositorService.qml | 57 ++++++++++++++++++++ 3 files changed, 99 insertions(+), 28 deletions(-) diff --git a/quickshell/Modules/DankBar/DankBarWindow.qml b/quickshell/Modules/DankBar/DankBarWindow.qml index c93c1db3..14722c09 100644 --- a/quickshell/Modules/DankBar/DankBarWindow.qml +++ b/quickshell/Modules/DankBar/DankBarWindow.qml @@ -97,11 +97,14 @@ PanelWindow { case "overlay": return WlrLayer.Overlay; case "background": - return WlrLayer.background; + return WlrLayer.Background; + case "top": + return WlrLayer.Top; default: // Elevate to Overlay when Frame is enabled so the bar stays above - // the FrameWindow (WlrLayer.Top) when it is re-mapped on mode switch. - return SettingsData.frameEnabled ? WlrLayer.Overlay : WlrLayer.Top; + // the FrameWindow (WlrLayer.Top) when it is re-mapped on mode switch, + // but drop back to Top while a true fullscreen app owns this screen. + return SettingsData.frameEnabled && !barWindow.hasFullscreenToplevel ? WlrLayer.Overlay : WlrLayer.Top; } } @@ -307,22 +310,7 @@ PanelWindow { } function _updateHasFullscreenToplevel() { - if (!CompositorService.isHyprland) { - hasFullscreenToplevel = false; - return; - } - - const filtered = CompositorService.filterCurrentWorkspace(CompositorService.sortedToplevels, screenName); - for (let i = 0; i < filtered.length; i++) { - if (filtered[i]?.fullscreen) { - // On niri, fullscreen windows in inactive columns should not hide the bar - if (CompositorService.isNiri && !filtered[i]?.activated) - continue; - hasFullscreenToplevel = true; - return; - } - } - hasFullscreenToplevel = false; + hasFullscreenToplevel = CompositorService.hasFullscreenToplevelOnScreen(screenName); } function _updateShouldHideForWindows() { @@ -536,6 +524,7 @@ PanelWindow { updateGpuTempConfig(); _updateBackgroundAlpha(); _updateHasMaximizedToplevel(); + _updateHasFullscreenToplevel(); _updateShouldHideForWindows(); inhibitorInitTimer.start(); @@ -646,6 +635,13 @@ PanelWindow { } } + Connections { + target: ToplevelManager + function onActiveToplevelChanged() { + barWindow._updateHasFullscreenToplevel(); + } + } + Connections { function onNvidiaGpuTempEnabledChanged() { barWindow.updateGpuTempConfig(); @@ -665,7 +661,7 @@ PanelWindow { anchors.left: !isVertical ? true : (barPos === SettingsData.Position.Left) anchors.right: !isVertical ? true : (barPos === SettingsData.Position.Right) - exclusiveZone: (!(barConfig?.visible ?? true) || topBarCore.autoHide) ? -1 : (barWindow.effectiveBarThickness + effectiveSpacing + (Theme.isConnectedEffect ? 0 : (barConfig?.bottomGap ?? 0))) + exclusiveZone: (barWindow.hasFullscreenToplevel || !(barConfig?.visible ?? true) || topBarCore.autoHide) ? -1 : (barWindow.effectiveBarThickness + effectiveSpacing + (Theme.isConnectedEffect ? 0 : (barConfig?.bottomGap ?? 0))) Item { id: inputMask @@ -674,9 +670,9 @@ PanelWindow { readonly property bool inOverviewWithShow: CompositorService.isNiri && NiriService.inOverview && barWindow.effectiveOpenOnOverview readonly property bool effectiveVisible: (barConfig?.visible ?? true) || inOverviewWithShow - readonly property bool showing: effectiveVisible && (topBarCore.reveal || inOverviewWithShow || !topBarCore.autoHide) + readonly property bool showing: effectiveVisible && !barWindow.hasFullscreenToplevel && (topBarCore.reveal || inOverviewWithShow || !topBarCore.autoHide) - readonly property int maskThickness: showing ? barThickness : 1 + readonly property int maskThickness: barWindow.hasFullscreenToplevel ? 0 : (showing ? barThickness : 1) x: { if (!axis.isVertical) { @@ -813,13 +809,13 @@ PanelWindow { } property bool reveal: { + if (barWindow.hasFullscreenToplevel) + return false; + const inOverviewWithShow = CompositorService.isNiri && NiriService.inOverview && barWindow.effectiveOpenOnOverview; if (inOverviewWithShow) return true; - if (barWindow.hasFullscreenToplevel) - return false; - const showOnWindowsSetting = barConfig?.showOnWindowsOpen ?? false; if (showOnWindowsSetting && autoHide && (CompositorService.isNiri || CompositorService.isHyprland)) { if (barWindow.shouldHideForWindows) @@ -911,9 +907,9 @@ PanelWindow { bottom: barWindow.isVertical ? parent.bottom : undefined } readonly property bool inOverview: CompositorService.isNiri && NiriService.inOverview && barWindow.effectiveOpenOnOverview - hoverEnabled: (barConfig?.autoHide ?? false) && !inOverview && !topBarCore.hasActivePopout + hoverEnabled: (barConfig?.autoHide ?? false) && !inOverview && !barWindow.hasFullscreenToplevel && !topBarCore.hasActivePopout acceptedButtons: Qt.NoButton - enabled: (barConfig?.autoHide ?? false) && !inOverview + enabled: (barConfig?.autoHide ?? false) && !inOverview && !barWindow.hasFullscreenToplevel Item { id: topBarContainer diff --git a/quickshell/Modules/Dock/Dock.qml b/quickshell/Modules/Dock/Dock.qml index 6e621bfd..fe152ef9 100644 --- a/quickshell/Modules/Dock/Dock.qml +++ b/quickshell/Modules/Dock/Dock.qml @@ -29,7 +29,7 @@ Variants { } WlrLayershell.namespace: "dms:dock" - WlrLayershell.layer: SettingsData.frameEnabled ? WlrLayer.Overlay : WlrLayer.Top + WlrLayershell.layer: SettingsData.frameEnabled && !dock.hasFullscreenToplevel ? WlrLayer.Overlay : WlrLayer.Top readonly property bool isVertical: SettingsData.dockPosition === SettingsData.Position.Left || SettingsData.dockPosition === SettingsData.Position.Right @@ -163,6 +163,18 @@ Variants { } readonly property string _dockScreenName: dock.modelData ? dock.modelData.name : (dock.screen ? dock.screen.name : "") + readonly property bool hasFullscreenToplevel: { + CompositorService.sortedToplevels; + ToplevelManager.activeToplevel; + if (CompositorService.isNiri) { + NiriService.currentOutput; + NiriService.windows; + NiriService.allWorkspaces; + } + if (CompositorService.isHyprland) + Hyprland.focusedWorkspace; + return CompositorService.hasFullscreenToplevelOnScreen(dock._dockScreenName); + } function _syncDockChromeState() { if (!dock._dockScreenName) @@ -353,6 +365,9 @@ Variants { if (_modalRetractActive) return false; + if (dock.hasFullscreenToplevel) + return false; + if (CompositorService.isNiri && NiriService.inOverview && SettingsData.dockOpenOnOverview) { return true; } @@ -384,6 +399,7 @@ Variants { onVisibleChanged: dock._syncDockChromeState() onHasAppsChanged: dock._syncDockChromeState() onConnectedBarSideChanged: dock._syncDockChromeState() + onHasFullscreenToplevelChanged: dock._syncDockChromeState() Connections { target: SettingsData @@ -409,6 +425,8 @@ Variants { color: "transparent" exclusiveZone: { + if (dock.hasFullscreenToplevel) + return -1; if (!SettingsData.showDock || autoHide) return -1; if (barSpacing > 0) diff --git a/quickshell/Services/CompositorService.qml b/quickshell/Services/CompositorService.qml index 541148d0..617fcfbe 100644 --- a/quickshell/Services/CompositorService.qml +++ b/quickshell/Services/CompositorService.qml @@ -391,6 +391,63 @@ Singleton { return toplevels; } + function _screenName(screenOrName) { + if (typeof screenOrName === "string") + return screenOrName; + return screenOrName?.name ?? ""; + } + + function _toplevelOnScreen(toplevel, screenName) { + if (!toplevel || !screenName) + return false; + const screens = toplevel.screens; + if (!screens) + return false; + for (let i = 0; i < screens.length; i++) { + if (screens[i]?.name === screenName) + return true; + } + return false; + } + + function hasFullscreenToplevelOnScreen(screenOrName) { + const screenName = _screenName(screenOrName); + if (!screenName) + return false; + + if (isNiri) { + const active = ToplevelManager.activeToplevel; + if (active?.fullscreen && active?.activated && NiriService.currentOutput === screenName) + return true; + + const filtered = filterCurrentWorkspace(sortedToplevels, screenName); + for (let i = 0; i < filtered.length; i++) { + const toplevel = filtered[i]; + if (toplevel?.fullscreen && toplevel?.activated) + return true; + } + return false; + } + + if (isHyprland) { + const filtered = filterCurrentWorkspace(sortedToplevels, screenName); + for (let i = 0; i < filtered.length; i++) { + if (filtered[i]?.fullscreen) + return true; + } + return false; + } + + if (!ToplevelManager.toplevels?.values) + return false; + + for (const toplevel of ToplevelManager.toplevels.values) { + if (toplevel?.fullscreen && _toplevelOnScreen(toplevel, screenName)) + return true; + } + return false; + } + function filterHyprlandCurrentDisplaySafe(toplevels, screenName) { if (!toplevels || toplevels.length === 0 || !Hyprland.toplevels) return toplevels;