Client *FocusChain::nextForDesktop(Client *reference, uint desktop) const { DesktopChains::const_iterator it = m_desktopFocusChains.find(desktop); if (it == m_desktopFocusChains.end()) { return NULL; } const QList<Client*> &chain = it.value(); for (int i = chain.size() - 1; i >= 0; --i) { Client* client = chain.at(i); if (isUsableFocusCandidate(client, reference)) { return client; } } return NULL; }
// deactivates 'c' and activates next client bool Workspace::activateNextClient(Client* c) { // if 'c' is not the active or the to-become active one, do nothing if (!(c == active_client || (should_get_focus.count() > 0 && c == should_get_focus.last()))) return false; closeActivePopup(); if (c != NULL) { if (c == active_client) setActiveClient(NULL, Allowed); should_get_focus.removeAll(c); } // if blocking focus, move focus to the desktop later if needed // in order to avoid flickering if (!focusChangeEnabled()) { focusToNull(); return true; } if (!options->focusPolicyIsReasonable()) return false; Client* get_focus = NULL; if (options->isNextFocusPrefersMouse()) { 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; } } if (!get_focus) { // no suitable window under the mouse -> find sth. else // first try to pass the focus to the (former) active clients leader if (c && (get_focus = c->transientFor()) && isUsableFocusCandidate(get_focus, c, options->isSeparateScreenFocus())) { raiseClient(get_focus); // also raise - we don't know where it came from } else { // nope, ask the focus chain for the next candidate get_focus = NULL; // reset from the inline assignment above for (int i = focus_chain[ currentDesktop()].size() - 1; i >= 0; --i) { Client* ci = focus_chain[ currentDesktop()].at(i); if (isUsableFocusCandidate(ci, c, options->isSeparateScreenFocus())) { get_focus = ci; break; // we're done } } } } if (get_focus == NULL) // last chance: focus the desktop get_focus = findDesktop(true, currentDesktop()); if (get_focus != NULL) requestFocus(get_focus); else focusToNull(); return true; }