diff --git a/activation.cpp b/activation.cpp index 37f0070414..d5159bb967 100644 --- a/activation.cpp +++ b/activation.cpp @@ -408,6 +408,25 @@ static inline bool isUsableFocusCandidate(Client *c, Client *prev, bool respectS (!respectScreen || c->isOnScreen(prev ? prev->screen() : Workspace::self()->activeScreen())); } +Client *Workspace::clientUnderMouse(int screen) const +{ + QList::const_iterator it = stackingOrder().constEnd(); + while (it != stackingOrder().constBegin()) { + Client *client = *(--it); + + // rule out clients which are not really visible. + // the screen test is rather superflous for xrandr & twinview since the geometry would differ -> TODO: might be dropped + if (!(client->isShown(false) && client->isOnCurrentDesktop() && + client->isOnCurrentActivity() && client->isOnScreen(screen))) + continue; + + if (client->geometry().contains(QCursor::pos())) { + return client; + } + } + return 0; +} + // deactivates 'c' and activates next client bool Workspace::activateNextClient(Client* c) { @@ -436,22 +455,10 @@ bool Workspace::activateNextClient(Client* c) Client* get_focus = NULL; if (options->nextFocusPrefersMouse) { - QList::const_iterator it = stackingOrder().constEnd(); - while (it != stackingOrder().constBegin()) { - Client *client = *(--it); - - // rule out clients which are not really visible. - // the screen test is rather superflous for xrandr & twinview since the geometry would differ -> TODO: might be dropped - if (!(client->isShown(false) && client->isOnCurrentDesktop() && - client->isOnCurrentActivity() && client->isOnScreen(c ? c->screen() : activeScreen()))) - continue; - - if (client->geometry().contains(QCursor::pos())) { - if (client != c && !client->isDesktop()) // should rather not happen, but it cannot get the focus. rest of usability is tested above - get_focus = client; - break; // unconditional break - we do not pass the focus to some client below an unusable one - } - + get_focus = clientUnderMouse(c ? c->screen() : activeScreen()); + if (get_focus && (get_focus == c || get_focus->isDesktop())) { + // should rather not happen, but it cannot get the focus. rest of usability is tested above + get_focus = 0; } } diff --git a/useractions.cpp b/useractions.cpp index b310a3929f..6eec1b15a1 100644 --- a/useractions.cpp +++ b/useractions.cpp @@ -816,13 +816,17 @@ bool Client::performMouseCommand(Options::MouseCommand command, const QPoint &gl case Options::MouseRaise: workspace()->raiseClient(this); break; - case Options::MouseLower: + case Options::MouseLower: { workspace()->lowerClient(this); - // As this most likely makes the window no longer visible change the - // keyboard focus to the next available window. - //workspace()->activateNextClient( this ); // Doesn't work when we lower a child window - workspace()->activateClient(workspace()->topClientOnDesktop(workspace()->currentDesktop(), -1)); + // used to be activateNextClient(this), then topClientOnDesktop + // since this is a mouseOp it's however safe to use the client under the mouse instead + if (isActive()) { + Client *next = workspace()->clientUnderMouse(screen()); + if (next && next != this) + workspace()->requestFocus(next, false); + } break; + } case Options::MouseShade : toggleShade(); cancelShadeHoverTimer(); @@ -1238,13 +1242,13 @@ void Workspace::slotWindowRaise() */ void Workspace::slotWindowLower() { - Client* c = active_popup_client ? active_popup_client : active_client; - if (c) { + if ((Client* c = active_popup_client ? active_popup_client : active_client)) { lowerClient(c); // As this most likely makes the window no longer visible change the // keyboard focus to the next available window. //activateNextClient( c ); // Doesn't work when we lower a child window - activateClient(topClientOnDesktop(currentDesktop(), -1)); + if (c->isActive()) + activateClient(topClientOnDesktop(currentDesktop(), -1)); } } diff --git a/workspace.h b/workspace.h index 092b6a72ff..d5942dca38 100644 --- a/workspace.h +++ b/workspace.h @@ -144,6 +144,8 @@ public: */ Client* mostRecentlyActivatedClient() const; + Client* clientUnderMouse(int screen) const; + void activateClient(Client*, bool force = false); void requestFocus(Client* c, bool force = false); void takeActivity(Client* c, int flags, bool handled); // Flags are ActivityFlags