Split out handling of focus chain into an own class
The new class FocusChain manages two different kind of focus chains. First of all there is a most recently used focus chain which is primarily used for TabBox. Then there is one focus chain per virtual desktop. These chains are used to determine which Client needs to be activated when e.g. switching to a virtual desktop. The individual chains are implemented as a simple QList of Client* with the most recently used Client as the last element. That way one can see it as a LIFO like structure. The desktop focus chains are internally represented as a hash with the id of the virtual desktop as the key and a list as described as the value. FocusChain is a singleton which provides some methods to manipulate the chains and to get a specific Client for a task (e.g. TabBox). While splitting out the code some unused code inside TabBox got removed as well as some activities related code (windows cannot be moved while switching activities). REVIEW: 107494
This commit is contained in:
parent
840b952096
commit
4a0a4bc27e
13 changed files with 572 additions and 227 deletions
|
@ -95,6 +95,7 @@ set(kwin_KDEINIT_SRCS
|
|||
client.cpp
|
||||
client_machine.cpp
|
||||
tabgroup.cpp
|
||||
focuschain.cpp
|
||||
placement.cpp
|
||||
atoms.cpp
|
||||
utils.cpp
|
||||
|
|
|
@ -27,6 +27,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/
|
||||
|
||||
#include "client.h"
|
||||
#include "focuschain.h"
|
||||
#include "workspace.h"
|
||||
|
||||
#include <fixx11h.h>
|
||||
|
@ -244,7 +245,7 @@ void Workspace::setActiveClient(Client* c, allowed_t)
|
|||
if (active_client != NULL)
|
||||
last_active_client = active_client;
|
||||
if (active_client) {
|
||||
updateFocusChains(active_client, FocusChainMakeFirst);
|
||||
FocusChain::self()->update(active_client, FocusChain::MakeFirst);
|
||||
active_client->demandAttention(false);
|
||||
}
|
||||
pending_take_activity = NULL;
|
||||
|
@ -401,13 +402,6 @@ void Workspace::clientHidden(Client* c)
|
|||
activateNextClient(c);
|
||||
}
|
||||
|
||||
static inline bool isUsableFocusCandidate(Client *c, Client *prev, bool respectScreen)
|
||||
{
|
||||
return c != prev &&
|
||||
c->isShown(false) && c->isOnCurrentDesktop() && c->isOnCurrentActivity() &&
|
||||
(!respectScreen || c->isOnScreen(prev ? prev->screen() : Workspace::self()->activeScreen()));
|
||||
}
|
||||
|
||||
Client *Workspace::clientUnderMouse(int screen) const
|
||||
{
|
||||
ToplevelList::const_iterator it = stackingOrder().constEnd();
|
||||
|
@ -478,18 +472,11 @@ bool Workspace::activateNextClient(Client* c)
|
|||
|
||||
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())) {
|
||||
if (c && (get_focus = c->transientFor()) && FocusChain::self()->isUsableFocusCandidate(get_focus, c)) {
|
||||
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[desktop].size() - 1; i >= 0; --i) {
|
||||
Client* ci = focus_chain[desktop].at(i);
|
||||
if (isUsableFocusCandidate(ci, c, options->isSeparateScreenFocus())) {
|
||||
get_focus = ci;
|
||||
break; // we're done
|
||||
}
|
||||
}
|
||||
get_focus = FocusChain::self()->nextForDesktop(c, desktop);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -512,19 +499,8 @@ void Workspace::setCurrentScreen(int new_screen)
|
|||
if (!options->focusPolicyIsReasonable())
|
||||
return;
|
||||
closeActivePopup();
|
||||
Client* get_focus = NULL;
|
||||
const int desktop = VirtualDesktopManager::self()->current();
|
||||
for (int i = focus_chain[desktop].count() - 1;
|
||||
i >= 0;
|
||||
--i) {
|
||||
Client* ci = focus_chain[desktop].at(i);
|
||||
if (!ci->isShown(false) || !ci->isOnCurrentDesktop() || !ci->isOnCurrentActivity())
|
||||
continue;
|
||||
if (ci->screen() == new_screen) {
|
||||
get_focus = ci;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Client *get_focus = FocusChain::self()->getForActivation(desktop, new_screen);
|
||||
if (get_focus == NULL)
|
||||
get_focus = findDesktop(true, desktop);
|
||||
if (get_focus != NULL && get_focus != mostRecentlyActivatedClient())
|
||||
|
|
15
client.cpp
15
client.cpp
|
@ -44,6 +44,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include "client_machine.h"
|
||||
#include "composite.h"
|
||||
#include "group.h"
|
||||
#include "focuschain.h"
|
||||
#include "workspace.h"
|
||||
#include "atoms.h"
|
||||
#include "notifications.h"
|
||||
|
@ -865,7 +866,7 @@ void Client::minimize(bool avoid_animation)
|
|||
updateAllowedActions();
|
||||
workspace()->updateMinimizedOfTransients(this);
|
||||
updateWindowRules(Rules::Minimize);
|
||||
workspace()->updateFocusChains(this, Workspace::FocusChainMakeLast);
|
||||
FocusChain::self()->update(this, FocusChain::MakeLast);
|
||||
// TODO: merge signal with s_minimized
|
||||
emit clientMinimized(this, !avoid_animation);
|
||||
|
||||
|
@ -1406,8 +1407,8 @@ void Client::setSkipTaskbar(bool b, bool from_outside)
|
|||
info->setState(b ? NET::SkipTaskbar : 0, NET::SkipTaskbar);
|
||||
updateWindowRules(Rules::SkipTaskbar);
|
||||
if (was_wants_tab_focus != wantsTabFocus())
|
||||
workspace()->updateFocusChains(this,
|
||||
isActive() ? Workspace::FocusChainMakeFirst : Workspace::FocusChainUpdate);
|
||||
FocusChain::self()->update(this,
|
||||
isActive() ? FocusChain::MakeFirst : FocusChain::Update);
|
||||
emit skipTaskbarChanged();
|
||||
}
|
||||
|
||||
|
@ -1478,7 +1479,7 @@ void Client::setDesktop(int desktop)
|
|||
c2->setDesktop(desktop);
|
||||
}
|
||||
|
||||
workspace()->updateFocusChains(this, Workspace::FocusChainMakeFirst);
|
||||
FocusChain::self()->update(this, FocusChain::MakeFirst);
|
||||
updateVisibility();
|
||||
updateWindowRules(Rules::Desktop);
|
||||
|
||||
|
@ -1552,7 +1553,7 @@ void Client::updateActivities(bool includeTransients)
|
|||
*/
|
||||
if (includeTransients)
|
||||
workspace()->updateOnAllActivitiesOfTransients(this);
|
||||
workspace()->updateFocusChains(this, Workspace::FocusChainMakeFirst);
|
||||
FocusChain::self()->update(this, FocusChain::MakeFirst);
|
||||
updateVisibility();
|
||||
updateWindowRules(Rules::Activity);
|
||||
|
||||
|
@ -1947,12 +1948,12 @@ void Client::setClientShown(bool shown)
|
|||
map(Allowed);
|
||||
takeFocus(Allowed);
|
||||
autoRaise();
|
||||
workspace()->updateFocusChains(this, Workspace::FocusChainMakeFirst);
|
||||
FocusChain::self()->update(this, FocusChain::MakeFirst);
|
||||
} else {
|
||||
unmap(Allowed);
|
||||
// Don't move tabs to the end of the list when another tab get's activated
|
||||
if (isCurrentTab())
|
||||
workspace()->updateFocusChains(this, Workspace::FocusChainMakeLast);
|
||||
FocusChain::self()->update(this, FocusChain::MakeLast);
|
||||
addWorkspaceRepaint(visibleRect());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include <config-X11.h>
|
||||
|
||||
#include "client.h"
|
||||
#include "focuschain.h"
|
||||
#include "workspace.h"
|
||||
#include "atoms.h"
|
||||
#ifdef KWIN_BUILD_TABBOX
|
||||
|
@ -354,7 +355,7 @@ bool Workspace::workspaceEvent(XEvent * e)
|
|||
// e->xmaprequest.window is different from e->xany.window
|
||||
// TODO this shouldn't be necessary now
|
||||
c->windowEvent(e);
|
||||
updateFocusChains(c, FocusChainUpdate);
|
||||
FocusChain::self()->update(c, FocusChain::Update);
|
||||
} else if ( true /*|| e->xmaprequest.parent != root */ ) {
|
||||
// NOTICE don't check for the parent being the root window, this breaks when some app unmaps
|
||||
// a window, changes something and immediately maps it back, without giving KWin
|
||||
|
|
262
focuschain.cpp
Normal file
262
focuschain.cpp
Normal file
|
@ -0,0 +1,262 @@
|
|||
/********************************************************************
|
||||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
Copyright (C) 2012 Martin Gräßlin <mgraesslin@kde.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*********************************************************************/
|
||||
#include "focuschain.h"
|
||||
#include "client.h"
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
FocusChain *FocusChain::s_manager = NULL;
|
||||
|
||||
FocusChain::FocusChain(QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_separateScreenFocus(false)
|
||||
, m_activeClient(NULL)
|
||||
, m_currentDesktop(0)
|
||||
{
|
||||
}
|
||||
|
||||
FocusChain *FocusChain::create(QObject *parent)
|
||||
{
|
||||
Q_ASSERT(!s_manager);
|
||||
s_manager = new FocusChain(parent);
|
||||
return s_manager;
|
||||
}
|
||||
|
||||
FocusChain::~FocusChain()
|
||||
{
|
||||
s_manager = NULL;
|
||||
}
|
||||
|
||||
void FocusChain::remove(Client *client)
|
||||
{
|
||||
for (DesktopChains::iterator it = m_desktopFocusChains.begin();
|
||||
it != m_desktopFocusChains.end();
|
||||
++it) {
|
||||
it.value().removeAll(client);
|
||||
}
|
||||
m_mostRecentlyUsed.removeAll(client);
|
||||
}
|
||||
|
||||
void FocusChain::resize(uint previousSize, uint newSize)
|
||||
{
|
||||
for (uint i = previousSize + 1; i <= newSize; ++i) {
|
||||
m_desktopFocusChains.insert(i, QList<Client*>());
|
||||
}
|
||||
for (uint i = previousSize; i > newSize; --i) {
|
||||
m_desktopFocusChains.remove(i);
|
||||
}
|
||||
}
|
||||
|
||||
Client *FocusChain::getForActivation(uint desktop) const
|
||||
{
|
||||
return getForActivation(desktop, Workspace::self()->activeScreen());
|
||||
}
|
||||
|
||||
Client *FocusChain::getForActivation(uint desktop, int screen) const
|
||||
{
|
||||
DesktopChains::const_iterator it = m_desktopFocusChains.find(desktop);
|
||||
if (it == m_desktopFocusChains.constEnd()) {
|
||||
return NULL;
|
||||
}
|
||||
const QList<Client*> &chain = it.value();
|
||||
for (int i = chain.size() - 1; i >= 0; --i) {
|
||||
Client *tmp = chain.at(i);
|
||||
// TODO: move the check into Client
|
||||
if (tmp->isShown(false) && tmp->isOnCurrentActivity()
|
||||
&& ( !m_separateScreenFocus || tmp->screen() == screen)) {
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void FocusChain::update(Client *client, FocusChain::Change change)
|
||||
{
|
||||
if (!client->wantsTabFocus()) {
|
||||
// Doesn't want tab focus, remove
|
||||
remove(client);
|
||||
return;
|
||||
}
|
||||
|
||||
if (client->isOnAllDesktops()) {
|
||||
// Now on all desktops, add it to focus chains it is not already in
|
||||
for (DesktopChains::iterator it = m_desktopFocusChains.begin();
|
||||
it != m_desktopFocusChains.end();
|
||||
++it) {
|
||||
QList<Client*> &chain = it.value();
|
||||
// Making first/last works only on current desktop, don't affect all desktops
|
||||
if (it.key() == m_currentDesktop
|
||||
&& (change == MakeFirst || change == MakeLast)) {
|
||||
if (change == MakeFirst) {
|
||||
makeFirstInChain(client, chain);
|
||||
} else {
|
||||
makeLastInChain(client, chain);
|
||||
}
|
||||
} else {
|
||||
insertClientIntoChain(client, chain);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Now only on desktop, remove it anywhere else
|
||||
for (DesktopChains::iterator it = m_desktopFocusChains.begin();
|
||||
it != m_desktopFocusChains.end();
|
||||
++it) {
|
||||
QList<Client*> &chain = it.value();
|
||||
if (client->isOnDesktop(it.key())) {
|
||||
updateClientInChain(client, change, chain);
|
||||
} else {
|
||||
chain.removeAll(client);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add for most recently used chain
|
||||
updateClientInChain(client, change, m_mostRecentlyUsed);
|
||||
}
|
||||
|
||||
void FocusChain::updateClientInChain(Client *client, FocusChain::Change change, QList< Client * >& chain)
|
||||
{
|
||||
if (change == MakeFirst) {
|
||||
makeFirstInChain(client, chain);
|
||||
} else if (change == MakeLast) {
|
||||
makeLastInChain(client, chain);
|
||||
} else {
|
||||
insertClientIntoChain(client, chain);
|
||||
}
|
||||
}
|
||||
|
||||
void FocusChain::insertClientIntoChain(Client *client, QList< Client * >& chain)
|
||||
{
|
||||
if (chain.contains(client)) {
|
||||
return;
|
||||
}
|
||||
if (m_activeClient && m_activeClient != client &&
|
||||
chain.last() == m_activeClient) {
|
||||
// Add it after the active client
|
||||
chain.insert(chain.size() - 1, client);
|
||||
} else {
|
||||
// Otherwise add as the first one
|
||||
chain.append(client);
|
||||
}
|
||||
}
|
||||
|
||||
void FocusChain::moveAfterClient(Client *client, Client *reference)
|
||||
{
|
||||
if (!client->wantsTabFocus()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (DesktopChains::iterator it = m_desktopFocusChains.begin();
|
||||
it != m_desktopFocusChains.end();
|
||||
++it) {
|
||||
if (!client->isOnDesktop(it.key())) {
|
||||
continue;
|
||||
}
|
||||
moveAfterClientInChain(client, reference, it.value());
|
||||
}
|
||||
moveAfterClientInChain(client, reference, m_mostRecentlyUsed);
|
||||
}
|
||||
|
||||
void FocusChain::moveAfterClientInChain(Client *client, Client *reference, QList<Client *> &chain)
|
||||
{
|
||||
if (!chain.contains(reference)) {
|
||||
return;
|
||||
}
|
||||
if (Client::belongToSameApplication(reference, client)) {
|
||||
chain.removeAll(client);
|
||||
chain.insert(chain.indexOf(reference), client);
|
||||
} else {
|
||||
chain.removeAll(client);
|
||||
for (int i = chain.size() - 1; i >= 0; --i) {
|
||||
if (Client::belongToSameApplication(reference, chain.at(i))) {
|
||||
chain.insert(i, client);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Client *FocusChain::firstMostRecentlyUsed() const
|
||||
{
|
||||
if (m_mostRecentlyUsed.isEmpty()) {
|
||||
return NULL;
|
||||
}
|
||||
return m_mostRecentlyUsed.first();
|
||||
}
|
||||
|
||||
Client *FocusChain::nextMostRecentlyUsed(Client *reference) const
|
||||
{
|
||||
if (m_mostRecentlyUsed.isEmpty()) {
|
||||
return NULL;
|
||||
}
|
||||
const int index = m_mostRecentlyUsed.indexOf(reference);
|
||||
if (index == -1 || index == 0) {
|
||||
return m_mostRecentlyUsed.last();
|
||||
}
|
||||
return m_mostRecentlyUsed.at(index - 1);
|
||||
}
|
||||
|
||||
// copied from activation.cpp
|
||||
bool FocusChain::isUsableFocusCandidate(Client *c, Client *prev) const
|
||||
{
|
||||
return c != prev &&
|
||||
c->isShown(false) && c->isOnCurrentDesktop() && c->isOnCurrentActivity() &&
|
||||
(!m_separateScreenFocus || c->isOnScreen(prev ? prev->screen() : Workspace::self()->activeScreen()));
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void FocusChain::makeFirstInChain(Client *client, QList< Client * >& chain)
|
||||
{
|
||||
chain.removeAll(client);
|
||||
chain.append(client);
|
||||
}
|
||||
|
||||
void FocusChain::makeLastInChain(Client *client, QList< Client * >& chain)
|
||||
{
|
||||
chain.removeAll(client);
|
||||
chain.prepend(client);
|
||||
}
|
||||
|
||||
bool FocusChain::contains(Client *client, uint desktop) const
|
||||
{
|
||||
DesktopChains::const_iterator it = m_desktopFocusChains.find(desktop);
|
||||
if (it == m_desktopFocusChains.end()) {
|
||||
return false;
|
||||
}
|
||||
return it.value().contains(client);
|
||||
}
|
||||
|
||||
} // namespace
|
273
focuschain.h
Normal file
273
focuschain.h
Normal file
|
@ -0,0 +1,273 @@
|
|||
/********************************************************************
|
||||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
Copyright (C) 2012 Martin Gräßlin <mgraesslin@kde.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*********************************************************************/
|
||||
#ifndef KWIN_FOCUS_CHAIN_H
|
||||
#define KWIN_FOCUS_CHAIN_H
|
||||
#include <QObject>
|
||||
#include <QHash>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
// forward declarations
|
||||
class Client;
|
||||
|
||||
/**
|
||||
* @brief Singleton class to handle the various focus chains.
|
||||
*
|
||||
* A focus chain is a list of Clients containing information on which Client should be activated.
|
||||
*
|
||||
* Internally this FocusChain holds multiple independent chains. There is one chain of most recently
|
||||
* used Clients which is primarily used by TabBox to build up the list of Clients for navigation.
|
||||
* The chains are organized as a normal QList of Clients with the most recently used Client being the
|
||||
* last item of the list, that is a LIFO like structure.
|
||||
*
|
||||
* In addition there is one chain for each virtual desktop which is used to determine which Client
|
||||
* should get activated when the user switches to another virtual desktop.
|
||||
*
|
||||
* Furthermore this class contains various helper methods for the two different kind of chains.
|
||||
**/
|
||||
class FocusChain : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum Change {
|
||||
MakeFirst,
|
||||
MakeLast,
|
||||
Update
|
||||
};
|
||||
virtual ~FocusChain();
|
||||
/**
|
||||
* @brief Updates the position of the @p client according to the requested @p change in the
|
||||
* focus chain.
|
||||
*
|
||||
* This method affects both the most recently used focus chain and the per virtual desktop focus
|
||||
* chain.
|
||||
*
|
||||
* In case the client does no longer want to get focus, it is removed from all chains. In case
|
||||
* the client is on all virtual desktops it is ensured that it is present in each of the virtual
|
||||
* desktops focus chain. In case it's on exactly one virtual desktop it is ensured that it is only
|
||||
* in the focus chain for that virtual desktop.
|
||||
*
|
||||
* Depending on @p change the Client is inserted at different positions in the focus chain. In case
|
||||
* of @c MakeFirst it is moved to the first position of the chain, in case of
|
||||
* @c MakeLast it is moved to the last position of the chain. In all other cases it
|
||||
* depends on whether the @p client is the currently active Client. If it is the active Client it
|
||||
* becomes the first Client in the chain, otherwise it is inserted at the second position that is
|
||||
* directly after the currently active Client.
|
||||
*
|
||||
* @param client The Client which should be moved inside the chains.
|
||||
* @param change Where to move the Client
|
||||
* @return void
|
||||
**/
|
||||
void update(Client *client, Change change);
|
||||
/**
|
||||
* @brief Moves @p client behind the @p reference Client in all focus chains.
|
||||
*
|
||||
* @param client The Client to move in the chains
|
||||
* @param reference The Client behind which the @p client should be moved
|
||||
* @return void
|
||||
**/
|
||||
void moveAfterClient(Client *client, Client *reference);
|
||||
/**
|
||||
* @brief Finds the best Client to become the new active Client in the focus chain for the given
|
||||
* virtual @p desktop.
|
||||
*
|
||||
* In case that separate screen focus is used only Clients on the current screen are considered.
|
||||
* If no Client for activation is found @c null is returned.
|
||||
*
|
||||
* @param desktop The virtual desktop to look for a Client for activation
|
||||
* @return :Client* The Client which could be activated or @c null if there is none.
|
||||
**/
|
||||
Client *getForActivation(uint desktop) const;
|
||||
/**
|
||||
* @brief Finds the best Client to become the new active Client in the focus chain for the given
|
||||
* virtual @p desktop on the given @p screen.
|
||||
*
|
||||
* This method makes only sense to use if separate screen focus is used. If separate screen focus
|
||||
* is disabled the @p screen is ignored.
|
||||
* If no Client for activation is found @c null is returned.
|
||||
*
|
||||
* @param desktop The virtual desktop to look for a Client for activation
|
||||
* @param screen The screen to constrain the search on with separate screen focus
|
||||
* @return :Client* The Client which could be activated or @c null if there is none.
|
||||
**/
|
||||
Client *getForActivation(uint desktop, int screen) const;
|
||||
|
||||
/**
|
||||
* @brief Checks whether the most recently used focus chain contains the given @p client.
|
||||
*
|
||||
* Does not consider the per-desktop focus chains.
|
||||
* @param client The Client to look for.
|
||||
* @return bool @c true if the most recently used focus chain contains @p client, @c false otherwise.
|
||||
**/
|
||||
bool contains(Client *client) const;
|
||||
/**
|
||||
* @brief Checks whether the focus chain for the given @p desktop contains the given @p client.
|
||||
*
|
||||
* Does not consider the most recently used focus chain.
|
||||
*
|
||||
* @param client The Client to look for.
|
||||
* @param desktop The virtual desktop whose focus chain should be used
|
||||
* @return bool @c true if the focus chain for @p desktop contains @p client, @c false otherwise.
|
||||
**/
|
||||
bool contains(Client *client, uint desktop) const;
|
||||
/**
|
||||
* @brief Queries the most recently used focus chain for the next Client after the given
|
||||
* @p reference Client.
|
||||
*
|
||||
* The navigation wraps around the borders of the chain. That is if the @p reference Client is
|
||||
* the last item of the focus chain, the first Client will be returned.
|
||||
*
|
||||
* If the @p reference Client cannot be found in the focus chain, the first element of the focus
|
||||
* chain is returned.
|
||||
*
|
||||
* @param reference The start point in the focus chain to search
|
||||
* @return :Client* The relatively next Client in the most recently used chain.
|
||||
**/
|
||||
Client *nextMostRecentlyUsed(Client *reference) const;
|
||||
/**
|
||||
* @brief Queries the focus chain for @p desktop for the next Client in relation to the given
|
||||
* @p reference Client.
|
||||
*
|
||||
* The method finds the first usable Client which is not the @p reference Client. If no Client
|
||||
* can be found @c null is returned
|
||||
*
|
||||
* @param reference The reference Client which should not be returned
|
||||
* @param desktop The virtual desktop whose focus chain should be used
|
||||
* @return :Client* The next usable Client or @c null if none can be found.
|
||||
**/
|
||||
Client *nextForDesktop(Client *reference, uint desktop) const;
|
||||
/**
|
||||
* @brief Returns the first Client in the most recently used focus chain. First Client in this
|
||||
* case means really the first Client in the chain and not the most recently used Client.
|
||||
*
|
||||
* @return :Client* The first Client in the most recently used chain.
|
||||
**/
|
||||
Client *firstMostRecentlyUsed() const;
|
||||
|
||||
/**
|
||||
* @brief Singleton getter for this FocusChain.
|
||||
* If called before the Singleton is created the method returns a @c null pointer. Be sure
|
||||
* to call @link create first.
|
||||
*
|
||||
* @return :FocusChain* Singleton pointer
|
||||
* @see create
|
||||
**/
|
||||
static FocusChain *self();
|
||||
/**
|
||||
* @brief Creates this FocusChain and sets the singleton pointer.
|
||||
*
|
||||
* @param parent The parent for this FocusChain.
|
||||
* @return :FocusChain* The created FocusChain
|
||||
**/
|
||||
static FocusChain *create(QObject *parent);
|
||||
public slots:
|
||||
/**
|
||||
* @brief Resizes the per virtual desktop focus chains from @p previousSize to @p newSize.
|
||||
* This means that for each virtual desktop between previous and new size a new focus chain is
|
||||
* created and in case the number is reduced the focus chains are destroyed.
|
||||
*
|
||||
* @param previousSize The previous number of virtual desktops
|
||||
* @param newSize The new number of virtual desktops
|
||||
* @return void
|
||||
**/
|
||||
void resize(uint previousSize, uint newSize);
|
||||
/**
|
||||
* @brief Removes @p client from all focus chains.
|
||||
*
|
||||
* @param client The Client to remove from all focus chains.
|
||||
* @return void
|
||||
**/
|
||||
void remove(KWin::Client *client);
|
||||
void setSeparateScreenFocus(bool enabled);
|
||||
void setActiveClient(KWin::Client *client);
|
||||
void setCurrentDesktop(uint previous, uint newDesktop);
|
||||
bool isUsableFocusCandidate(Client *c, Client *prev) const;
|
||||
|
||||
private:
|
||||
explicit FocusChain(QObject *parent = 0);
|
||||
/**
|
||||
* @brief Makes @p client the first Client in the given focus @p chain.
|
||||
*
|
||||
* This means the existing position of @p client is dropped and @p client is appended to the
|
||||
* @p chain which makes it the first item.
|
||||
*
|
||||
* @param client The Client to become the first in @p chain
|
||||
* @param chain The focus chain to operate on
|
||||
* @return void
|
||||
**/
|
||||
void makeFirstInChain(Client *client, QList<Client*> &chain);
|
||||
/**
|
||||
* @brief Makes @p client the last Client in the given focus @p chain.
|
||||
*
|
||||
* This means the existing position of @p client is dropped and @p client is prepended to the
|
||||
* @p chain which makes it the last item.
|
||||
*
|
||||
* @param client The Client to become the last in @p chain
|
||||
* @param chain The focus chain to operate on
|
||||
* @return void
|
||||
**/
|
||||
void makeLastInChain(Client *client, QList<Client*> &chain);
|
||||
void moveAfterClientInChain(Client *client, Client *reference, QList<Client*> &chain);
|
||||
void updateClientInChain(Client *client, Change change, QList<Client*> &chain);
|
||||
void insertClientIntoChain(Client *client, QList<Client*> &chain);
|
||||
typedef QHash<uint, QList<Client*> > DesktopChains;
|
||||
QList<Client*> m_mostRecentlyUsed;
|
||||
DesktopChains m_desktopFocusChains;
|
||||
bool m_separateScreenFocus;
|
||||
Client *m_activeClient;
|
||||
uint m_currentDesktop;
|
||||
|
||||
static FocusChain *s_manager;
|
||||
};
|
||||
|
||||
inline
|
||||
FocusChain *FocusChain::self()
|
||||
{
|
||||
return s_manager;
|
||||
}
|
||||
|
||||
inline
|
||||
bool FocusChain::contains(Client *client) const
|
||||
{
|
||||
return m_mostRecentlyUsed.contains(client);
|
||||
}
|
||||
|
||||
inline
|
||||
void FocusChain::setSeparateScreenFocus(bool enabled)
|
||||
{
|
||||
m_separateScreenFocus = enabled;
|
||||
}
|
||||
|
||||
inline
|
||||
void FocusChain::setActiveClient(Client *client)
|
||||
{
|
||||
m_activeClient = client;
|
||||
}
|
||||
|
||||
inline
|
||||
void FocusChain::setCurrentDesktop(uint previous, uint newDesktop)
|
||||
{
|
||||
Q_UNUSED(previous)
|
||||
m_currentDesktop = newDesktop;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // KWIN_FOCUS_CHAIN_H
|
36
layers.cpp
36
layers.cpp
|
@ -78,6 +78,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
|
||||
#include "utils.h"
|
||||
#include "client.h"
|
||||
#include "focuschain.h"
|
||||
#include "workspace.h"
|
||||
#include "tabbox.h"
|
||||
#include "group.h"
|
||||
|
@ -459,40 +460,7 @@ void Workspace::restack(Client* c, Client* under)
|
|||
}
|
||||
|
||||
assert(unconstrained_stacking_order.contains(c));
|
||||
for (uint desktop = 1; desktop <= VirtualDesktopManager::self()->count(); ++desktop) {
|
||||
// do for every virtual desktop to handle the case of onalldesktop windows
|
||||
if (c->wantsTabFocus() && c->isOnDesktop(desktop) && focus_chain[ desktop ].contains(under)) {
|
||||
if (Client::belongToSameApplication(under, c)) {
|
||||
// put it after the active window if it's the same app
|
||||
focus_chain[ desktop ].removeAll(c);
|
||||
focus_chain[ desktop ].insert(focus_chain[ desktop ].indexOf(under), c);
|
||||
} else {
|
||||
// put it in focus_chain[currentDesktop()] after all windows belonging to the active applicationa
|
||||
focus_chain[ desktop ].removeAll(c);
|
||||
for (int i = focus_chain[ desktop ].size() - 1; i >= 0; --i) {
|
||||
if (Client::belongToSameApplication(under, focus_chain[ desktop ].at(i))) {
|
||||
focus_chain[ desktop ].insert(i, c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// the same for global_focus_chain
|
||||
if (c->wantsTabFocus() && global_focus_chain.contains(under)) {
|
||||
if (Client::belongToSameApplication(under, c)) {
|
||||
global_focus_chain.removeAll(c);
|
||||
global_focus_chain.insert(global_focus_chain.indexOf(under), c);
|
||||
} else {
|
||||
global_focus_chain.removeAll(c);
|
||||
for (int i = global_focus_chain.size() - 1; i >= 0; --i) {
|
||||
if (Client::belongToSameApplication(under, global_focus_chain.at(i))) {
|
||||
global_focus_chain.insert(i, c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
FocusChain::self()->moveAfterClient(c, under);
|
||||
updateStackingOrder();
|
||||
}
|
||||
|
||||
|
|
|
@ -294,7 +294,7 @@ void Options::setSeparateScreenFocus(bool separateScreenFocus)
|
|||
return;
|
||||
}
|
||||
m_separateScreenFocus = separateScreenFocus;
|
||||
emit separateScreenFocusChanged();
|
||||
emit separateScreenFocusChanged(m_separateScreenFocus);
|
||||
}
|
||||
|
||||
void Options::setActiveMouseScreen(bool activeMouseScreen)
|
||||
|
|
|
@ -744,7 +744,7 @@ Q_SIGNALS:
|
|||
void delayFocusIntervalChanged();
|
||||
void shadeHoverChanged();
|
||||
void shadeHoverIntervalChanged();
|
||||
void separateScreenFocusChanged();
|
||||
void separateScreenFocusChanged(bool);
|
||||
void activeMouseScreenChanged();
|
||||
void placementChanged();
|
||||
void borderSnapZoneChanged();
|
||||
|
|
|
@ -31,6 +31,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
// kwin
|
||||
#include "client.h"
|
||||
#include "effects.h"
|
||||
#include "focuschain.h"
|
||||
#include "virtualdesktops.h"
|
||||
#include "workspace.h"
|
||||
// Qt
|
||||
|
@ -104,7 +105,7 @@ QString TabBoxHandlerImpl::desktopName(int desktop) const
|
|||
QWeakPointer<TabBoxClient> TabBoxHandlerImpl::nextClientFocusChain(TabBoxClient* client) const
|
||||
{
|
||||
if (TabBoxClientImpl* c = static_cast< TabBoxClientImpl* >(client)) {
|
||||
Client* next = Workspace::self()->tabBox()->nextClientFocusChain(c->client());
|
||||
Client* next = FocusChain::self()->nextMostRecentlyUsed(c->client());
|
||||
if (next)
|
||||
return next->tabBoxClient();
|
||||
}
|
||||
|
@ -113,7 +114,7 @@ QWeakPointer<TabBoxClient> TabBoxHandlerImpl::nextClientFocusChain(TabBoxClient*
|
|||
|
||||
QWeakPointer< TabBoxClient > TabBoxHandlerImpl::firstClientFocusChain() const
|
||||
{
|
||||
if (Client *c = m_tabBox->firstClientFocusChain()) {
|
||||
if (Client *c = FocusChain::self()->firstMostRecentlyUsed()) {
|
||||
return QWeakPointer<TabBoxClient>(c->tabBoxClient());
|
||||
} else {
|
||||
return QWeakPointer<TabBoxClient>();
|
||||
|
@ -123,7 +124,7 @@ QWeakPointer< TabBoxClient > TabBoxHandlerImpl::firstClientFocusChain() const
|
|||
bool TabBoxHandlerImpl::isInFocusChain(TabBoxClient *client) const
|
||||
{
|
||||
if (TabBoxClientImpl *c = static_cast<TabBoxClientImpl*>(client)) {
|
||||
return Workspace::self()->globalFocusChain().contains(c->client());
|
||||
return FocusChain::self()->contains(c->client());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -1493,50 +1494,6 @@ int TabBox::previousDesktopStatic(int iDesktop) const
|
|||
return functor(iDesktop, true);
|
||||
}
|
||||
|
||||
/*!
|
||||
auxiliary functions to travers all clients according to the focus
|
||||
order. Useful for kwms Alt-tab feature.
|
||||
*/
|
||||
Client* TabBox::nextClientFocusChain(Client* c) const
|
||||
{
|
||||
const ClientList &globalFocusChain = Workspace::self()->globalFocusChain();
|
||||
if (globalFocusChain.isEmpty())
|
||||
return 0;
|
||||
int pos = globalFocusChain.indexOf(c);
|
||||
if (pos == -1)
|
||||
return globalFocusChain.last();
|
||||
if (pos == 0)
|
||||
return globalFocusChain.last();
|
||||
pos--;
|
||||
return globalFocusChain[ pos ];
|
||||
}
|
||||
|
||||
/*!
|
||||
auxiliary functions to travers all clients according to the focus
|
||||
order. Useful for kwms Alt-tab feature.
|
||||
*/
|
||||
Client* TabBox::previousClientFocusChain(Client* c) const
|
||||
{
|
||||
const ClientList &globalFocusChain = Workspace::self()->globalFocusChain();
|
||||
if (globalFocusChain.isEmpty())
|
||||
return 0;
|
||||
int pos = globalFocusChain.indexOf(c);
|
||||
if (pos == -1)
|
||||
return globalFocusChain.first();
|
||||
pos++;
|
||||
if (pos == globalFocusChain.count())
|
||||
return globalFocusChain.first();
|
||||
return globalFocusChain[ pos ];
|
||||
}
|
||||
|
||||
Client *TabBox::firstClientFocusChain() const
|
||||
{
|
||||
const ClientList &globalFocusChain = Workspace::self()->globalFocusChain();
|
||||
if (globalFocusChain.isEmpty())
|
||||
return NULL;
|
||||
return globalFocusChain.first();
|
||||
}
|
||||
|
||||
/*!
|
||||
auxiliary functions to travers all clients according to the static
|
||||
order. Useful for the CDE-style Alt-tab feature.
|
||||
|
|
|
@ -165,9 +165,6 @@ public:
|
|||
|
||||
void initShortcuts(KActionCollection* keys);
|
||||
|
||||
Client* nextClientFocusChain(Client*) const;
|
||||
Client* previousClientFocusChain(Client*) const;
|
||||
Client* firstClientFocusChain() const;
|
||||
Client* nextClientStatic(Client*) const;
|
||||
Client* previousClientStatic(Client*) const;
|
||||
int nextDesktopStatic(int iDesktop) const;
|
||||
|
|
106
workspace.cpp
106
workspace.cpp
|
@ -47,6 +47,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
|
||||
#include "client.h"
|
||||
#include "composite.h"
|
||||
#include "focuschain.h"
|
||||
#ifdef KWIN_BUILD_TABBOX
|
||||
#include "tabbox.h"
|
||||
#endif
|
||||
|
@ -270,6 +271,14 @@ void Workspace::init()
|
|||
connect(this, SIGNAL(clientActivated(KWin::Client*)), screenEdges, SIGNAL(checkBlocking()));
|
||||
#endif
|
||||
|
||||
FocusChain *focusChain = FocusChain::create(this);
|
||||
connect(this, SIGNAL(clientRemoved(KWin::Client*)), focusChain, SLOT(remove(KWin::Client*)));
|
||||
connect(this, SIGNAL(clientActivated(KWin::Client*)), focusChain, SLOT(setActiveClient(KWin::Client*)));
|
||||
connect(VirtualDesktopManager::self(), SIGNAL(countChanged(uint,uint)), focusChain, SLOT(resize(uint,uint)));
|
||||
connect(VirtualDesktopManager::self(), SIGNAL(currentChanged(uint,uint)), focusChain, SLOT(setCurrentDesktop(uint,uint)));
|
||||
connect(options, SIGNAL(separateScreenFocusChanged(bool)), focusChain, SLOT(setSeparateScreenFocus(bool)));
|
||||
focusChain->setSeparateScreenFocus(options->isSeparateScreenFocus());
|
||||
|
||||
supportWindow = new QWidget(NULL, Qt::X11BypassWindowManagerHint);
|
||||
XLowerWindow(display(), supportWindow->winId()); // See usage in layers.cpp
|
||||
|
||||
|
@ -610,7 +619,7 @@ void Workspace::addClient(Client* c, allowed_t)
|
|||
if (active_client == NULL && should_get_focus.isEmpty() && c->isOnCurrentDesktop())
|
||||
requestFocus(c); // TODO: Make sure desktop is active after startup if there's no other window active
|
||||
} else {
|
||||
updateFocusChains(c, FocusChainUpdate); // Add to focus chain if not already there
|
||||
FocusChain::self()->update(c, FocusChain::Update);
|
||||
clients.append(c);
|
||||
}
|
||||
if (!unconstrained_stacking_order.contains(c))
|
||||
|
@ -685,9 +694,6 @@ void Workspace::removeClient(Client* c, allowed_t)
|
|||
clients.removeAll(c);
|
||||
desktops.removeAll(c);
|
||||
x_stacking_dirty = true;
|
||||
for (uint i = 1; i <= VirtualDesktopManager::self()->count(); ++i)
|
||||
focus_chain[i].removeAll(c);
|
||||
global_focus_chain.removeAll(c);
|
||||
attention_chain.removeAll(c);
|
||||
showing_desktop_clients.removeAll(c);
|
||||
Group* group = findGroup(c->window());
|
||||
|
@ -756,71 +762,6 @@ void Workspace::removeDeleted(Deleted* c, allowed_t)
|
|||
x_stacking_dirty = true;
|
||||
}
|
||||
|
||||
void Workspace::updateFocusChains(Client* c, FocusChainChange change)
|
||||
{
|
||||
if (!c->wantsTabFocus()) { // Doesn't want tab focus, remove
|
||||
for (uint i = 1; i <= VirtualDesktopManager::self()->count(); ++i)
|
||||
focus_chain[i].removeAll(c);
|
||||
global_focus_chain.removeAll(c);
|
||||
return;
|
||||
}
|
||||
if (c->desktop() == NET::OnAllDesktops) {
|
||||
// Now on all desktops, add it to focus_chains it is not already in
|
||||
for (uint i = 1; i <= VirtualDesktopManager::self()->count(); i++) {
|
||||
// Making first/last works only on current desktop, don't affect all desktops
|
||||
if (i == VirtualDesktopManager::self()->current()
|
||||
&& (change == FocusChainMakeFirst || change == FocusChainMakeLast)) {
|
||||
focus_chain[i].removeAll(c);
|
||||
if (change == FocusChainMakeFirst)
|
||||
focus_chain[i].append(c);
|
||||
else
|
||||
focus_chain[i].prepend(c);
|
||||
} else if (!focus_chain[i].contains(c)) {
|
||||
// Add it after the active one
|
||||
if (active_client != NULL && active_client != c &&
|
||||
!focus_chain[i].isEmpty() && focus_chain[i].last() == active_client)
|
||||
focus_chain[i].insert(focus_chain[i].size() - 1, c);
|
||||
else
|
||||
focus_chain[i].append(c); // Otherwise add as the first one
|
||||
}
|
||||
}
|
||||
} else { // Now only on desktop, remove it anywhere else
|
||||
for (uint i = 1; i <= VirtualDesktopManager::self()->count(); i++) {
|
||||
if (c->isOnDesktop(i)) {
|
||||
if (change == FocusChainMakeFirst) {
|
||||
focus_chain[i].removeAll(c);
|
||||
focus_chain[i].append(c);
|
||||
} else if (change == FocusChainMakeLast) {
|
||||
focus_chain[i].removeAll(c);
|
||||
focus_chain[i].prepend(c);
|
||||
} else if (!focus_chain[i].contains(c)) {
|
||||
// Add it after the active one
|
||||
if (active_client != NULL && active_client != c &&
|
||||
!focus_chain[i].isEmpty() && focus_chain[i].last() == active_client)
|
||||
focus_chain[i].insert(focus_chain[i].size() - 1, c);
|
||||
else
|
||||
focus_chain[i].append(c); // Otherwise add as the first one
|
||||
}
|
||||
} else
|
||||
focus_chain[i].removeAll(c);
|
||||
}
|
||||
}
|
||||
if (change == FocusChainMakeFirst) {
|
||||
global_focus_chain.removeAll(c);
|
||||
global_focus_chain.append(c);
|
||||
} else if (change == FocusChainMakeLast) {
|
||||
global_focus_chain.removeAll(c);
|
||||
global_focus_chain.prepend(c);
|
||||
} else if (!global_focus_chain.contains(c)) {
|
||||
// Add it after the active one
|
||||
if (active_client != NULL && active_client != c &&
|
||||
!global_focus_chain.isEmpty() && global_focus_chain.last() == active_client)
|
||||
global_focus_chain.insert(global_focus_chain.size() - 1, c);
|
||||
else
|
||||
global_focus_chain.append(c); // Otherwise add as the first one
|
||||
}
|
||||
}
|
||||
|
||||
void Workspace::updateToolWindows(bool also_hide)
|
||||
{
|
||||
// TODO: What if Client's transiency/group changes? should this be called too? (I'm paranoid, am I not?)
|
||||
|
@ -1230,7 +1171,7 @@ void Workspace::activateClientOnNewDesktop(uint desktop)
|
|||
Client *Workspace::findClientToActivateOnDesktop(uint desktop)
|
||||
{
|
||||
if (movingClient != NULL && active_client == movingClient &&
|
||||
focus_chain[desktop].contains(active_client) &&
|
||||
FocusChain::self()->contains(active_client, desktop) &&
|
||||
active_client->isShown(true) && active_client->isOnCurrentDesktop()) {
|
||||
// A requestFocus call will fail, as the client is already active
|
||||
return active_client;
|
||||
|
@ -1255,14 +1196,7 @@ Client *Workspace::findClientToActivateOnDesktop(uint desktop)
|
|||
}
|
||||
}
|
||||
}
|
||||
for (int i = focus_chain[desktop].size() - 1; i >= 0; --i) {
|
||||
Client* tmp = focus_chain[desktop].at(i);
|
||||
if (tmp->isShown(false) && tmp->isOnCurrentActivity()
|
||||
&& ( !options->isSeparateScreenFocus() || tmp->screen() == activeScreen() )) {
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
return FocusChain::self()->getForActivation(desktop);
|
||||
}
|
||||
|
||||
#ifdef KWIN_BUILD_ACTIVITIES
|
||||
|
@ -1410,19 +1344,7 @@ void Workspace::updateCurrentActivity(const QString &new_activity)
|
|||
//FIXME below here is a lot of focuschain stuff, probably all wrong now
|
||||
if (options->focusPolicyIsReasonable()) {
|
||||
// Search in focus chain
|
||||
if (movingClient != NULL && active_client == movingClient &&
|
||||
focus_chain[VirtualDesktopManager::self()->current()].contains(active_client) &&
|
||||
active_client->isShown(true) && active_client->isOnCurrentDesktop())
|
||||
c = active_client; // The requestFocus below will fail, as the client is already active
|
||||
if (!c) {
|
||||
for (int i = focus_chain[VirtualDesktopManager::self()->current()].size() - 1; i >= 0; --i) {
|
||||
if (focus_chain[VirtualDesktopManager::self()->current()].at(i)->isShown(false) &&
|
||||
focus_chain[VirtualDesktopManager::self()->current()].at(i)->isOnCurrentActivity()) {
|
||||
c = focus_chain[VirtualDesktopManager::self()->current()].at(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
c = FocusChain::self()->getForActivation(VirtualDesktopManager::self()->current());
|
||||
}
|
||||
// If "unreasonable focus policy" and active_client is on_all_desktops and
|
||||
// under mouse (Hence == old_active_client), conserve focus.
|
||||
|
@ -1486,8 +1408,6 @@ void Workspace::slotDesktopCountChanged(uint previousCount, uint newCount)
|
|||
{
|
||||
Q_UNUSED(previousCount)
|
||||
Placement::self()->reinitCascading(0);
|
||||
// Make it +1, so that it can be accessed as [1..numberofdesktops]
|
||||
focus_chain.resize(newCount + 1);
|
||||
|
||||
resetClientAreas(newCount);
|
||||
}
|
||||
|
|
11
workspace.h
11
workspace.h
|
@ -253,9 +253,6 @@ public:
|
|||
#endif
|
||||
bool hasTabBox() const;
|
||||
|
||||
const ClientList &globalFocusChain() const {
|
||||
return global_focus_chain;
|
||||
}
|
||||
KActionCollection* actionCollection() const {
|
||||
return keys;
|
||||
}
|
||||
|
@ -374,12 +371,6 @@ public:
|
|||
bool checkStartupNotification(Window w, KStartupInfoId& id, KStartupInfoData& data);
|
||||
|
||||
void focusToNull(); // SELI TODO: Public?
|
||||
enum FocusChainChange {
|
||||
FocusChainMakeFirst,
|
||||
FocusChainMakeLast,
|
||||
FocusChainUpdate
|
||||
};
|
||||
void updateFocusChains(Client* c, FocusChainChange change);
|
||||
|
||||
bool forcedGlobalMouseGrab() const;
|
||||
void clientShortcutUpdated(Client* c);
|
||||
|
@ -653,8 +644,6 @@ private:
|
|||
bool force_restacking;
|
||||
mutable ToplevelList x_stacking; // From XQueryTree()
|
||||
mutable bool x_stacking_dirty;
|
||||
QVector< ClientList > focus_chain; // Currently ative last
|
||||
ClientList global_focus_chain; // This one is only for things like tabbox's MRU
|
||||
ClientList should_get_focus; // Last is most recent
|
||||
ClientList attention_chain;
|
||||
|
||||
|
|
Loading…
Reference in a new issue