summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVaxry <43317083+vaxerski@users.noreply.github.com>2025-12-30 18:02:34 +0100
committerGitHub <noreply@github.com>2025-12-30 18:02:34 +0100
commit529559712bbfa9c8d79fe01770a77e925a7a0496 (patch)
tree9124e885d2e296b1eb2578c1e469a1f4f4ea0a84
parent293d3e5de9fb18d54a5b0b7f9dbb4492207a25dd (diff)
desktop/window: go back to the previously focused window in a group (#12763)
-rw-r--r--hyprtester/src/tests/main/window.cpp37
-rw-r--r--src/desktop/view/Window.cpp19
2 files changed, 55 insertions, 1 deletions
diff --git a/hyprtester/src/tests/main/window.cpp b/hyprtester/src/tests/main/window.cpp
index 37442790..0a2e31d0 100644
--- a/hyprtester/src/tests/main/window.cpp
+++ b/hyprtester/src/tests/main/window.cpp
@@ -373,6 +373,41 @@ static void testMaximizeSize() {
EXPECT(Tests::windowCount(), 0);
}
+static void testGroupFallbackFocus() {
+ NLog::log("{}Testing group fallback focus", Colors::GREEN);
+
+ EXPECT(spawnKitty("kitty_A"), true);
+
+ OK(getFromSocket("/dispatch togglegroup"));
+
+ EXPECT(spawnKitty("kitty_B"), true);
+ EXPECT(spawnKitty("kitty_C"), true);
+ EXPECT(spawnKitty("kitty_D"), true);
+
+ {
+ auto str = getFromSocket("/activewindow");
+ EXPECT(str.contains("class: kitty_D"), true);
+ }
+
+ OK(getFromSocket("/dispatch focuswindow class:kitty_B"));
+ OK(getFromSocket("/dispatch focuswindow class:kitty_D"));
+ OK(getFromSocket("/dispatch killactive"));
+
+ Tests::waitUntilWindowsN(3);
+
+ // Focus must return to the last focus, in this case B.
+ {
+ auto str = getFromSocket("/activewindow");
+ EXPECT(str.contains("class: kitty_B"), true);
+ }
+
+ NLog::log("{}Killing all windows", Colors::YELLOW);
+ Tests::killAllWindows();
+
+ NLog::log("{}Expecting 0 windows", Colors::YELLOW);
+ EXPECT(Tests::windowCount(), 0);
+}
+
static void testBringActiveToTopMouseMovement() {
NLog::log("{}Testing bringactivetotop mouse movement", Colors::GREEN);
@@ -847,6 +882,8 @@ static bool test() {
testBringActiveToTopMouseMovement();
+ testGroupFallbackFocus();
+
NLog::log("{}Reloading config", Colors::YELLOW);
OK(getFromSocket("/reload"));
diff --git a/src/desktop/view/Window.cpp b/src/desktop/view/Window.cpp
index 695ba81f..b0e6a365 100644
--- a/src/desktop/view/Window.cpp
+++ b/src/desktop/view/Window.cpp
@@ -2437,7 +2437,24 @@ void CWindow::unmapWindow() {
}
bool wasLastWindow = false;
- PHLWINDOW nextInGroup = m_groupData.pNextWindow ? m_groupData.pNextWindow.lock() : nullptr;
+ PHLWINDOW nextInGroup = [this] -> PHLWINDOW {
+ if (!m_groupData.pNextWindow)
+ return nullptr;
+
+ // walk the history to find a suitable window
+ const auto HISTORY = Desktop::History::windowTracker()->fullHistory();
+ for (const auto& w : HISTORY | std::views::reverse) {
+ if (!w || !w->m_isMapped || w == m_self)
+ continue;
+
+ if (!hasInGroup(w.lock()))
+ continue;
+
+ return w.lock();
+ }
+
+ return nullptr;
+ }();
if (m_self.lock() == Desktop::focusState()->window()) {
wasLastWindow = true;