diff --git a/tabbox/clientmodel.cpp b/tabbox/clientmodel.cpp index 9591babaa8..a67d979bde 100644 --- a/tabbox/clientmodel.cpp +++ b/tabbox/clientmodel.cpp @@ -188,7 +188,7 @@ void ClientModel::createClientList(int desktop, bool partialReset) switch(tabBox->config().clientSwitchingMode()) { case TabBoxConfig::FocusChainSwitching: { TabBoxClient* c = start; - if (!c) { + if (!tabBox->isInFocusChain(c)) { QSharedPointer firstClient = tabBox->firstClientFocusChain().toStrongRef(); if (firstClient) { c = firstClient.data(); diff --git a/tabbox/tabbox.cpp b/tabbox/tabbox.cpp index d96d0bdace..7a08d375b9 100644 --- a/tabbox/tabbox.cpp +++ b/tabbox/tabbox.cpp @@ -112,6 +112,14 @@ QWeakPointer< TabBoxClient > TabBoxHandlerImpl::firstClientFocusChain() const } } +bool TabBoxHandlerImpl::isInFocusChain(TabBoxClient *client) const +{ + if (TabBoxClientImpl *c = static_cast(client)) { + return Workspace::self()->globalFocusChain().contains(c->client()); + } + return false; +} + int TabBoxHandlerImpl::nextDesktopFocusChain(int desktop) const { return m_tabBox->nextDesktopFocusChain(desktop); diff --git a/tabbox/tabbox.h b/tabbox/tabbox.h index 6652f93d05..bba0b39b7e 100644 --- a/tabbox/tabbox.h +++ b/tabbox/tabbox.h @@ -52,6 +52,7 @@ public: virtual QString desktopName(int desktop) const; virtual QWeakPointer< TabBoxClient > nextClientFocusChain(TabBoxClient* client) const; virtual QWeakPointer< TabBoxClient > firstClientFocusChain() const; + virtual bool isInFocusChain (TabBoxClient* client) const; virtual int nextDesktopFocusChain(int desktop) const; virtual int numberOfDesktops() const; virtual TabBoxClientList stackingOrder() const; diff --git a/tabbox/tabboxhandler.h b/tabbox/tabboxhandler.h index 7abddfcd0e..2af65b2930 100644 --- a/tabbox/tabboxhandler.h +++ b/tabbox/tabboxhandler.h @@ -119,6 +119,20 @@ public: * @since 4.9.1 **/ virtual QWeakPointer firstClientFocusChain() const = 0; + /** + * Checks whether the given @p client is part of the focus chain at all. + * This is useful to figure out whether the currently active Client can be used + * as a starting point to construct the recently used list. + * + * In case the @p client is not in the focus chain it is recommended to use the + * Client returned by @link firstClientFocusChain. + * + * The method accepts a @c null Client and in that case @c false is returned. + * @param client The Client to check whether it is in the Focus Chain + * @return @c true in case the Client is part of the focus chain, @c false otherwise. + * @since 4.9.2 + **/ + virtual bool isInFocusChain(TabBoxClient* client) 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 c3ad7a9a46..20fe8e89fc 100644 --- a/tabbox/tests/mock_tabboxhandler.cpp +++ b/tabbox/tests/mock_tabboxhandler.cpp @@ -72,6 +72,9 @@ QWeakPointer< TabBox::TabBoxClient > MockTabBoxHandler::nextClientFocusChain(Tab } } } + if (!m_windows.isEmpty()) { + return QWeakPointer< TabBox::TabBoxClient >(m_windows.last()); + } return QWeakPointer< TabBox::TabBoxClient >(); } @@ -83,6 +86,20 @@ QWeakPointer< TabBox::TabBoxClient > MockTabBoxHandler::firstClientFocusChain() return m_windows.first(); } +bool MockTabBoxHandler::isInFocusChain(TabBox::TabBoxClient *client) const +{ + if (!client) { + return false; + } + QList< QSharedPointer< TabBox::TabBoxClient > >::const_iterator it = m_windows.constBegin(); + for (; it != m_windows.constEnd(); ++it) { + if ((*it).data() == client) { + return true; + } + } + return false; +} + QWeakPointer< TabBox::TabBoxClient > MockTabBoxHandler::createMockWindow(const QString &caption, WId id) { QSharedPointer< TabBox::TabBoxClient > client(new MockTabBoxClient(caption, id)); diff --git a/tabbox/tests/mock_tabboxhandler.h b/tabbox/tests/mock_tabboxhandler.h index a2236486cb..5578001a01 100644 --- a/tabbox/tests/mock_tabboxhandler.h +++ b/tabbox/tests/mock_tabboxhandler.h @@ -60,6 +60,7 @@ public: } virtual QWeakPointer< TabBox::TabBoxClient > nextClientFocusChain(TabBox::TabBoxClient *client) const; virtual QWeakPointer firstClientFocusChain() const; + virtual bool isInFocusChain (TabBox::TabBoxClient* client) const; virtual int nextDesktopFocusChain(int desktop) const { Q_UNUSED(desktop) return 1; diff --git a/tabbox/tests/test_tabbox_clientmodel.cpp b/tabbox/tests/test_tabbox_clientmodel.cpp index 79d02534e4..cee9860d08 100644 --- a/tabbox/tests/test_tabbox_clientmodel.cpp +++ b/tabbox/tests/test_tabbox_clientmodel.cpp @@ -63,4 +63,24 @@ void TestTabBoxClientModel::testCreateClientListNoActiveClient() QCOMPARE(clientModel->rowCount(), 2); } +void TestTabBoxClientModel::testCreateClientListActiveClientNotInFocusChain() +{ + MockTabBoxHandler tabboxhandler; + tabboxhandler.setConfig(TabBox::TabBoxConfig()); + TabBox::ClientModel *clientModel = new TabBox::ClientModel(&tabboxhandler); + // create two windows, rowCount() should go to two + QWeakPointer client = tabboxhandler.createMockWindow(QString("test"), 1); + client = tabboxhandler.createMockWindow(QString("test2"), 2); + clientModel->createClientList(); + QCOMPARE(clientModel->rowCount(), 2); + + // simulate that the active client is not in the focus chain + // for that we use the closeWindow of the MockTabBoxHandler which + // removes the Client from the Focus Chain but leaves the active window as it is + QSharedPointer clientOwner = client.toStrongRef(); + tabboxhandler.closeWindow(client.data()); + clientModel->createClientList(); + QCOMPARE(clientModel->rowCount(), 1); +} + QTEST_MAIN(TestTabBoxClientModel) diff --git a/tabbox/tests/test_tabbox_clientmodel.h b/tabbox/tests/test_tabbox_clientmodel.h index 2ec6608a34..fad79874fe 100644 --- a/tabbox/tests/test_tabbox_clientmodel.h +++ b/tabbox/tests/test_tabbox_clientmodel.h @@ -40,6 +40,13 @@ private slots: * See BUG: 305449 **/ void testCreateClientListNoActiveClient(); + /** + * Tests the creation of the Client list for the case that + * the active Client is not in the Focus chain. + * + * See BUG: 306260 + **/ + void testCreateClientListActiveClientNotInFocusChain(); }; #endif