From 47a2a2e12a52d1c28ba1043071190c9707640bee 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 --- 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 eec264b322..7bd656b732 100644 --- a/src/activation.cpp +++ b/src/activation.cpp @@ -490,13 +490,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; @@ -519,7 +520,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) { @@ -540,7 +541,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 a45dbc8396..65ede01eba 100644 --- a/src/workspace.cpp +++ b/src/workspace.cpp @@ -410,7 +410,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) { @@ -730,7 +730,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(); @@ -995,7 +995,7 @@ void Workspace::activateWindowOnDesktop(VirtualDesktop *desktop) } if (!window) { - window = findDesktop(true, desktop); + window = findDesktop(true, desktop, activeOutput()); } if (window != m_activeWindow) { @@ -1111,7 +1111,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) { @@ -1578,7 +1578,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 3d17e89189..878e733c7c 100644 --- a/src/workspace.h +++ b/src/workspace.h @@ -310,7 +310,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);