From 512cbd9773337ef3f3e4fca0778871435f3a9dc4 Mon Sep 17 00:00:00 2001 From: adam01110 Date: Sat, 25 Apr 2026 17:21:10 +0200 Subject: [PATCH] Backport upstream focus-grab closing fixes --- EXAMPLE.md | 2 ++ README.md | 8 ++++++++ common/Config.qml | 1 + modules/overview/Overview.qml | 27 ++++++++++++++++++++++++++- modules/overview/OverviewWidget.qml | 6 ++++++ 5 files changed, 43 insertions(+), 1 deletion(-) diff --git a/EXAMPLE.md b/EXAMPLE.md index 9a2cda7..4e16013 100644 --- a/EXAMPLE.md +++ b/EXAMPLE.md @@ -57,6 +57,8 @@ Path: `~/.config/overzicht/settings.json` "enable": true, // Hides rows that have no windows and are not the active workspace row. "hideEmptyRows": false, + // Closes the overview when clicking outside it or when the focus grab is cleared. + "closeOnFocusLoss": true, // Enables per-monitor workspace offsets from workspaceMap when grouping workspaces. "useWorkspaceMap": false, // Monitor-id keyed workspace start offsets used when useWorkspaceMap is enabled. diff --git a/README.md b/README.md index c476e9a..3e027ad 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,7 @@ Overzicht is a full-screen workspace switcher built as a standalone Quickshell p - Middle-click a window preview to close it. - Drag a window preview onto another workspace tile to move it there. - Keyboard navigation with arrow keys or `h/j/k/l`. +- Optional auto-close on focus loss or outside click. - Optional reversed row and column ordering. - Optional per-monitor workspace offsets through `workspaceMap`. - Optional empty-row hiding within the active workspace group. @@ -138,6 +139,7 @@ Keyboard controls while the overview is open: - `1` to `9` jump to the matching workspace position in the current group. - `0` jumps to position 10 when the grid has at least ten cells. - `Return` and `Escape` close the overlay. +- Clicking outside the overview closes it when `overview.closeOnFocusLoss` is enabled. ## Configuration @@ -159,6 +161,12 @@ Main groups: - `windowPreview` - `hacks` +Useful `overview` toggles include: + +- `hideEmptyRows` to collapse unused workspace rows in the current group. +- `closeOnFocusLoss` to dismiss the overview on outside click or focus-grab loss. Defaults to `true`. +- `useWorkspaceMap` and `workspaceMap` for per-monitor workspace offsets. + > [!TIP] > `previewMode` accepts `live` and event-driven values such as `event` or `snapshot`. For the full schema and examples, use [`EXAMPLE.md`](./EXAMPLE.md). diff --git a/common/Config.qml b/common/Config.qml index 540ce03..0d7fbb1 100644 --- a/common/Config.qml +++ b/common/Config.qml @@ -91,6 +91,7 @@ Singleton { property real scale: root.optionValue(["overview", "scale"], 0.12) property bool enable: root.optionValue(["overview", "enable"], true) property bool hideEmptyRows: root.optionValue(["overview", "hideEmptyRows"], false) + property bool closeOnFocusLoss: root.optionValue(["overview", "closeOnFocusLoss"], true) property bool useWorkspaceMap: root.optionValue(["overview", "useWorkspaceMap"], false) property var workspaceMap: root.optionValue(["overview", "workspaceMap"], []) property bool orderRightLeft: root.optionValue(["overview", "orderRightLeft"], false) diff --git a/modules/overview/Overview.qml b/modules/overview/Overview.qml index bfd4f23..63a4144 100644 --- a/modules/overview/Overview.qml +++ b/modules/overview/Overview.qml @@ -21,6 +21,7 @@ Scope { property bool monitorIsFocused: Hyprland.focusedMonitor?.id == monitor?.id property bool backdropEnabled: Config.options.overview.effects.enableBackdrop property real backdropOpacity: Math.max(0, Math.min(1, Config.options.overview.effects.backdropOpacity)) + property bool closeOnFocusLoss: Config.options.overview.closeOnFocusLoss ?? true screen: modelData visible: GlobalStates.overviewOpen @@ -42,7 +43,7 @@ Scope { property bool canBeActive: root.monitorIsFocused active: false onCleared: () => { - if (!active) + if (root.closeOnFocusLoss && !active && canBeActive) GlobalStates.overviewOpen = false; } } @@ -55,6 +56,19 @@ Scope { } } + Connections { + target: Hyprland + function onFocusedMonitorChanged() { + if (!GlobalStates.overviewOpen) + return; + + if (root.monitorIsFocused && !grab.active) + grab.active = true; + else if (!root.monitorIsFocused && grab.active) + grab.active = false; + } + } + Timer { id: delayedGrabTimer interval: Config.options.hacks.arbitraryRaceConditionDelay @@ -84,6 +98,17 @@ Scope { z: 0 } + MouseArea { + anchors.fill: parent + acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton + enabled: root.closeOnFocusLoss && GlobalStates.overviewOpen + z: 0 + onPressed: mouse => { + GlobalStates.overviewOpen = false; + mouse.accepted = true; + } + } + Keys.onPressed: event => { if (event.key === Qt.Key_Escape || event.key === Qt.Key_Return) { GlobalStates.overviewOpen = false; diff --git a/modules/overview/OverviewWidget.qml b/modules/overview/OverviewWidget.qml index 8f7ad44..e1a5346 100644 --- a/modules/overview/OverviewWidget.qml +++ b/modules/overview/OverviewWidget.qml @@ -142,6 +142,12 @@ Item { border.width: 1 border.color: ColorUtils.applyAlpha(Appearance.colors.colLayer0Border, root.panelOpacity) + MouseArea { + anchors.fill: parent + acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton + onPressed: mouse => mouse.accepted = true + } + ColumnLayout { id: workspaceColumnLayout -- 2.51.2