diff --git a/tabbox/clientmodel.cpp b/tabbox/clientmodel.cpp index ddb0659a54..f16368f8a5 100644 --- a/tabbox/clientmodel.cpp +++ b/tabbox/clientmodel.cpp @@ -161,25 +161,24 @@ void ClientModel::createClientList(int desktop, bool partialReset) switch(tabBox->config().clientSwitchingMode()) { case TabBoxConfig::FocusChainSwitching: { - TabBoxClient* c = tabBox->nextClientFocusChain(start).data(); + TabBoxClient* c = start; + if (!c) { + QSharedPointer firstClient = tabBox->firstClientFocusChain().toStrongRef(); + if (firstClient) { + c = firstClient.data(); + } + } TabBoxClient* stop = c; - while (c) { + do { QWeakPointer add = tabBox->clientToAddToList(c, desktop); if (!add.isNull()) { - if (start == add.data()) { - m_clientList.removeAll(add); - m_clientList.prepend(add); - } else - m_clientList += add; + m_clientList += add; if (add.data()->isFirstInTabBox()) { stickyClients << add; } } c = tabBox->nextClientFocusChain(c).data(); - - if (c == stop) - break; - } + } while (c && c != stop); break; } case TabBoxConfig::StackingOrderSwitching: { diff --git a/tabbox/tabbox.cpp b/tabbox/tabbox.cpp index 0c8fcb38cc..a780a0d4ab 100644 --- a/tabbox/tabbox.cpp +++ b/tabbox/tabbox.cpp @@ -103,6 +103,15 @@ QWeakPointer TabBoxHandlerImpl::nextClientFocusChain(TabBoxClient* return QWeakPointer(); } +QWeakPointer< TabBoxClient > TabBoxHandlerImpl::firstClientFocusChain() const +{ + if (Client *c = m_tabBox->firstClientFocusChain()) { + return QWeakPointer(c->tabBoxClient()); + } else { + return QWeakPointer(); + } +} + int TabBoxHandlerImpl::nextDesktopFocusChain(int desktop) const { return m_tabBox->nextDesktopFocusChain(desktop); @@ -216,6 +225,9 @@ bool TabBoxHandlerImpl::checkMultiScreen(TabBoxClient* client) const QWeakPointer TabBoxHandlerImpl::clientToAddToList(TabBoxClient* client, int desktop) const { + if (!client) { + return QWeakPointer(); + } Client* ret = NULL; Client* current = (static_cast< TabBoxClientImpl* >(client))->client(); @@ -1515,6 +1527,14 @@ Client* TabBox::previousClientFocusChain(Client* c) const 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. diff --git a/tabbox/tabbox.h b/tabbox/tabbox.h index bf69ad9184..6652f93d05 100644 --- a/tabbox/tabbox.h +++ b/tabbox/tabbox.h @@ -51,6 +51,7 @@ public: virtual QString desktopName(TabBoxClient* client) const; virtual QString desktopName(int desktop) const; virtual QWeakPointer< TabBoxClient > nextClientFocusChain(TabBoxClient* client) const; + virtual QWeakPointer< TabBoxClient > firstClientFocusChain() const; virtual int nextDesktopFocusChain(int desktop) const; virtual int numberOfDesktops() const; virtual TabBoxClientList stackingOrder() const; @@ -163,6 +164,7 @@ public: Client* nextClientFocusChain(Client*) const; Client* previousClientFocusChain(Client*) const; + Client* firstClientFocusChain() const; Client* nextClientStatic(Client*) const; Client* previousClientStatic(Client*) const; int nextDesktopFocusChain(int iDesktop) const; diff --git a/tabbox/tabboxhandler.h b/tabbox/tabboxhandler.h index 976f201735..7abddfcd0e 100644 --- a/tabbox/tabboxhandler.h +++ b/tabbox/tabboxhandler.h @@ -111,6 +111,14 @@ public: * @return The next TabBoxClient in focus chain */ virtual QWeakPointer 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 firstClientFocusChain() const = 0; /** * @param client The client whose desktop name should be retrieved * @return The desktop name of the given TabBoxClient. If the client is diff --git a/tabbox/tests/mock_tabboxhandler.cpp b/tabbox/tests/mock_tabboxhandler.cpp index 1d27dc752b..c3ad7a9a46 100644 --- a/tabbox/tests/mock_tabboxhandler.cpp +++ b/tabbox/tests/mock_tabboxhandler.cpp @@ -39,10 +39,12 @@ void MockTabBoxHandler::grabbedKeyEvent(QKeyEvent *event) const QWeakPointer< TabBox::TabBoxClient > MockTabBoxHandler::activeClient() const { - if (!m_windows.isEmpty()) { - return QWeakPointer< TabBox::TabBoxClient >(m_windows.first()); - } - return QWeakPointer(); + return m_activeClient; +} + +void MockTabBoxHandler::setActiveClient(const QWeakPointer< TabBox::TabBoxClient >& client) +{ + m_activeClient = client; } 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 { - if (!client) { - if (!m_windows.isEmpty()) { - return QWeakPointer< TabBox::TabBoxClient >(m_windows.first()); - } - } QList< QSharedPointer< TabBox::TabBoxClient > >::const_iterator it = m_windows.constBegin(); for (; it != m_windows.constEnd(); ++it) { if ((*it).data() == client) { @@ -78,10 +75,19 @@ QWeakPointer< TabBox::TabBoxClient > MockTabBoxHandler::nextClientFocusChain(Tab return QWeakPointer< TabBox::TabBoxClient >(); } +QWeakPointer< TabBox::TabBoxClient > MockTabBoxHandler::firstClientFocusChain() const +{ + if (m_windows.isEmpty()) { + return QWeakPointer(); + } + return m_windows.first(); +} + QWeakPointer< TabBox::TabBoxClient > MockTabBoxHandler::createMockWindow(const QString &caption, WId id) { QSharedPointer< TabBox::TabBoxClient > client(new MockTabBoxClient(caption, id)); m_windows.append(client); + m_activeClient = client; return QWeakPointer< TabBox::TabBoxClient >(client); } diff --git a/tabbox/tests/mock_tabboxhandler.h b/tabbox/tests/mock_tabboxhandler.h index f13a820aac..a2236486cb 100644 --- a/tabbox/tests/mock_tabboxhandler.h +++ b/tabbox/tests/mock_tabboxhandler.h @@ -32,6 +32,7 @@ public: virtual void activateAndClose() { } virtual QWeakPointer< TabBox::TabBoxClient > activeClient() const; + void setActiveClient(const QWeakPointer &client); virtual int activeScreen() const { return 0; } @@ -58,6 +59,7 @@ public: virtual void hideOutline() { } virtual QWeakPointer< TabBox::TabBoxClient > nextClientFocusChain(TabBox::TabBoxClient *client) const; + virtual QWeakPointer firstClientFocusChain() const; virtual int nextDesktopFocusChain(int desktop) const { Q_UNUSED(desktop) return 1; @@ -88,6 +90,7 @@ public: void closeWindow(TabBox::TabBoxClient *client); private: QList< QSharedPointer > m_windows; + QWeakPointer m_activeClient; }; } // namespace KWin #endif diff --git a/tabbox/tests/test_tabbox_clientmodel.cpp b/tabbox/tests/test_tabbox_clientmodel.cpp index cd2c963629..79d02534e4 100644 --- a/tabbox/tests/test_tabbox_clientmodel.cpp +++ b/tabbox/tests/test_tabbox_clientmodel.cpp @@ -44,4 +44,23 @@ void TestTabBoxClientModel::testLongestCaptionWithNullClient() 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 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()); + // now it should still have two members in the list + clientModel->createClientList(); + QCOMPARE(clientModel->rowCount(), 2); +} + QTEST_MAIN(TestTabBoxClientModel) diff --git a/tabbox/tests/test_tabbox_clientmodel.h b/tabbox/tests/test_tabbox_clientmodel.h index 1bdf0d4aa4..2ec6608a34 100644 --- a/tabbox/tests/test_tabbox_clientmodel.h +++ b/tabbox/tests/test_tabbox_clientmodel.h @@ -33,6 +33,13 @@ private slots: * See bug #303840 **/ 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