From 0100c64d7a4ebbb6daef45e666e9670df01f52c5 Mon Sep 17 00:00:00 2001 From: Alexander Date: Mon, 17 Aug 2026 20:35:10 +0300 Subject: [PATCH] feat(niri): close overview on window focus (#3030) * feat(niri): close overview on window focus * feat(niri): close overview on window focus --------- Co-authored-by: bbedward --- quickshell/Common/SettingsData.qml | 4 +- quickshell/Common/settings/SettingsSpec.js | 2 +- quickshell/Common/settings/SettingsStore.js | 12 +++ .../Modals/DankLauncherV2/LauncherContent.qml | 3 - .../SpotlightLauncherContent.qml | 2 - quickshell/Modals/Settings/SettingsModal.qml | 1 + quickshell/Modules/Dock/DockAppButton.qml | 2 +- .../Modules/Settings/CompositorLayoutTab.qml | 18 ++++ quickshell/Modules/Settings/LauncherTab.qml | 9 -- .../WorkspaceOverlays/NiriOverviewOverlay.qml | 4 +- quickshell/Services/CompositorService.qml | 13 ++- quickshell/Services/NiriService.qml | 8 ++ quickshell/Services/PopoutService.qml | 4 +- quickshell/Services/SessionService.qml | 2 + .../translations/settings_search_index.json | 100 ++++++++++++------ 15 files changed, 125 insertions(+), 59 deletions(-) diff --git a/quickshell/Common/SettingsData.qml b/quickshell/Common/SettingsData.qml index 61d52833e..22765c6e9 100644 --- a/quickshell/Common/SettingsData.qml +++ b/quickshell/Common/SettingsData.qml @@ -15,7 +15,7 @@ Singleton { id: root readonly property var log: Log.scoped("SettingsData") - readonly property int settingsConfigVersion: 15 + readonly property int settingsConfigVersion: 16 enum Position { Top, @@ -549,7 +549,7 @@ Singleton { property string appPickerViewMode: "grid" property bool sortAppsAlphabetically: false property int appLauncherGridColumns: 4 - property bool spotlightCloseNiriOverview: true + property bool closeNiriOverviewOnWindowFocus: true property bool rememberLastQuery: false property bool rememberLastMode: true property var spotlightSectionViewModes: ({}) diff --git a/quickshell/Common/settings/SettingsSpec.js b/quickshell/Common/settings/SettingsSpec.js index 4157b54b4..b17655a4a 100644 --- a/quickshell/Common/settings/SettingsSpec.js +++ b/quickshell/Common/settings/SettingsSpec.js @@ -280,7 +280,7 @@ var SPEC = { appPickerViewMode: { def: "grid" }, sortAppsAlphabetically: { def: false }, appLauncherGridColumns: { def: 4 }, - spotlightCloseNiriOverview: { def: true }, + closeNiriOverviewOnWindowFocus: { def: true }, rememberLastQuery: { def: false }, rememberLastMode: { def: true }, spotlightSectionViewModes: { def: {} }, diff --git a/quickshell/Common/settings/SettingsStore.js b/quickshell/Common/settings/SettingsStore.js index 1335d2ac7..5a13b3118 100644 --- a/quickshell/Common/settings/SettingsStore.js +++ b/quickshell/Common/settings/SettingsStore.js @@ -389,5 +389,17 @@ function migrateToVersion(obj, targetVersion) { settings.configVersion = 15; } + if (currentVersion < 16) { + console.info("Migrating settings from version", currentVersion, "to version 16"); + console.info("Moving Niri overview close behavior to the window focus setting"); + + if (settings.closeNiriOverviewOnWindowFocus === undefined && settings.spotlightCloseNiriOverview !== undefined) { + settings.closeNiriOverviewOnWindowFocus = settings.spotlightCloseNiriOverview; + } + delete settings.spotlightCloseNiriOverview; + + settings.configVersion = 16; + } + return settings; } diff --git a/quickshell/Modals/DankLauncherV2/LauncherContent.qml b/quickshell/Modals/DankLauncherV2/LauncherContent.qml index beed9e71c..a2957cd42 100644 --- a/quickshell/Modals/DankLauncherV2/LauncherContent.qml +++ b/quickshell/Modals/DankLauncherV2/LauncherContent.qml @@ -73,9 +73,6 @@ FocusScope { if (root.parentModal) { root.parentModal.hide(); } - if (SettingsData.spotlightCloseNiriOverview && NiriService.inOverview) { - NiriService.toggleOverview(); - } } } diff --git a/quickshell/Modals/DankLauncherV2/SpotlightLauncherContent.qml b/quickshell/Modals/DankLauncherV2/SpotlightLauncherContent.qml index 78685ad10..404c54e62 100644 --- a/quickshell/Modals/DankLauncherV2/SpotlightLauncherContent.qml +++ b/quickshell/Modals/DankLauncherV2/SpotlightLauncherContent.qml @@ -224,8 +224,6 @@ FocusScope { onItemExecuted: { root.parentModal?.hide(); - if (SettingsData.spotlightCloseNiriOverview && NiriService.inOverview) - NiriService.toggleOverview(); } } diff --git a/quickshell/Modals/Settings/SettingsModal.qml b/quickshell/Modals/Settings/SettingsModal.qml index f1449e17d..4b98804f1 100644 --- a/quickshell/Modals/Settings/SettingsModal.qml +++ b/quickshell/Modals/Settings/SettingsModal.qml @@ -44,6 +44,7 @@ DankFloatingWindow { if (visible && !backingWindowVisible) { visible = false; } + CompositorService.closeNiriOverviewOnWindowFocus(); visible = true; } diff --git a/quickshell/Modules/Dock/DockAppButton.qml b/quickshell/Modules/Dock/DockAppButton.qml index 68f7c7d90..82cf4dd38 100644 --- a/quickshell/Modules/Dock/DockAppButton.qml +++ b/quickshell/Modules/Dock/DockAppButton.qml @@ -182,7 +182,7 @@ Item { return false; HyprlandService.toggleSpecial(specialName); - Qt.callLater(() => waylandToplevel.activate()); + Qt.callLater(() => CompositorService.activateToplevel(waylandToplevel)); return true; } diff --git a/quickshell/Modules/Settings/CompositorLayoutTab.qml b/quickshell/Modules/Settings/CompositorLayoutTab.qml index 505375400..944b30897 100644 --- a/quickshell/Modules/Settings/CompositorLayoutTab.qml +++ b/quickshell/Modules/Settings/CompositorLayoutTab.qml @@ -285,6 +285,24 @@ awk '$1 == "xray" { print FILENAME ":" FNR; exit }' $files 2>/dev/null`; } } + SettingsCard { + width: parent.width + tags: ["niri", "overview", "window", "focus", "launch", "launcher", "dock", "settings"] + title: I18n.tr("Overview") + settingKey: "niriOverview" + iconName: "overview" + visible: CompositorService.isNiri + + SettingsToggleRow { + tags: ["niri", "overview", "window", "focus", "launch", "launcher", "dock", "settings"] + settingKey: "closeNiriOverviewOnWindowFocus" + text: I18n.tr("Close Niri Overview on Window Focus", "Niri setting to leave Niri overview when DMS launches or focuses a window") + description: I18n.tr("Auto-close Niri overview when DMS launches or focuses a window.", "Description of the close Niri overview on window focus setting") + checked: SettingsData.closeNiriOverviewOnWindowFocus + onToggled: checked => SettingsData.set("closeNiriOverviewOnWindowFocus", checked) + } + } + SettingsCard { width: parent.width tags: ["niri", "layout", "gaps", "radius", "window", "border"] diff --git a/quickshell/Modules/Settings/LauncherTab.qml b/quickshell/Modules/Settings/LauncherTab.qml index 9c5e787c6..b0a86db97 100644 --- a/quickshell/Modules/Settings/LauncherTab.qml +++ b/quickshell/Modules/Settings/LauncherTab.qml @@ -777,15 +777,6 @@ Item { title: I18n.tr("Niri Integration").replace("Niri", "niri") visible: CompositorService.isNiri - SettingsToggleRow { - settingKey: "spotlightCloseNiriOverview" - tags: ["launcher", "niri", "overview", "close", "launch"] - text: I18n.tr("Close Overview on Launch") - description: I18n.tr("Auto-close Niri overview when launching apps.") - checked: SettingsData.spotlightCloseNiriOverview - onToggled: checked => SettingsData.set("spotlightCloseNiriOverview", checked) - } - SettingsToggleRow { settingKey: "niriOverviewOverlayEnabled" tags: ["launcher", "niri", "overview", "overlay", "enable"] diff --git a/quickshell/Modules/WorkspaceOverlays/NiriOverviewOverlay.qml b/quickshell/Modules/WorkspaceOverlays/NiriOverviewOverlay.qml index 4454b96aa..6d30ae775 100644 --- a/quickshell/Modules/WorkspaceOverlays/NiriOverviewOverlay.qml +++ b/quickshell/Modules/WorkspaceOverlays/NiriOverviewOverlay.qml @@ -115,7 +115,7 @@ Scope { niriOverviewScope.hideSpotlight(); return; } - NiriService.toggleOverview(); + NiriService.closeOverview(); } } @@ -200,7 +200,7 @@ Scope { if (overlayWindow.shouldShowSpotlight || niriOverviewScope.isClosing) return; if ([Qt.Key_Escape, Qt.Key_Return].includes(event.key)) { - NiriService.toggleOverview(); + NiriService.closeOverview(); event.accepted = true; return; } diff --git a/quickshell/Services/CompositorService.qml b/quickshell/Services/CompositorService.qml index 59d36a58c..c77b9f72a 100644 --- a/quickshell/Services/CompositorService.qml +++ b/quickshell/Services/CompositorService.qml @@ -51,9 +51,15 @@ Singleton { return supportsMinimize && toplevel && toplevel.minimized !== undefined; } + function closeNiriOverviewOnWindowFocus() { + if (SettingsData.closeNiriOverviewOnWindowFocus && isNiri && NiriService.inOverview) + NiriService.closeOverview(); + } + function activateToplevel(toplevel) { if (!toplevel) return; + closeNiriOverviewOnWindowFocus(); if (canMinimize(toplevel) && toplevel.minimized) toplevel.minimized = false; toplevel.activate(); @@ -63,19 +69,18 @@ Singleton { if (!toplevel) return; if (!canMinimize(toplevel)) { - toplevel.activate(); + activateToplevel(toplevel); return; } if (toplevel.minimized) { - toplevel.minimized = false; - toplevel.activate(); + activateToplevel(toplevel); return; } if (toplevel.activated) { toplevel.minimized = true; return; } - toplevel.activate(); + activateToplevel(toplevel); } function fetchRandrData() { diff --git a/quickshell/Services/NiriService.qml b/quickshell/Services/NiriService.qml index b3483cfee..df7ccbea8 100644 --- a/quickshell/Services/NiriService.qml +++ b/quickshell/Services/NiriService.qml @@ -795,6 +795,14 @@ Singleton { }); } + function closeOverview() { + return send({ + "Action": { + "CloseOverview": {} + } + }); + } + function focusMonitor(outputName) { return send({ "Action": { diff --git a/quickshell/Services/PopoutService.qml b/quickshell/Services/PopoutService.qml index 8b74b564b..aa91e821e 100644 --- a/quickshell/Services/PopoutService.qml +++ b/quickshell/Services/PopoutService.qml @@ -460,7 +460,7 @@ Singleton { settingsModal.hide(); return; } - toplevel.activate(); + CompositorService.activateToplevel(toplevel); return; } } @@ -479,7 +479,7 @@ Singleton { } var idx = settingsModal.resolveTabIndex(tabName); settingsModal.setTabIndex(idx); - toplevel.activate(); + CompositorService.activateToplevel(toplevel); return; } } diff --git a/quickshell/Services/SessionService.qml b/quickshell/Services/SessionService.qml index 71c0fb7d0..417b601c5 100644 --- a/quickshell/Services/SessionService.qml +++ b/quickshell/Services/SessionService.qml @@ -281,6 +281,7 @@ Singleton { function launchDesktopEntry(desktopEntry, useNvidia) { if (!desktopEntry || !desktopEntry.command) return; + CompositorService.closeNiriOverviewOnWindowFocus(); let cmd = desktopEntry.command; const appId = desktopEntry.id || desktopEntry.execString || desktopEntry.exec || ""; @@ -338,6 +339,7 @@ Singleton { function launchDesktopAction(desktopEntry, action, useNvidia) { if (!desktopEntry || !action || !action.command) return; + CompositorService.closeNiriOverviewOnWindowFocus(); let cmd = action.command; const appId = desktopEntry.id || desktopEntry.execString || desktopEntry.exec || ""; diff --git a/quickshell/translations/settings_search_index.json b/quickshell/translations/settings_search_index.json index ffe1ec558..4be4b577f 100644 --- a/quickshell/translations/settings_search_index.json +++ b/quickshell/translations/settings_search_index.json @@ -2917,31 +2917,6 @@ "style" ] }, - { - "section": "niriOverviewOverlayEnabled", - "label": "Enable Overview Overlay", - "tabIndex": 9, - "category": "Launcher", - "keywords": [ - "another", - "app drawer", - "app menu", - "applications", - "disable", - "drawer", - "enable", - "launcher", - "menu", - "niri", - "overlay", - "overview", - "show", - "start", - "start menu", - "typing" - ], - "description": "Show launcher overlay when typing in Niri overview. Disable to use another launcher." - }, { "section": "appLauncherGridColumns", "label": "Grid Columns", @@ -3118,26 +3093,31 @@ "description": "Show darkened overlay behind modal dialogs" }, { - "section": "spotlightCloseNiriOverview", + "section": "niriOverviewOverlayEnabled", "label": "Niri Integration", "tabIndex": 9, "category": "Launcher", "keywords": [ - "apps", - "auto", - "close", + "another", + "app drawer", + "app menu", + "applications", + "disable", "drawer", + "enable", "integration", - "launch", "launcher", - "launching", "menu", "niri", + "overlay", "overview", - "start" + "show", + "start", + "start menu", + "typing" ], "icon": "open_in_new", - "description": "Auto-close Niri overview when launching apps.", + "description": "Show launcher overlay when typing in Niri overview. Disable to use another launcher.", "conditionKey": "isNiri" }, { @@ -10141,6 +10121,32 @@ ], "description": "Width of window border and focus ring" }, + { + "section": "closeNiriOverviewOnWindowFocus", + "label": "Close Niri Overview on Window Focus", + "tabIndex": 37, + "category": "Personalization", + "keywords": [ + "appearance", + "auto", + "close", + "custom", + "customize", + "dock", + "focus", + "focuses", + "launch", + "launcher", + "launches", + "niri", + "overview", + "personal", + "personalization", + "settings", + "window" + ], + "description": "Auto-close Niri overview when DMS launches or focuses a window." + }, { "section": "hyprlandLayoutBarXrayEnabled", "label": "Frame Xray", @@ -10553,6 +10559,34 @@ ], "description": "Use custom window radius instead of theme radius" }, + { + "section": "niriOverview", + "label": "Overview", + "tabIndex": 37, + "category": "Personalization", + "keywords": [ + "appearance", + "auto", + "close", + "custom", + "customize", + "dock", + "focus", + "focuses", + "launch", + "launcher", + "launches", + "niri", + "overview", + "personal", + "personalization", + "settings", + "window" + ], + "icon": "overview", + "description": "Auto-close Niri overview when DMS launches or focuses a window.", + "conditionKey": "isNiri" + }, { "section": "hyprlandResizeOnBorder", "label": "Resize on Border",