From 9981fcf529d18c530a15d14f300df0c5232f9df1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hu=E1=BB=B3nh=20Thi=E1=BB=87n=20L=E1=BB=99c?= Date: Thu, 6 Aug 2026 06:19:47 +0700 Subject: [PATCH] fix(slideout): yield keyboard focus when modal is open on same screen (#2902) DankSlideout always held WlrKeyboardFocus.OnDemand regardless of modals, causing Notepad to steal focus back when Launcher was opened. ModalManager: clone currentModalsByScreen on mutation so QML bindings re-evaluate when modals open/close. DankSlideout: set keyboardFocus to None while a modal is active on the same screen, letting the modal (launcher) claim focus exclusively. --- quickshell/Common/ModalManager.qml | 13 +++++++++++-- quickshell/Widgets/DankSlideout.qml | 4 +++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/quickshell/Common/ModalManager.qml b/quickshell/Common/ModalManager.qml index a2d3198ac..457ec7816 100644 --- a/quickshell/Common/ModalManager.qml +++ b/quickshell/Common/ModalManager.qml @@ -15,7 +15,11 @@ Singleton { function openModal(modal) { PopoutManager.screenshotActive = false; const screenName = modal.effectiveScreen?.name ?? "unknown"; - currentModalsByScreen[screenName] = modal; + var next = {}; + for (var k in currentModalsByScreen) + next[k] = currentModalsByScreen[k]; + next[screenName] = modal; + currentModalsByScreen = next; modalChanged(); Qt.callLater(() => { if (!modal.allowStacking) @@ -34,7 +38,12 @@ Singleton { function closeModal(modal) { const screenName = modal.effectiveScreen?.name ?? "unknown"; if (currentModalsByScreen[screenName] === modal) { - delete currentModalsByScreen[screenName]; + var next = {}; + for (var k in currentModalsByScreen) { + if (k !== screenName) + next[k] = currentModalsByScreen[k]; + } + currentModalsByScreen = next; modalChanged(); } } diff --git a/quickshell/Widgets/DankSlideout.qml b/quickshell/Widgets/DankSlideout.qml index 9a4c52917..c361c26f2 100644 --- a/quickshell/Widgets/DankSlideout.qml +++ b/quickshell/Widgets/DankSlideout.qml @@ -105,9 +105,11 @@ PanelWindow { readonly property bool slideoutBlurActive: root.visible && BlurService.enabled && Theme.connectedSurfaceBlurEnabled + readonly property string _slideoutScreenName: modelData?.name ?? "" + WlrLayershell.layer: (!suppressOverlayLayer && (triggerUsesOverlayLayer || CompositorService.framePeerSurfacesUseOverlayForScreen(modelData))) ? WlrLayershell.Overlay : WlrLayershell.Top WlrLayershell.exclusiveZone: 0 - WlrLayershell.keyboardFocus: isVisible ? WlrKeyboardFocus.OnDemand : WlrKeyboardFocus.None + WlrLayershell.keyboardFocus: isVisible && !ModalManager.currentModalsByScreen[_slideoutScreenName] ? WlrKeyboardFocus.OnDemand : WlrKeyboardFocus.None readonly property real dpr: CompositorService.getScreenScale(root.screen) readonly property real alignedWidth: Theme.px(expandable && expandedWidth ? expandedWidthValue : slideoutWidth, dpr)