Use the first client as entrance to the focus chain if no active window
The recently used mode of TabBox uses the active window as the entrance into the focus chain. If there is no active window it does not find any Clients. To solve this issue the ClientModel now uses the first entry of the focus chain in case there is no active window. BUG: 305449 FIXED-IN: 4.9.1 REVIEW: 106088
This commit is contained in:
parent
74fe348b96
commit
a4fed7188c
8 changed files with 78 additions and 10 deletions
|
@ -138,7 +138,7 @@ int ClientModel::rowCount(const QModelIndex& parent) const
|
||||||
count = qRound(sqrt(float(m_clientList.count())));
|
count = qRound(sqrt(float(m_clientList.count())));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return qMax(count, 1);
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
QModelIndex ClientModel::parent(const QModelIndex& child) const
|
QModelIndex ClientModel::parent(const QModelIndex& child) const
|
||||||
|
@ -188,6 +188,12 @@ void ClientModel::createClientList(int desktop, bool partialReset)
|
||||||
switch(tabBox->config().clientSwitchingMode()) {
|
switch(tabBox->config().clientSwitchingMode()) {
|
||||||
case TabBoxConfig::FocusChainSwitching: {
|
case TabBoxConfig::FocusChainSwitching: {
|
||||||
TabBoxClient* c = tabBox->nextClientFocusChain(start).data();
|
TabBoxClient* c = tabBox->nextClientFocusChain(start).data();
|
||||||
|
if (!c) {
|
||||||
|
QSharedPointer<TabBoxClient> firstClient = tabBox->firstClientFocusChain().toStrongRef();
|
||||||
|
if (firstClient) {
|
||||||
|
c = firstClient.data();
|
||||||
|
}
|
||||||
|
}
|
||||||
TabBoxClient* stop = c;
|
TabBoxClient* stop = c;
|
||||||
while (c) {
|
while (c) {
|
||||||
QWeakPointer<TabBoxClient> add = tabBox->clientToAddToList(c, desktop);
|
QWeakPointer<TabBoxClient> add = tabBox->clientToAddToList(c, desktop);
|
||||||
|
|
|
@ -103,6 +103,15 @@ QWeakPointer<TabBoxClient> TabBoxHandlerImpl::nextClientFocusChain(TabBoxClient*
|
||||||
return QWeakPointer<TabBoxClient>();
|
return QWeakPointer<TabBoxClient>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QWeakPointer< TabBoxClient > TabBoxHandlerImpl::firstClientFocusChain() const
|
||||||
|
{
|
||||||
|
if (Client *c = m_tabBox->firstClientFocusChain()) {
|
||||||
|
return QWeakPointer<TabBoxClient>(c->tabBoxClient());
|
||||||
|
} else {
|
||||||
|
return QWeakPointer<TabBoxClient>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int TabBoxHandlerImpl::nextDesktopFocusChain(int desktop) const
|
int TabBoxHandlerImpl::nextDesktopFocusChain(int desktop) const
|
||||||
{
|
{
|
||||||
return m_tabBox->nextDesktopFocusChain(desktop);
|
return m_tabBox->nextDesktopFocusChain(desktop);
|
||||||
|
@ -1519,6 +1528,14 @@ Client* TabBox::previousClientFocusChain(Client* c) const
|
||||||
return globalFocusChain[ pos ];
|
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
|
auxiliary functions to travers all clients according to the static
|
||||||
order. Useful for the CDE-style Alt-tab feature.
|
order. Useful for the CDE-style Alt-tab feature.
|
||||||
|
|
|
@ -51,6 +51,7 @@ public:
|
||||||
virtual QString desktopName(TabBoxClient* client) const;
|
virtual QString desktopName(TabBoxClient* client) const;
|
||||||
virtual QString desktopName(int desktop) const;
|
virtual QString desktopName(int desktop) const;
|
||||||
virtual QWeakPointer< TabBoxClient > nextClientFocusChain(TabBoxClient* client) const;
|
virtual QWeakPointer< TabBoxClient > nextClientFocusChain(TabBoxClient* client) const;
|
||||||
|
virtual QWeakPointer< TabBoxClient > firstClientFocusChain() const;
|
||||||
virtual int nextDesktopFocusChain(int desktop) const;
|
virtual int nextDesktopFocusChain(int desktop) const;
|
||||||
virtual int numberOfDesktops() const;
|
virtual int numberOfDesktops() const;
|
||||||
virtual TabBoxClientList stackingOrder() const;
|
virtual TabBoxClientList stackingOrder() const;
|
||||||
|
@ -163,6 +164,7 @@ public:
|
||||||
|
|
||||||
Client* nextClientFocusChain(Client*) const;
|
Client* nextClientFocusChain(Client*) const;
|
||||||
Client* previousClientFocusChain(Client*) const;
|
Client* previousClientFocusChain(Client*) const;
|
||||||
|
Client* firstClientFocusChain() const;
|
||||||
Client* nextClientStatic(Client*) const;
|
Client* nextClientStatic(Client*) const;
|
||||||
Client* previousClientStatic(Client*) const;
|
Client* previousClientStatic(Client*) const;
|
||||||
int nextDesktopFocusChain(int iDesktop) const;
|
int nextDesktopFocusChain(int iDesktop) const;
|
||||||
|
|
|
@ -111,6 +111,14 @@ public:
|
||||||
* @return The next TabBoxClient in focus chain
|
* @return The next TabBoxClient in focus chain
|
||||||
*/
|
*/
|
||||||
virtual QWeakPointer<TabBoxClient> nextClientFocusChain(TabBoxClient* client) const = 0;
|
virtual QWeakPointer<TabBoxClient> nextClientFocusChain(TabBoxClient* client) const = 0;
|
||||||
|
/**
|
||||||
|
* This method is used by the ClientModel to find an entrance into the focus chain in case
|
||||||
|
* there is no active Client.
|
||||||
|
*
|
||||||
|
* @return The first Client of the focus chain
|
||||||
|
* @since 4.9.1
|
||||||
|
**/
|
||||||
|
virtual QWeakPointer<TabBoxClient> firstClientFocusChain() const = 0;
|
||||||
/**
|
/**
|
||||||
* @param client The client whose desktop name should be retrieved
|
* @param client The client whose desktop name should be retrieved
|
||||||
* @return The desktop name of the given TabBoxClient. If the client is
|
* @return The desktop name of the given TabBoxClient. If the client is
|
||||||
|
|
|
@ -39,10 +39,12 @@ void MockTabBoxHandler::grabbedKeyEvent(QKeyEvent *event) const
|
||||||
|
|
||||||
QWeakPointer< TabBox::TabBoxClient > MockTabBoxHandler::activeClient() const
|
QWeakPointer< TabBox::TabBoxClient > MockTabBoxHandler::activeClient() const
|
||||||
{
|
{
|
||||||
if (!m_windows.isEmpty()) {
|
return m_activeClient;
|
||||||
return QWeakPointer< TabBox::TabBoxClient >(m_windows.first());
|
}
|
||||||
}
|
|
||||||
return QWeakPointer<TabBox::TabBoxClient>();
|
void MockTabBoxHandler::setActiveClient(const QWeakPointer< TabBox::TabBoxClient >& client)
|
||||||
|
{
|
||||||
|
m_activeClient = client;
|
||||||
}
|
}
|
||||||
|
|
||||||
QWeakPointer< TabBox::TabBoxClient > MockTabBoxHandler::clientToAddToList(TabBox::TabBoxClient *client, int desktop) const
|
QWeakPointer< TabBox::TabBoxClient > MockTabBoxHandler::clientToAddToList(TabBox::TabBoxClient *client, int desktop) const
|
||||||
|
@ -59,11 +61,6 @@ QWeakPointer< TabBox::TabBoxClient > MockTabBoxHandler::clientToAddToList(TabBox
|
||||||
|
|
||||||
QWeakPointer< TabBox::TabBoxClient > MockTabBoxHandler::nextClientFocusChain(TabBox::TabBoxClient *client) const
|
QWeakPointer< TabBox::TabBoxClient > MockTabBoxHandler::nextClientFocusChain(TabBox::TabBoxClient *client) const
|
||||||
{
|
{
|
||||||
if (!client) {
|
|
||||||
if (!m_windows.isEmpty()) {
|
|
||||||
return QWeakPointer< TabBox::TabBoxClient >(m_windows.first());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
QList< QSharedPointer< TabBox::TabBoxClient > >::const_iterator it = m_windows.constBegin();
|
QList< QSharedPointer< TabBox::TabBoxClient > >::const_iterator it = m_windows.constBegin();
|
||||||
for (; it != m_windows.constEnd(); ++it) {
|
for (; it != m_windows.constEnd(); ++it) {
|
||||||
if ((*it).data() == client) {
|
if ((*it).data() == client) {
|
||||||
|
@ -78,10 +75,19 @@ QWeakPointer< TabBox::TabBoxClient > MockTabBoxHandler::nextClientFocusChain(Tab
|
||||||
return QWeakPointer< TabBox::TabBoxClient >();
|
return QWeakPointer< TabBox::TabBoxClient >();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QWeakPointer< TabBox::TabBoxClient > MockTabBoxHandler::firstClientFocusChain() const
|
||||||
|
{
|
||||||
|
if (m_windows.isEmpty()) {
|
||||||
|
return QWeakPointer<TabBox::TabBoxClient>();
|
||||||
|
}
|
||||||
|
return m_windows.first();
|
||||||
|
}
|
||||||
|
|
||||||
QWeakPointer< TabBox::TabBoxClient > MockTabBoxHandler::createMockWindow(const QString &caption, WId id)
|
QWeakPointer< TabBox::TabBoxClient > MockTabBoxHandler::createMockWindow(const QString &caption, WId id)
|
||||||
{
|
{
|
||||||
QSharedPointer< TabBox::TabBoxClient > client(new MockTabBoxClient(caption, id));
|
QSharedPointer< TabBox::TabBoxClient > client(new MockTabBoxClient(caption, id));
|
||||||
m_windows.append(client);
|
m_windows.append(client);
|
||||||
|
m_activeClient = client;
|
||||||
return QWeakPointer< TabBox::TabBoxClient >(client);
|
return QWeakPointer< TabBox::TabBoxClient >(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,7 @@ public:
|
||||||
virtual void activateAndClose() {
|
virtual void activateAndClose() {
|
||||||
}
|
}
|
||||||
virtual QWeakPointer< TabBox::TabBoxClient > activeClient() const;
|
virtual QWeakPointer< TabBox::TabBoxClient > activeClient() const;
|
||||||
|
void setActiveClient(const QWeakPointer<TabBox::TabBoxClient> &client);
|
||||||
virtual int activeScreen() const {
|
virtual int activeScreen() const {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -58,6 +59,7 @@ public:
|
||||||
virtual void hideOutline() {
|
virtual void hideOutline() {
|
||||||
}
|
}
|
||||||
virtual QWeakPointer< TabBox::TabBoxClient > nextClientFocusChain(TabBox::TabBoxClient *client) const;
|
virtual QWeakPointer< TabBox::TabBoxClient > nextClientFocusChain(TabBox::TabBoxClient *client) const;
|
||||||
|
virtual QWeakPointer<TabBox::TabBoxClient> firstClientFocusChain() const;
|
||||||
virtual int nextDesktopFocusChain(int desktop) const {
|
virtual int nextDesktopFocusChain(int desktop) const {
|
||||||
Q_UNUSED(desktop)
|
Q_UNUSED(desktop)
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -88,6 +90,7 @@ public:
|
||||||
void closeWindow(TabBox::TabBoxClient *client);
|
void closeWindow(TabBox::TabBoxClient *client);
|
||||||
private:
|
private:
|
||||||
QList< QSharedPointer<TabBox::TabBoxClient> > m_windows;
|
QList< QSharedPointer<TabBox::TabBoxClient> > m_windows;
|
||||||
|
QWeakPointer<TabBox::TabBoxClient> m_activeClient;
|
||||||
};
|
};
|
||||||
} // namespace KWin
|
} // namespace KWin
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -44,4 +44,23 @@ void TestTabBoxClientModel::testLongestCaptionWithNullClient()
|
||||||
QCOMPARE(clientModel->longestCaption(), QString());
|
QCOMPARE(clientModel->longestCaption(), QString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TestTabBoxClientModel::testCreateClientListNoActiveClient()
|
||||||
|
{
|
||||||
|
MockTabBoxHandler tabboxhandler;
|
||||||
|
tabboxhandler.setConfig(TabBox::TabBoxConfig());
|
||||||
|
TabBox::ClientModel *clientModel = new TabBox::ClientModel(&tabboxhandler);
|
||||||
|
clientModel->createClientList();
|
||||||
|
QCOMPARE(clientModel->rowCount(), 0);
|
||||||
|
// create two windows, rowCount() should go to two
|
||||||
|
QWeakPointer<TabBox::TabBoxClient> client = tabboxhandler.createMockWindow(QString("test"), 1);
|
||||||
|
tabboxhandler.createMockWindow(QString("test2"), 2);
|
||||||
|
clientModel->createClientList();
|
||||||
|
QCOMPARE(clientModel->rowCount(), 2);
|
||||||
|
// let's ensure there is no active client
|
||||||
|
tabboxhandler.setActiveClient(QWeakPointer<TabBox::TabBoxClient>());
|
||||||
|
// now it should still have two members in the list
|
||||||
|
clientModel->createClientList();
|
||||||
|
QCOMPARE(clientModel->rowCount(), 2);
|
||||||
|
}
|
||||||
|
|
||||||
QTEST_MAIN(TestTabBoxClientModel)
|
QTEST_MAIN(TestTabBoxClientModel)
|
||||||
|
|
|
@ -33,6 +33,13 @@ private slots:
|
||||||
* See bug #303840
|
* See bug #303840
|
||||||
**/
|
**/
|
||||||
void testLongestCaptionWithNullClient();
|
void testLongestCaptionWithNullClient();
|
||||||
|
/**
|
||||||
|
* Tests the creation of the Client list for the case that
|
||||||
|
* there is no active Client, but that Clients actually exist.
|
||||||
|
*
|
||||||
|
* See BUG: 305449
|
||||||
|
**/
|
||||||
|
void testCreateClientListNoActiveClient();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue