From 72d64a3b96f1fb7111852f876de2bb68aa7645f5 Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Wed, 9 Oct 2024 12:31:24 +0300 Subject: [PATCH] Prefer activating desktop window on active output Workspace::findDesktop() doesn't take into account the current active output, and instead returns the first top desktop window found in the stack. This means that the active output may drift and the focus chain logic can break. BUG: 493735 BUG: 494332 (cherry picked from commit 47a2a2e12a52d1c28ba1043071190c9707640bee) --- src/activation.cpp | 9 +++++---- src/layers.cpp | 6 +++--- src/workspace.cpp | 10 +++++----- src/workspace.h | 2 +- 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/activation.cpp b/src/activation.cpp index 11143d1655..4ba8a998f1 100644 --- a/src/activation.cpp +++ b/src/activation.cpp @@ -492,13 +492,14 @@ bool Workspace::activateNextWindow(Window *window) Window *focusCandidate = nullptr; VirtualDesktop *desktop = VirtualDesktopManager::self()->currentDesktop(); + Output *output = window ? window->output() : workspace()->activeOutput(); if (!focusCandidate && showingDesktop()) { - focusCandidate = findDesktop(true, desktop); // to not break the state + focusCandidate = findDesktop(true, desktop, output); // to not break the state } if (!focusCandidate && options->isNextFocusPrefersMouse()) { - focusCandidate = windowUnderMouse(window ? window->output() : workspace()->activeOutput()); + focusCandidate = windowUnderMouse(output); if (focusCandidate && (focusCandidate == window || focusCandidate->isDesktop())) { // should rather not happen, but it cannot get the focus. rest of usability is tested above focusCandidate = nullptr; @@ -521,7 +522,7 @@ bool Workspace::activateNextWindow(Window *window) } if (focusCandidate == nullptr) { // last chance: focus the desktop - focusCandidate = findDesktop(true, desktop); + focusCandidate = findDesktop(true, desktop, output); } if (focusCandidate != nullptr) { @@ -542,7 +543,7 @@ void Workspace::switchToOutput(Output *output) VirtualDesktop *desktop = VirtualDesktopManager::self()->currentDesktop(); Window *get_focus = m_focusChain->getForActivation(desktop, output); if (get_focus == nullptr) { - get_focus = findDesktop(true, desktop); + get_focus = findDesktop(true, desktop, output); } if (get_focus != nullptr && get_focus != mostRecentlyActivatedWindow()) { requestFocus(get_focus); diff --git a/src/layers.cpp b/src/layers.cpp index a476a472ea..ce4a9dc664 100644 --- a/src/layers.cpp +++ b/src/layers.cpp @@ -256,7 +256,7 @@ Window *Workspace::topWindowOnDesktop(VirtualDesktop *desktop, Output *output, b return nullptr; } -Window *Workspace::findDesktop(bool topmost, VirtualDesktop *desktop) const +Window *Workspace::findDesktop(bool topmost, VirtualDesktop *desktop, Output *output) const { // TODO Q_ASSERT( block_stacking_updates == 0 ); if (topmost) { @@ -265,7 +265,7 @@ Window *Workspace::findDesktop(bool topmost, VirtualDesktop *desktop) const if (window->isDeleted()) { continue; } - if (window->isClient() && window->isOnDesktop(desktop) && window->isDesktop() && window->isShown()) { + if (window->isClient() && window->isOnDesktop(desktop) && window->isOnOutput(output) && window->isDesktop() && window->isShown()) { return window; } } @@ -274,7 +274,7 @@ Window *Workspace::findDesktop(bool topmost, VirtualDesktop *desktop) const if (window->isDeleted()) { continue; } - if (window->isClient() && window->isOnDesktop(desktop) && window->isDesktop() && window->isShown()) { + if (window->isClient() && window->isOnDesktop(desktop) && window->isOnOutput(output) && window->isDesktop() && window->isShown()) { return window; } } diff --git a/src/workspace.cpp b/src/workspace.cpp index 6103ad500d..d0681e7b45 100644 --- a/src/workspace.cpp +++ b/src/workspace.cpp @@ -414,7 +414,7 @@ void Workspace::initializeX11() newActiveWindow = topWindowOnDesktop(VirtualDesktopManager::self()->currentDesktop()); } if (newActiveWindow == nullptr) { - newActiveWindow = findDesktop(true, VirtualDesktopManager::self()->currentDesktop()); + newActiveWindow = findDesktop(true, VirtualDesktopManager::self()->currentDesktop(), activeOutput()); } } if (newActiveWindow != nullptr) { @@ -734,7 +734,7 @@ void Workspace::addX11Window(X11Window *window) raiseWindow(window); // If there's no active window, make this desktop the active one if (activeWindow() == nullptr && should_get_focus.count() == 0) { - activateWindow(findDesktop(true, VirtualDesktopManager::self()->currentDesktop())); + activateWindow(findDesktop(true, VirtualDesktopManager::self()->currentDesktop(), window->output())); } } window->checkActiveModal(); @@ -999,7 +999,7 @@ void Workspace::activateWindowOnDesktop(VirtualDesktop *desktop) } if (!window) { - window = findDesktop(true, desktop); + window = findDesktop(true, desktop, activeOutput()); } if (window != m_activeWindow) { @@ -1115,7 +1115,7 @@ void Workspace::updateCurrentActivity(const QString &new_activity) } if (!window) { - window = findDesktop(true, VirtualDesktopManager::self()->currentDesktop()); + window = findDesktop(true, VirtualDesktopManager::self()->currentDesktop(), activeOutput()); } if (window != m_activeWindow) { @@ -1582,7 +1582,7 @@ void Workspace::setShowingDesktop(bool showing, bool animated) } if (showing_desktop) { - Window *desktop = findDesktop(true, VirtualDesktopManager::self()->currentDesktop()); + Window *desktop = findDesktop(true, VirtualDesktopManager::self()->currentDesktop(), activeOutput()); if (desktop) { requestFocus(desktop); } diff --git a/src/workspace.h b/src/workspace.h index a1823efa6c..05bc325969 100644 --- a/src/workspace.h +++ b/src/workspace.h @@ -314,7 +314,7 @@ public: Window *topWindowOnDesktop(VirtualDesktop *desktop, Output *output = nullptr, bool unconstrained = false, bool only_normal = true) const; - Window *findDesktop(bool topmost, VirtualDesktop *desktop) const; + Window *findDesktop(bool topmost, VirtualDesktop *desktop, Output *output) const; void addWindowToDesktop(Window *window, VirtualDesktop *desktop); void removeWindowFromDesktop(Window *window, VirtualDesktop *desktop); void sendWindowToDesktops(Window *window, const QList &desktops, bool dont_activate);