tabbox: Drop TabBoxClient

The indirection contributes unnecessary complexity. The usage of
std::weak_ptr and std::shared_ptr complicates the things further, e.g.

![Screenshot_20230325_170226](/uploads/d8b68a9eff47c93c4463bb230b5bbe49/Screenshot_20230325_170226.png)

---

Ideally, same should be done with TabBox and TabBoxHandler, but that can be done in another MR.
This commit is contained in:
Vlad Zahorodnii 2023-03-25 20:46:54 +00:00
parent fc890340d9
commit c5eabfa4d1
19 changed files with 217 additions and 1062 deletions

View file

@ -3,7 +3,6 @@ remove_definitions(-DQT_USE_QSTRINGBUILDER)
add_subdirectory(libkwineffects)
add_subdirectory(integration)
add_subdirectory(libinput)
add_subdirectory(tabbox)
add_subdirectory(drm)
########################################################

View file

@ -1,80 +0,0 @@
add_definitions(-DKWIN_UNIT_TEST)
########################################################
# Test TabBox::ClientModel
########################################################
set(testTabBoxClientModel_SRCS
../../src/tabbox/clientmodel.cpp
../../src/tabbox/tabbox_logging.cpp
../../src/tabbox/tabboxconfig.cpp
../../src/tabbox/tabboxhandler.cpp
mock_tabboxclient.cpp
mock_tabboxhandler.cpp
test_tabbox_clientmodel.cpp
)
add_executable(testTabBoxClientModel ${testTabBoxClientModel_SRCS})
set_target_properties(testTabBoxClientModel PROPERTIES COMPILE_DEFINITIONS "NO_NONE_WINDOW")
target_link_libraries(testTabBoxClientModel
Qt::Core
Qt::DBus
Qt::Quick
Qt::Test
Qt::Widgets
Qt::GuiPrivate
KF6::ConfigCore
KF6::I18n
KF6::Package
KF6::WindowSystem
XCB::XCB
)
add_test(NAME kwin-testTabBoxClientModel COMMAND testTabBoxClientModel)
ecm_mark_as_test(testTabBoxClientModel)
########################################################
# Test TabBox::TabBoxHandler
########################################################
set(testTabBoxHandler_SRCS
../../src/tabbox/clientmodel.cpp
../../src/tabbox/tabbox_logging.cpp
../../src/tabbox/tabboxconfig.cpp
../../src/tabbox/tabboxhandler.cpp
mock_tabboxclient.cpp
mock_tabboxhandler.cpp
test_tabbox_handler.cpp
)
add_executable(testTabBoxHandler ${testTabBoxHandler_SRCS})
set_target_properties(testTabBoxHandler PROPERTIES COMPILE_DEFINITIONS "NO_NONE_WINDOW")
target_link_libraries(testTabBoxHandler
Qt::Core
Qt::DBus
Qt::Quick
Qt::Test
Qt::Widgets
Qt::GuiPrivate
KF6::ConfigCore
KF6::I18n
KF6::Package
KF6::WindowSystem
XCB::XCB
)
add_test(NAME kwin-testTabBoxHandler COMMAND testTabBoxHandler)
ecm_mark_as_test(testTabBoxHandler)
########################################################
# Test TabBox::TabBoxConfig
########################################################
set(testTabBoxConfig_SRCS
../../src/tabbox/tabbox_logging.cpp
../../src/tabbox/tabboxconfig.cpp
test_tabbox_config.cpp
)
add_executable(testTabBoxConfig ${testTabBoxConfig_SRCS})
target_link_libraries(testTabBoxConfig Qt::Core Qt::Test)
add_test(NAME kwin-testTabBoxConfig COMMAND testTabBoxConfig)
ecm_mark_as_test(testTabBoxConfig)

View file

@ -1,26 +0,0 @@
/*
KWin - the KDE window manager
This file is part of the KDE project.
SPDX-FileCopyrightText: 2012 Martin Gräßlin <mgraesslin@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "mock_tabboxclient.h"
#include "mock_tabboxhandler.h"
namespace KWin
{
MockTabBoxClient::MockTabBoxClient(QString caption)
: TabBoxClient()
, m_caption(caption)
{
}
void MockTabBoxClient::close()
{
static_cast<MockTabBoxHandler *>(TabBox::tabBox)->closeWindow(this);
}
} // namespace KWin

View file

@ -1,70 +0,0 @@
/*
KWin - the KDE window manager
This file is part of the KDE project.
SPDX-FileCopyrightText: 2012 Martin Gräßlin <mgraesslin@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef KWIN_MOCK_TABBOX_CLIENT_H
#define KWIN_MOCK_TABBOX_CLIENT_H
#include "tabbox/tabboxhandler.h"
#include <QIcon>
#include <QUuid>
namespace KWin
{
class MockTabBoxClient : public TabBox::TabBoxClient
{
public:
explicit MockTabBoxClient(QString caption);
bool isMinimized() const override
{
return false;
}
QString caption() const override
{
return m_caption;
}
void close() override;
int height() const override
{
return 100;
}
virtual QPixmap icon(const QSize &size = QSize(32, 32)) const
{
return QPixmap(size);
}
bool isCloseable() const override
{
return true;
}
int width() const override
{
return 100;
}
int x() const override
{
return 0;
}
int y() const override
{
return 0;
}
QIcon icon() const override
{
return QIcon();
}
QUuid internalId() const override
{
return QUuid{};
}
private:
QString m_caption;
};
} // namespace KWin
#endif

View file

@ -1,109 +0,0 @@
/*
KWin - the KDE window manager
This file is part of the KDE project.
SPDX-FileCopyrightText: 2012 Martin Gräßlin <mgraesslin@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "mock_tabboxhandler.h"
#include "mock_tabboxclient.h"
namespace KWin
{
MockTabBoxHandler::MockTabBoxHandler(QObject *parent)
: TabBoxHandler(parent)
{
}
MockTabBoxHandler::~MockTabBoxHandler()
{
}
void MockTabBoxHandler::grabbedKeyEvent(QKeyEvent *event) const
{
}
std::weak_ptr<TabBox::TabBoxClient> MockTabBoxHandler::activeClient() const
{
return m_activeClient;
}
void MockTabBoxHandler::setActiveClient(const std::weak_ptr<TabBox::TabBoxClient> &client)
{
m_activeClient = client;
}
std::weak_ptr<TabBox::TabBoxClient> MockTabBoxHandler::clientToAddToList(TabBox::TabBoxClient *client, int desktop) const
{
QList<std::shared_ptr<TabBox::TabBoxClient>>::const_iterator it = m_windows.constBegin();
for (; it != m_windows.constEnd(); ++it) {
if ((*it).get() == client) {
return std::weak_ptr<TabBox::TabBoxClient>(*it);
}
}
return std::weak_ptr<TabBox::TabBoxClient>();
}
std::weak_ptr<TabBox::TabBoxClient> MockTabBoxHandler::nextClientFocusChain(TabBox::TabBoxClient *client) const
{
QList<std::shared_ptr<TabBox::TabBoxClient>>::const_iterator it = m_windows.constBegin();
for (; it != m_windows.constEnd(); ++it) {
if ((*it).get() == client) {
++it;
if (it == m_windows.constEnd()) {
return std::weak_ptr<TabBox::TabBoxClient>(m_windows.first());
} else {
return std::weak_ptr<TabBox::TabBoxClient>(*it);
}
}
}
if (!m_windows.isEmpty()) {
return std::weak_ptr<TabBox::TabBoxClient>(m_windows.last());
}
return std::weak_ptr<TabBox::TabBoxClient>();
}
std::weak_ptr<TabBox::TabBoxClient> MockTabBoxHandler::firstClientFocusChain() const
{
if (m_windows.isEmpty()) {
return std::weak_ptr<TabBox::TabBoxClient>();
}
return m_windows.first();
}
bool MockTabBoxHandler::isInFocusChain(TabBox::TabBoxClient *client) const
{
if (!client) {
return false;
}
QList<std::shared_ptr<TabBox::TabBoxClient>>::const_iterator it = m_windows.constBegin();
for (; it != m_windows.constEnd(); ++it) {
if ((*it).get() == client) {
return true;
}
}
return false;
}
std::weak_ptr<TabBox::TabBoxClient> MockTabBoxHandler::createMockWindow(const QString &caption)
{
std::shared_ptr<TabBox::TabBoxClient> client(new MockTabBoxClient(caption));
m_windows.append(client);
m_activeClient = client;
return std::weak_ptr<TabBox::TabBoxClient>(client);
}
void MockTabBoxHandler::closeWindow(TabBox::TabBoxClient *client)
{
QList<std::shared_ptr<TabBox::TabBoxClient>>::iterator it = m_windows.begin();
for (; it != m_windows.end(); ++it) {
if ((*it).get() == client) {
m_windows.erase(it);
return;
}
}
}
} // namespace KWin

View file

@ -1,92 +0,0 @@
/*
KWin - the KDE window manager
This file is part of the KDE project.
SPDX-FileCopyrightText: 2012 Martin Gräßlin <mgraesslin@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef KWIN_MOCK_TABBOX_HANDLER_H
#define KWIN_MOCK_TABBOX_HANDLER_H
#include "tabbox/tabboxhandler.h"
namespace KWin
{
class MockTabBoxHandler : public TabBox::TabBoxHandler
{
Q_OBJECT
public:
MockTabBoxHandler(QObject *parent = nullptr);
~MockTabBoxHandler() override;
void activateAndClose() override
{
}
std::weak_ptr<TabBox::TabBoxClient> activeClient() const override;
void setActiveClient(const std::weak_ptr<TabBox::TabBoxClient> &client);
int activeScreen() const override
{
return 0;
}
std::weak_ptr<TabBox::TabBoxClient> clientToAddToList(TabBox::TabBoxClient *client, int desktop) const override;
int currentDesktop() const override
{
return 1;
}
std::weak_ptr<TabBox::TabBoxClient> desktopClient() const override
{
return std::weak_ptr<TabBox::TabBoxClient>();
}
QString desktopName(TabBox::TabBoxClient *client) const override
{
return "desktop";
}
void elevateClient(TabBox::TabBoxClient *c, QWindow *tabbox, bool elevate) const override
{
}
void shadeClient(TabBox::TabBoxClient *c, bool b) const override
{
}
virtual void hideOutline()
{
}
std::weak_ptr<TabBox::TabBoxClient> nextClientFocusChain(TabBox::TabBoxClient *client) const override;
std::weak_ptr<TabBox::TabBoxClient> firstClientFocusChain() const override;
bool isInFocusChain(TabBox::TabBoxClient *client) const override;
bool isKWinCompositing() const override
{
return false;
}
void raiseClient(TabBox::TabBoxClient *c) const override
{
}
void restack(TabBox::TabBoxClient *c, TabBox::TabBoxClient *under) override
{
}
virtual void showOutline(const QRect &outline)
{
}
TabBox::TabBoxClientList stackingOrder() const override
{
return TabBox::TabBoxClientList();
}
void grabbedKeyEvent(QKeyEvent *event) const override;
void highlightWindows(TabBox::TabBoxClient *window = nullptr, QWindow *controller = nullptr) override
{
}
bool noModifierGrab() const override
{
return false;
}
// mock methods
std::weak_ptr<TabBox::TabBoxClient> createMockWindow(const QString &caption);
void closeWindow(TabBox::TabBoxClient *client);
private:
QList<std::shared_ptr<TabBox::TabBoxClient>> m_windows;
std::weak_ptr<TabBox::TabBoxClient> m_activeClient;
};
} // namespace KWin
#endif

View file

@ -1,84 +0,0 @@
/*
KWin - the KDE window manager
This file is part of the KDE project.
SPDX-FileCopyrightText: 2012 Martin Gräßlin <mgraesslin@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "test_tabbox_clientmodel.h"
#include "../testutils.h"
#include "mock_tabboxhandler.h"
#include "tabbox/clientmodel.h"
#include <QtTest>
#include <private/qtx11extras_p.h>
using namespace KWin;
void TestTabBoxClientModel::initTestCase()
{
qApp->setProperty("x11Connection", QVariant::fromValue<void *>(QX11Info::connection()));
}
void TestTabBoxClientModel::testLongestCaptionWithNullClient()
{
MockTabBoxHandler tabboxhandler;
TabBox::ClientModel *clientModel = new TabBox::ClientModel(&tabboxhandler);
clientModel->createClientList();
QCOMPARE(clientModel->longestCaption(), QString());
// add a window to the mock
tabboxhandler.createMockWindow(QString("test"));
clientModel->createClientList();
QCOMPARE(clientModel->longestCaption(), QString("test"));
// delete the one client in the list
QModelIndex index = clientModel->index(0, 0);
QVERIFY(index.isValid());
TabBox::TabBoxClient *client = static_cast<TabBox::TabBoxClient *>(clientModel->data(index, TabBox::ClientModel::ClientRole).value<void *>());
client->close();
// internal model of ClientModel now contains a deleted pointer
// longestCaption should behave just as if the window were not in the list
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
std::weak_ptr<TabBox::TabBoxClient> client = tabboxhandler.createMockWindow(QString("test"));
tabboxhandler.createMockWindow(QString("test2"));
clientModel->createClientList();
QCOMPARE(clientModel->rowCount(), 2);
// let's ensure there is no active client
tabboxhandler.setActiveClient(std::weak_ptr<TabBox::TabBoxClient>());
// now it should still have two members in the list
clientModel->createClientList();
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
std::weak_ptr<TabBox::TabBoxClient> client = tabboxhandler.createMockWindow(QString("test"));
client = tabboxhandler.createMockWindow(QString("test2"));
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
std::shared_ptr<TabBox::TabBoxClient> clientOwner = client.lock();
tabboxhandler.closeWindow(clientOwner.get());
clientModel->createClientList();
QCOMPARE(clientModel->rowCount(), 1);
}
Q_CONSTRUCTOR_FUNCTION(forceXcb)
QTEST_MAIN(TestTabBoxClientModel)

View file

@ -1,42 +0,0 @@
/*
KWin - the KDE window manager
This file is part of the KDE project.
SPDX-FileCopyrightText: 2012 Martin Gräßlin <mgraesslin@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef TEST_TABBOX_CLIENT_MODEL_H
#define TEST_TABBOX_CLIENT_MODEL_H
#include <QObject>
class TestTabBoxClientModel : public QObject
{
Q_OBJECT
private Q_SLOTS:
void initTestCase();
/**
* Tests that calculating the longest caption does not
* crash in case the internal m_clientList contains a weak
* pointer to a deleted TabBoxClient.
*
* 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();
/**
* 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

View file

@ -1,71 +0,0 @@
/*
KWin - the KDE window manager
This file is part of the KDE project.
SPDX-FileCopyrightText: 2012 Martin Gräßlin <mgraesslin@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "tabbox/tabboxconfig.h"
#include <QtTest>
using namespace KWin;
using namespace KWin::TabBox;
class TestTabBoxConfig : public QObject
{
Q_OBJECT
private Q_SLOTS:
void testDefaultCtor();
void testAssignmentOperator();
};
void TestTabBoxConfig::testDefaultCtor()
{
TabBoxConfig config;
QCOMPARE(config.isShowTabBox(), TabBoxConfig::defaultShowTabBox());
QCOMPARE(config.isHighlightWindows(), TabBoxConfig::defaultHighlightWindow());
QCOMPARE(config.clientDesktopMode(), TabBoxConfig::defaultDesktopMode());
QCOMPARE(config.clientActivitiesMode(), TabBoxConfig::defaultActivitiesMode());
QCOMPARE(config.clientApplicationsMode(), TabBoxConfig::defaultApplicationsMode());
QCOMPARE(config.orderMinimizedMode(), TabBoxConfig::defaultOrderMinimizedMode());
QCOMPARE(config.clientMinimizedMode(), TabBoxConfig::defaultMinimizedMode());
QCOMPARE(config.showDesktopMode(), TabBoxConfig::defaultShowDesktopMode());
QCOMPARE(config.clientMultiScreenMode(), TabBoxConfig::defaultMultiScreenMode());
QCOMPARE(config.clientSwitchingMode(), TabBoxConfig::defaultSwitchingMode());
QCOMPARE(config.layoutName(), TabBoxConfig::defaultLayoutName());
}
void TestTabBoxConfig::testAssignmentOperator()
{
TabBoxConfig config;
// changing all values of the config object
config.setShowTabBox(!TabBoxConfig::defaultShowTabBox());
config.setHighlightWindows(!TabBoxConfig::defaultHighlightWindow());
config.setClientDesktopMode(TabBoxConfig::AllDesktopsClients);
config.setClientActivitiesMode(TabBoxConfig::AllActivitiesClients);
config.setClientApplicationsMode(TabBoxConfig::OneWindowPerApplication);
config.setOrderMinimizedMode(TabBoxConfig::GroupByMinimized);
config.setClientMinimizedMode(TabBoxConfig::ExcludeMinimizedClients);
config.setShowDesktopMode(TabBoxConfig::ShowDesktopClient);
config.setClientMultiScreenMode(TabBoxConfig::ExcludeCurrentScreenClients);
config.setClientSwitchingMode(TabBoxConfig::StackingOrderSwitching);
config.setLayoutName(QStringLiteral("grid"));
TabBoxConfig config2;
config2 = config;
// verify the config2 values
QCOMPARE(config2.isShowTabBox(), !TabBoxConfig::defaultShowTabBox());
QCOMPARE(config2.isHighlightWindows(), !TabBoxConfig::defaultHighlightWindow());
QCOMPARE(config2.clientDesktopMode(), TabBoxConfig::AllDesktopsClients);
QCOMPARE(config2.clientActivitiesMode(), TabBoxConfig::AllActivitiesClients);
QCOMPARE(config2.clientApplicationsMode(), TabBoxConfig::OneWindowPerApplication);
QCOMPARE(config2.orderMinimizedMode(), TabBoxConfig::GroupByMinimized);
QCOMPARE(config2.clientMinimizedMode(), TabBoxConfig::ExcludeMinimizedClients);
QCOMPARE(config2.showDesktopMode(), TabBoxConfig::ShowDesktopClient);
QCOMPARE(config2.clientMultiScreenMode(), TabBoxConfig::ExcludeCurrentScreenClients);
QCOMPARE(config2.clientSwitchingMode(), TabBoxConfig::StackingOrderSwitching);
QCOMPARE(config2.layoutName(), QStringLiteral("grid"));
}
QTEST_MAIN(TestTabBoxConfig)
#include "test_tabbox_config.moc"

View file

@ -1,51 +0,0 @@
/*
KWin - the KDE window manager
This file is part of the KDE project.
SPDX-FileCopyrightText: 2012 Martin Gräßlin <mgraesslin@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "../testutils.h"
#include "mock_tabboxhandler.h"
#include "tabbox/clientmodel.h"
#include <QtTest>
#include <private/qtx11extras_p.h>
using namespace KWin;
class TestTabBoxHandler : public QObject
{
Q_OBJECT
private Q_SLOTS:
void initTestCase();
/**
* Test to verify that update outline does not crash
* if the ModelIndex for which the outline should be
* shown is not valid. That is accessing the Pointer
* to the Client returns an invalid QVariant.
* BUG: 304620
*/
void testDontCrashUpdateOutlineNullClient();
};
void TestTabBoxHandler::initTestCase()
{
qApp->setProperty("x11Connection", QVariant::fromValue<void *>(QX11Info::connection()));
}
void TestTabBoxHandler::testDontCrashUpdateOutlineNullClient()
{
MockTabBoxHandler tabboxhandler;
TabBox::TabBoxConfig config;
config.setShowTabBox(false);
config.setHighlightWindows(false);
tabboxhandler.setConfig(config);
// now show the tabbox which will attempt to show the outline
tabboxhandler.show();
}
Q_CONSTRUCTOR_FUNCTION(forceXcb)
QTEST_MAIN(TestTabBoxHandler)
#include "test_tabbox_handler.moc"

View file

@ -7,16 +7,16 @@
SPDX-License-Identifier: GPL-2.0-or-later
*/
// own
#include "clientmodel.h"
// tabbox
#include "tabboxconfig.h"
// Qt
#include "window.h"
#include <KLocalizedString>
#include <QIcon>
#include <QTextDocument> // TODO: remove with Qt 5, only for HTML escaping the caption
#include <QUuid>
// TODO: remove with Qt 5, only for HTML escaping the caption
#include <QTextDocument>
// other
#include <cmath>
namespace KWin
@ -47,13 +47,17 @@ QVariant ClientModel::data(const QModelIndex &index, int role) const
if (clientIndex >= m_clientList.count()) {
return QVariant();
}
std::shared_ptr<TabBoxClient> client = m_clientList[clientIndex].lock();
Window *client = m_clientList[clientIndex];
if (!client) {
return QVariant();
}
switch (role) {
case Qt::DisplayRole:
case CaptionRole: {
if (client->isDesktop()) {
return i18nc("Special entry in alt+tab list for minimizing all windows",
"Show Desktop");
}
QString caption = client->caption();
if (Qt::mightBeRichText(caption)) {
caption = caption.toHtmlEscaped();
@ -61,9 +65,9 @@ QVariant ClientModel::data(const QModelIndex &index, int role) const
return caption;
}
case ClientRole:
return QVariant::fromValue<void *>(client.get());
return QVariant::fromValue<void *>(client);
case DesktopNameRole: {
return tabBox->desktopName(client.get());
return tabBox->desktopName(client);
}
case WIdRole:
return client->internalId();
@ -72,6 +76,9 @@ QVariant ClientModel::data(const QModelIndex &index, int role) const
case CloseableRole:
return client->isCloseable();
case IconRole:
if (client->isDesktop()) {
return QIcon::fromTheme(QStringLiteral("user-desktop"));
}
return client->icon();
default:
return QVariant();
@ -81,13 +88,9 @@ QVariant ClientModel::data(const QModelIndex &index, int role) const
QString ClientModel::longestCaption() const
{
QString caption;
for (const std::weak_ptr<TabBoxClient> &clientPointer : std::as_const(m_clientList)) {
std::shared_ptr<TabBoxClient> client = clientPointer.lock();
if (!client) {
continue;
}
if (client->caption().size() > caption.size()) {
caption = client->caption();
for (Window *window : std::as_const(m_clientList)) {
if (window->caption().size() > caption.size()) {
caption = window->caption();
}
}
return caption;
@ -135,15 +138,12 @@ QHash<int, QByteArray> ClientModel::roleNames() const
};
}
QModelIndex ClientModel::index(std::weak_ptr<TabBoxClient> client) const
QModelIndex ClientModel::index(Window *client) const
{
const auto it = std::find_if(m_clientList.cbegin(), m_clientList.cend(), [c = client.lock()](auto &client) {
return client.lock() == c;
});
if (it == m_clientList.cend()) {
const int index = m_clientList.indexOf(client);
if (index == -1) {
return QModelIndex();
}
int index = std::distance(m_clientList.cbegin(), it);
int row = index / columnCount();
int column = index % columnCount();
return createIndex(row, column);
@ -154,40 +154,37 @@ void ClientModel::createClientList(bool partialReset)
createClientList(tabBox->currentDesktop(), partialReset);
}
void ClientModel::createFocusChainClientList(int desktop, const std::shared_ptr<TabBoxClient> &start)
void ClientModel::createFocusChainClientList(int desktop, Window *start)
{
auto c = start;
if (!tabBox->isInFocusChain(c.get())) {
std::shared_ptr<TabBoxClient> firstClient = tabBox->firstClientFocusChain().lock();
if (!tabBox->isInFocusChain(c)) {
Window *firstClient = tabBox->firstClientFocusChain();
if (firstClient) {
c = firstClient;
}
}
auto stop = c;
do {
std::shared_ptr<TabBoxClient> add = tabBox->clientToAddToList(c.get(), desktop).lock();
Window *add = tabBox->clientToAddToList(c, desktop);
if (add) {
m_mutableClientList += add;
}
c = tabBox->nextClientFocusChain(c.get()).lock();
c = tabBox->nextClientFocusChain(c);
} while (c && c != stop);
}
void ClientModel::createStackingOrderClientList(int desktop, const std::shared_ptr<TabBoxClient> &start)
void ClientModel::createStackingOrderClientList(int desktop, Window *start)
{
// TODO: needs improvement
const TabBoxClientList stacking = tabBox->stackingOrder();
auto c = stacking.first().lock();
const QList<Window *> stacking = tabBox->stackingOrder();
auto c = stacking.first();
auto stop = c;
int index = 0;
while (c) {
std::shared_ptr<TabBoxClient> add = tabBox->clientToAddToList(c.get(), desktop).lock();
Window *add = tabBox->clientToAddToList(c, desktop);
if (add) {
if (start == add) {
m_mutableClientList.erase(std::remove_if(m_mutableClientList.begin(), m_mutableClientList.end(), [&add](auto &client) {
return client.lock() == add;
}),
m_mutableClientList.end());
m_mutableClientList.removeAll(add);
m_mutableClientList.prepend(add);
} else {
m_mutableClientList += add;
@ -196,7 +193,7 @@ void ClientModel::createStackingOrderClientList(int desktop, const std::shared_p
if (index >= stacking.size() - 1) {
c = nullptr;
} else {
c = stacking[++index].lock();
c = stacking[++index];
}
if (c == stop) {
@ -207,10 +204,10 @@ void ClientModel::createStackingOrderClientList(int desktop, const std::shared_p
void ClientModel::createClientList(int desktop, bool partialReset)
{
auto start = tabBox->activeClient().lock();
auto start = tabBox->activeClient();
// TODO: new clients are not added at correct position
if (partialReset && !m_mutableClientList.isEmpty()) {
std::shared_ptr<TabBoxClient> firstClient = m_mutableClientList.constFirst().lock();
Window *firstClient = m_mutableClientList.constFirst();
if (firstClient) {
start = firstClient;
}
@ -232,23 +229,19 @@ void ClientModel::createClientList(int desktop, bool partialReset)
if (tabBox->config().orderMinimizedMode() == TabBoxConfig::GroupByMinimized) {
// Put all non-minimized included clients first.
std::stable_partition(m_mutableClientList.begin(), m_mutableClientList.end(), [](const auto &client) {
return !client.lock()->isMinimized();
return !client->isMinimized();
});
}
if (tabBox->config().clientApplicationsMode() != TabBoxConfig::AllWindowsCurrentApplication
&& (tabBox->config().showDesktopMode() == TabBoxConfig::ShowDesktopClient || m_mutableClientList.isEmpty())) {
std::weak_ptr<TabBoxClient> desktopClient = tabBox->desktopClient();
if (!desktopClient.expired()) {
Window *desktopClient = tabBox->desktopClient();
if (desktopClient) {
m_mutableClientList.append(desktopClient);
}
}
bool equal = m_clientList.size() == m_mutableClientList.size();
for (int i = 0; i < m_clientList.size() && equal; i++) {
equal &= m_clientList[i].lock() == m_mutableClientList[i].lock();
}
if (equal) {
if (m_clientList == m_mutableClientList) {
return;
}
@ -263,9 +256,9 @@ void ClientModel::close(int i)
if (!ind.isValid()) {
return;
}
std::shared_ptr<TabBoxClient> client = m_mutableClientList.at(i).lock();
Window *client = m_mutableClientList.at(i);
if (client) {
client->close();
client->closeWindow();
}
}

View file

@ -13,7 +13,7 @@
#include <QModelIndex>
/**
* @file
* This file defines the class ClientModel, the model for TabBoxClients.
* This file defines the class ClientModel, the model for Windows.
*
* @author Martin Gräßlin <mgraesslin@kde.org>
* @since 4.4
@ -25,7 +25,7 @@ namespace TabBox
{
/**
* The model for TabBoxClients used in TabBox.
* The model for Windows used in TabBox.
*
* @author Martin Gräßlin <mgraesslin@kde.org>
* @since 4.4
@ -36,13 +36,13 @@ class ClientModel
Q_OBJECT
public:
enum {
ClientRole = Qt::UserRole, ///< The TabBoxClient
CaptionRole = Qt::UserRole + 1, ///< The caption of TabBoxClient
DesktopNameRole = Qt::UserRole + 2, ///< The name of the desktop the TabBoxClient is on
ClientRole = Qt::UserRole, ///< The Window
CaptionRole = Qt::UserRole + 1, ///< The caption of Window
DesktopNameRole = Qt::UserRole + 2, ///< The name of the desktop the Window is on
IconRole = Qt::UserRole + 3, // TODO: to be removed
WIdRole = Qt::UserRole + 5, ///< The window ID of TabBoxClient
MinimizedRole = Qt::UserRole + 6, ///< TabBoxClient is minimized
CloseableRole = Qt::UserRole + 7 ///< TabBoxClient can be closed
WIdRole = Qt::UserRole + 5, ///< The window ID of Window
MinimizedRole = Qt::UserRole + 6, ///< Window is minimized
CloseableRole = Qt::UserRole + 7 ///< Window can be closed
};
explicit ClientModel(QObject *parent = nullptr);
~ClientModel() override;
@ -55,14 +55,14 @@ public:
Q_INVOKABLE QString longestCaption() const;
/**
* @param client The TabBoxClient whose index should be returned
* @return Returns the ModelIndex of given TabBoxClient or an invalid ModelIndex
* if the model does not contain the given TabBoxClient.
* @param client The Window whose index should be returned
* @return Returns the ModelIndex of given Window or an invalid ModelIndex
* if the model does not contain the given Window.
*/
QModelIndex index(std::weak_ptr<TabBoxClient> client) const;
QModelIndex index(Window *client) const;
/**
* Generates a new list of TabBoxClients based on the current config.
* Generates a new list of Windows based on the current config.
* Calling this method will reset the model. If partialReset is true
* the top of the list is kept as a starting point. If not the
* current active client is used as the starting point to generate the
@ -77,9 +77,9 @@ public:
*/
void createClientList(bool partialReset = false);
/**
* @return Returns the current list of TabBoxClients.
* @return Returns the current list of Windows.
*/
TabBoxClientList clientList() const
QList<Window *> clientList() const
{
return m_mutableClientList;
}
@ -93,11 +93,11 @@ public Q_SLOTS:
void activate(int index);
private:
void createFocusChainClientList(int desktop, const std::shared_ptr<TabBoxClient> &start);
void createStackingOrderClientList(int desktop, const std::shared_ptr<TabBoxClient> &start);
void createFocusChainClientList(int desktop, Window *start);
void createStackingOrderClientList(int desktop, Window *start);
TabBoxClientList m_clientList;
TabBoxClientList m_mutableClientList;
QList<Window *> m_clientList;
QList<Window *> m_mutableClientList;
};
} // namespace Tabbox

View file

@ -77,106 +77,81 @@ int TabBoxHandlerImpl::currentDesktop() const
return VirtualDesktopManager::self()->current();
}
QString TabBoxHandlerImpl::desktopName(TabBoxClient *client) const
QString TabBoxHandlerImpl::desktopName(Window *client) const
{
if (TabBoxClientImpl *c = static_cast<TabBoxClientImpl *>(client)) {
if (!c->client()->isOnAllDesktops()) {
return VirtualDesktopManager::self()->desktopForX11Id(c->client()->desktop())->name();
}
if (!client->isOnAllDesktops()) {
return client->desktops().last()->name();
}
return VirtualDesktopManager::self()->currentDesktop()->name();
}
std::weak_ptr<TabBoxClient> TabBoxHandlerImpl::nextClientFocusChain(TabBoxClient *client) const
Window *TabBoxHandlerImpl::nextClientFocusChain(Window *client) const
{
if (TabBoxClientImpl *c = static_cast<TabBoxClientImpl *>(client)) {
auto next = Workspace::self()->focusChain()->nextMostRecentlyUsed(c->client());
if (next) {
return std::static_pointer_cast<TabBoxClientImpl>(next->tabBoxClient().lock());
}
}
return std::weak_ptr<TabBoxClient>();
return Workspace::self()->focusChain()->nextMostRecentlyUsed(client);
}
std::weak_ptr<TabBoxClient> TabBoxHandlerImpl::firstClientFocusChain() const
Window *TabBoxHandlerImpl::firstClientFocusChain() const
{
if (auto c = Workspace::self()->focusChain()->firstMostRecentlyUsed()) {
return std::static_pointer_cast<TabBoxClientImpl>(c->tabBoxClient().lock());
} else {
return std::weak_ptr<TabBoxClient>();
}
return Workspace::self()->focusChain()->firstMostRecentlyUsed();
}
bool TabBoxHandlerImpl::isInFocusChain(TabBoxClient *client) const
bool TabBoxHandlerImpl::isInFocusChain(Window *client) const
{
if (TabBoxClientImpl *c = static_cast<TabBoxClientImpl *>(client)) {
return Workspace::self()->focusChain()->contains(c->client());
}
return false;
return Workspace::self()->focusChain()->contains(client);
}
std::weak_ptr<TabBoxClient> TabBoxHandlerImpl::activeClient() const
Window *TabBoxHandlerImpl::activeClient() const
{
if (Workspace::self()->activeWindow()) {
return std::static_pointer_cast<TabBoxClientImpl>(Workspace::self()->activeWindow()->tabBoxClient().lock());
} else {
return std::weak_ptr<TabBoxClient>();
}
return Workspace::self()->activeWindow();
}
bool TabBoxHandlerImpl::checkDesktop(TabBoxClient *client, int desktop) const
bool TabBoxHandlerImpl::checkDesktop(Window *client, int desktop) const
{
auto current = (static_cast<TabBoxClientImpl *>(client))->client();
switch (config().clientDesktopMode()) {
case TabBoxConfig::AllDesktopsClients:
return true;
case TabBoxConfig::ExcludeCurrentDesktopClients:
return !current->isOnDesktop(desktop);
return !client->isOnDesktop(desktop);
default: // TabBoxConfig::OnlyCurrentDesktopClients
return current->isOnDesktop(desktop);
return client->isOnDesktop(desktop);
}
}
bool TabBoxHandlerImpl::checkActivity(TabBoxClient *client) const
bool TabBoxHandlerImpl::checkActivity(Window *client) const
{
auto current = (static_cast<TabBoxClientImpl *>(client))->client();
switch (config().clientActivitiesMode()) {
case TabBoxConfig::AllActivitiesClients:
return true;
case TabBoxConfig::ExcludeCurrentActivityClients:
return !current->isOnCurrentActivity();
return !client->isOnCurrentActivity();
default: // TabBoxConfig::OnlyCurrentActivityClients
return current->isOnCurrentActivity();
return client->isOnCurrentActivity();
}
}
bool TabBoxHandlerImpl::checkApplications(TabBoxClient *client) const
bool TabBoxHandlerImpl::checkApplications(Window *client) const
{
const auto current = (static_cast<TabBoxClientImpl *>(client))->client();
const auto list = clientList();
switch (config().clientApplicationsMode()) {
case TabBoxConfig::OneWindowPerApplication:
// check if the list already contains an entry of this application
for (const auto &weakClient : list) {
const std::shared_ptr<TabBoxClientImpl> client = std::dynamic_pointer_cast<TabBoxClientImpl>(weakClient.lock());
if (client && Window::belongToSameApplication(client->client(), current, Window::SameApplicationCheck::AllowCrossProcesses)) {
for (const Window *other : list) {
if (Window::belongToSameApplication(other, client, Window::SameApplicationCheck::AllowCrossProcesses)) {
return false;
}
}
return true;
case TabBoxConfig::AllWindowsCurrentApplication: {
const std::shared_ptr<TabBoxClientImpl> client = std::dynamic_pointer_cast<TabBoxClientImpl>(tabBox->activeClient().lock());
return client && Window::belongToSameApplication(client->client(), current, Window::SameApplicationCheck::AllowCrossProcesses);
const Window *active = tabBox->activeClient();
return active && Window::belongToSameApplication(active, client, Window::SameApplicationCheck::AllowCrossProcesses);
}
default: // TabBoxConfig::AllWindowsAllApplications
return true;
}
}
bool TabBoxHandlerImpl::checkMinimized(TabBoxClient *client) const
bool TabBoxHandlerImpl::checkMinimized(Window *client) const
{
switch (config().clientMinimizedMode()) {
case TabBoxConfig::ExcludeMinimizedClients:
@ -188,65 +163,54 @@ bool TabBoxHandlerImpl::checkMinimized(TabBoxClient *client) const
}
}
bool TabBoxHandlerImpl::checkMultiScreen(TabBoxClient *client) const
bool TabBoxHandlerImpl::checkMultiScreen(Window *client) const
{
auto current = (static_cast<TabBoxClientImpl *>(client))->client();
switch (config().clientMultiScreenMode()) {
case TabBoxConfig::IgnoreMultiScreen:
return true;
case TabBoxConfig::ExcludeCurrentScreenClients:
return current->output() != workspace()->activeOutput();
return client->output() != workspace()->activeOutput();
default: // TabBoxConfig::OnlyCurrentScreenClients
return current->output() == workspace()->activeOutput();
return client->output() == workspace()->activeOutput();
}
}
std::weak_ptr<TabBoxClient> TabBoxHandlerImpl::clientToAddToList(TabBoxClient *client, int desktop) const
Window *TabBoxHandlerImpl::clientToAddToList(Window *client, int desktop) const
{
if (!client) {
return std::weak_ptr<TabBoxClient>();
return nullptr;
}
Window *ret = nullptr;
Window *current = (static_cast<TabBoxClientImpl *>(client))->client();
bool addClient = checkDesktop(client, desktop)
&& checkActivity(client)
&& checkApplications(client)
&& checkMinimized(client)
&& checkMultiScreen(client);
addClient = addClient && current->wantsTabFocus() && !current->skipSwitcher();
addClient = addClient && client->wantsTabFocus() && !client->skipSwitcher();
if (addClient) {
// don't add windows that have modal dialogs
Window *modal = current->findModal();
if (modal == nullptr || modal == current) {
ret = current;
Window *modal = client->findModal();
if (modal == nullptr || modal == client) {
ret = client;
} else {
const auto list = clientList();
const bool contains = std::any_of(list.cbegin(), list.cend(), [c = std::static_pointer_cast<TabBoxClientImpl>(modal->tabBoxClient().lock())](auto &weak) {
return weak.lock() == c;
});
if (contains) {
if (clientList().contains(modal)) {
ret = modal;
} else {
// nothing
}
}
}
if (ret) {
return std::static_pointer_cast<TabBoxClientImpl>(ret->tabBoxClient().lock());
} else {
return std::weak_ptr<TabBoxClient>();
}
return ret;
}
TabBoxClientList TabBoxHandlerImpl::stackingOrder() const
QList<Window *> TabBoxHandlerImpl::stackingOrder() const
{
const QList<Window *> stacking = Workspace::self()->stackingOrder();
TabBoxClientList ret;
QList<Window *> ret;
for (Window *window : stacking) {
if (window->isClient()) {
ret.append(std::static_pointer_cast<TabBoxClientImpl>(window->tabBoxClient().lock()));
ret.append(window);
}
}
return ret;
@ -257,46 +221,43 @@ bool TabBoxHandlerImpl::isKWinCompositing() const
return Compositor::compositing();
}
void TabBoxHandlerImpl::raiseClient(TabBoxClient *c) const
void TabBoxHandlerImpl::raiseClient(Window *c) const
{
Workspace::self()->raiseWindow(static_cast<TabBoxClientImpl *>(c)->client());
Workspace::self()->raiseWindow(c);
}
void TabBoxHandlerImpl::restack(TabBoxClient *c, TabBoxClient *under)
void TabBoxHandlerImpl::restack(Window *c, Window *under)
{
Workspace::self()->restack(static_cast<TabBoxClientImpl *>(c)->client(),
static_cast<TabBoxClientImpl *>(under)->client(), true);
Workspace::self()->restack(c, under, true);
}
void TabBoxHandlerImpl::elevateClient(TabBoxClient *c, QWindow *tabbox, bool b) const
void TabBoxHandlerImpl::elevateClient(Window *c, QWindow *tabbox, bool b) const
{
auto cl = static_cast<TabBoxClientImpl *>(c)->client();
cl->elevate(b);
c->elevate(b);
if (Window *w = Workspace::self()->findInternal(tabbox)) {
w->elevate(b);
}
}
void TabBoxHandlerImpl::shadeClient(TabBoxClient *c, bool b) const
void TabBoxHandlerImpl::shadeClient(Window *c, bool b) const
{
Window *client = static_cast<TabBoxClientImpl *>(c)->client();
client->cancelShadeHoverTimer(); // stop core shading action
if (!b && client->shadeMode() == ShadeNormal) {
client->setShade(ShadeHover);
} else if (b && client->shadeMode() == ShadeHover) {
client->setShade(ShadeNormal);
c->cancelShadeHoverTimer(); // stop core shading action
if (!b && c->shadeMode() == ShadeNormal) {
c->setShade(ShadeHover);
} else if (b && c->shadeMode() == ShadeHover) {
c->setShade(ShadeNormal);
}
}
std::weak_ptr<TabBoxClient> TabBoxHandlerImpl::desktopClient() const
Window *TabBoxHandlerImpl::desktopClient() const
{
const auto stackingOrder = Workspace::self()->stackingOrder();
for (Window *window : stackingOrder) {
if (window->isClient() && window->isDesktop() && window->isOnCurrentDesktop() && window->output() == workspace()->activeOutput()) {
return window->tabBoxClient();
return window;
}
}
return std::weak_ptr<TabBoxClient>();
return nullptr;
}
void TabBoxHandlerImpl::activateAndClose()
@ -304,14 +265,14 @@ void TabBoxHandlerImpl::activateAndClose()
m_tabBox->accept();
}
void TabBoxHandlerImpl::highlightWindows(TabBoxClient *window, QWindow *controller)
void TabBoxHandlerImpl::highlightWindows(Window *window, QWindow *controller)
{
if (!effects) {
return;
}
QVector<EffectWindow *> windows;
if (window) {
windows << static_cast<TabBoxClientImpl *>(window)->client()->effectWindow();
windows << window->effectWindow();
}
if (Window *t = workspace()->findInternal(controller)) {
windows << t->effectWindow();
@ -324,77 +285,6 @@ bool TabBoxHandlerImpl::noModifierGrab() const
return m_tabBox->noModifierGrab();
}
/*********************************************************
* TabBoxClientImpl
*********************************************************/
TabBoxClientImpl::TabBoxClientImpl(Window *client)
: TabBoxClient()
, m_client(client)
{
}
TabBoxClientImpl::~TabBoxClientImpl()
{
}
QString TabBoxClientImpl::caption() const
{
if (m_client->isDesktop()) {
return i18nc("Special entry in alt+tab list for minimizing all windows",
"Show Desktop");
}
return m_client->caption();
}
QIcon TabBoxClientImpl::icon() const
{
if (m_client->isDesktop()) {
return QIcon::fromTheme(QStringLiteral("user-desktop"));
}
return m_client->icon();
}
bool TabBoxClientImpl::isMinimized() const
{
return m_client->isMinimized();
}
int TabBoxClientImpl::x() const
{
return m_client->x();
}
int TabBoxClientImpl::y() const
{
return m_client->y();
}
int TabBoxClientImpl::width() const
{
return m_client->width();
}
int TabBoxClientImpl::height() const
{
return m_client->height();
}
bool TabBoxClientImpl::isCloseable() const
{
return m_client->isCloseable();
}
void TabBoxClientImpl::close()
{
m_client->closeWindow();
}
QUuid TabBoxClientImpl::internalId() const
{
return m_client->internalId();
}
/*********************************************************
* TabBox
*********************************************************/
@ -555,11 +445,11 @@ void TabBox::nextPrev(bool next)
Window *TabBox::currentClient()
{
if (TabBoxClientImpl *client = static_cast<TabBoxClientImpl *>(m_tabBox->client(m_tabBox->currentIndex()))) {
if (!Workspace::self()->hasWindow(client->client())) {
if (Window *client = m_tabBox->client(m_tabBox->currentIndex())) {
if (!Workspace::self()->hasWindow(client)) {
return nullptr;
}
return client->client();
return client;
} else {
return nullptr;
}
@ -567,23 +457,12 @@ Window *TabBox::currentClient()
QList<Window *> TabBox::currentClientList()
{
const TabBoxClientList list = m_tabBox->clientList();
QList<Window *> ret;
for (const std::weak_ptr<TabBoxClient> &clientPointer : list) {
std::shared_ptr<TabBoxClient> client = clientPointer.lock();
if (!client) {
continue;
}
if (const TabBoxClientImpl *c = static_cast<const TabBoxClientImpl *>(client.get())) {
ret.append(c->client());
}
}
return ret;
return m_tabBox->clientList();
}
void TabBox::setCurrentClient(Window *newClient)
{
setCurrentIndex(m_tabBox->index(std::static_pointer_cast<TabBoxClientImpl>(newClient->tabBoxClient().lock())));
setCurrentIndex(m_tabBox->index(newClient));
}
void TabBox::setCurrentIndex(QModelIndex index, bool notifyEffects)

View file

@ -41,60 +41,34 @@ public:
~TabBoxHandlerImpl() override;
int activeScreen() const override;
std::weak_ptr<TabBoxClient> activeClient() const override;
Window *activeClient() const override;
int currentDesktop() const override;
QString desktopName(TabBoxClient *client) const override;
QString desktopName(Window *client) const override;
bool isKWinCompositing() const override;
std::weak_ptr<TabBoxClient> nextClientFocusChain(TabBoxClient *client) const override;
std::weak_ptr<TabBoxClient> firstClientFocusChain() const override;
bool isInFocusChain(TabBoxClient *client) const override;
TabBoxClientList stackingOrder() const override;
void elevateClient(TabBoxClient *c, QWindow *tabbox, bool elevate) const override;
void raiseClient(TabBoxClient *client) const override;
void restack(TabBoxClient *c, TabBoxClient *under) override;
void shadeClient(TabBoxClient *c, bool b) const override;
std::weak_ptr<TabBoxClient> clientToAddToList(KWin::TabBox::TabBoxClient *client, int desktop) const override;
std::weak_ptr<TabBoxClient> desktopClient() const override;
Window *nextClientFocusChain(Window *client) const override;
Window *firstClientFocusChain() const override;
bool isInFocusChain(Window *client) const override;
QList<Window *> stackingOrder() const override;
void elevateClient(Window *c, QWindow *tabbox, bool elevate) const override;
void raiseClient(Window *client) const override;
void restack(Window *c, Window *under) override;
void shadeClient(Window *c, bool b) const override;
Window *clientToAddToList(Window *client, int desktop) const override;
Window *desktopClient() const override;
void activateAndClose() override;
void highlightWindows(TabBoxClient *window = nullptr, QWindow *controller = nullptr) override;
void highlightWindows(Window *window = nullptr, QWindow *controller = nullptr) override;
bool noModifierGrab() const override;
private:
bool checkDesktop(TabBoxClient *client, int desktop) const;
bool checkActivity(TabBoxClient *client) const;
bool checkApplications(TabBoxClient *client) const;
bool checkMinimized(TabBoxClient *client) const;
bool checkMultiScreen(TabBoxClient *client) const;
bool checkDesktop(Window *client, int desktop) const;
bool checkActivity(Window *client) const;
bool checkApplications(Window *client) const;
bool checkMinimized(Window *client) const;
bool checkMultiScreen(Window *client) const;
TabBox *m_tabBox;
};
class TabBoxClientImpl : public TabBoxClient
{
public:
explicit TabBoxClientImpl(Window *client);
~TabBoxClientImpl() override;
QString caption() const override;
QIcon icon() const override;
bool isMinimized() const override;
int x() const override;
int y() const override;
int width() const override;
int height() const override;
bool isCloseable() const override;
void close() override;
QUuid internalId() const override;
Window *client() const
{
return m_client;
}
private:
Window *m_client;
};
class KWIN_EXPORT TabBox : public QObject
{
Q_OBJECT

View file

@ -41,71 +41,71 @@ class TabBoxConfig
public:
/**
* ClientDesktopMode defines whether windows from the current desktop or from all
* desktops are included in the TabBoxClient List in the TabBoxClientModel
* desktops are included in the Window List in the ClientModel
*/
enum ClientDesktopMode {
AllDesktopsClients, ///< TabBoxClients from all desktops are included.
OnlyCurrentDesktopClients, ///< Only TabBoxClients on current desktop are included
ExcludeCurrentDesktopClients ///< Exclude TabBoxClients on current desktop
AllDesktopsClients, ///< Windows from all desktops are included.
OnlyCurrentDesktopClients, ///< Only Windows on current desktop are included
ExcludeCurrentDesktopClients ///< Exclude Windows on current desktop
};
/**
* ClientActivitiesMode defines whether windows from the current activity or from all
* activities are included in the TabBoxClient List in the TabBoxClientModel
* activities are included in the Window List in the ClientModel
*/
enum ClientActivitiesMode {
AllActivitiesClients, ///< TabBoxClients from all Activities are included.
OnlyCurrentActivityClients, ///< Only TabBoxClients on current activity are included
ExcludeCurrentActivityClients ///< Exclude TabBoxClients on current activity
AllActivitiesClients, ///< Windows from all Activities are included.
OnlyCurrentActivityClients, ///< Only Windows on current activity are included
ExcludeCurrentActivityClients ///< Exclude Windows on current activity
};
/**
* ClientApplicationsMode defines which windows from the current application or from all
* applications are included in the TabBoxClient List in the TabBoxClientModel
* applications are included in the Window List in the ClientModel
*/
enum ClientApplicationsMode {
AllWindowsAllApplications, ///< TabBoxClients from all applications are included
OneWindowPerApplication, ///< Only one TabBoxClient for each application is included
AllWindowsCurrentApplication ///< Only TabBoxClients for the current application are included
AllWindowsAllApplications, ///< Windows from all applications are included
OneWindowPerApplication, ///< Only one Window for each application is included
AllWindowsCurrentApplication ///< Only Windows for the current application are included
};
/**
* ClientMinimizedMode defines which windows are included in the TabBoxClient List
* in the TabBoxClientModel based on whether they are minimized or not
* ClientMinimizedMode defines which windows are included in the Window List
* in the ClientModel based on whether they are minimized or not
*/
enum ClientMinimizedMode {
IgnoreMinimizedStatus, ///< TabBoxClients are included no matter they are minimized or not
ExcludeMinimizedClients, ///< Exclude minimized TabBoxClients
OnlyMinimizedClients ///< Only minimized TabBoxClients are included
IgnoreMinimizedStatus, ///< Windows are included no matter they are minimized or not
ExcludeMinimizedClients, ///< Exclude minimized Windows
OnlyMinimizedClients ///< Only minimized Windows are included
};
/**
* ShowDesktopMode defines whether a TabBoxClient representing the desktop
* is included in the TabBoxClient List in the TabBoxClientModel
* ShowDesktopMode defines whether a Window representing the desktop
* is included in the Window List in the ClientModel
*/
enum ShowDesktopMode {
DoNotShowDesktopClient, ///< A TabBoxClient representing the desktop is not included
ShowDesktopClient ///< A TabBoxClient representing the desktop is included
DoNotShowDesktopClient, ///< A Window representing the desktop is not included
ShowDesktopClient ///< A Window representing the desktop is included
};
/**
* OrderMinimizedMode defines whether the TabBoxClients considered part of the
* TabBoxClient List should be grouped by the minimisation status
* OrderMinimizedMode defines whether the Windows considered part of the
* Window List should be grouped by the minimisation status
*/
enum OrderMinimizedMode {
NoGroupByMinimized, ///< TabBoxClients are not grouped by whether they are minimized
GroupByMinimized ///< TabBoxClients are grouped by whether they are minimized or not
NoGroupByMinimized, ///< Windows are not grouped by whether they are minimized
GroupByMinimized ///< Windows are grouped by whether they are minimized or not
};
/**
* ClientActivitiesMode defines whether windows from the current activity or from all
* activities are included in the TabBoxClient List in the TabBoxClientModel
* activities are included in the Window List in the ClientModel
*/
enum ClientMultiScreenMode {
IgnoreMultiScreen, ///< TabBoxClients are included independently of the screen they are on
OnlyCurrentScreenClients, ///< Only TabBoxClients on current screen are included
ExcludeCurrentScreenClients ///< Exclude TabBoxClients from the current screen
IgnoreMultiScreen, ///< Windows are included independently of the screen they are on
OnlyCurrentScreenClients, ///< Only Windows on current screen are included
ExcludeCurrentScreenClients ///< Exclude Windows from the current screen
};
/**
* ClientSwitchingMode defines the sorting of the TabBoxClients in the
* TabBoxClientModel.
* ClientSwitchingMode defines the sorting of the Windows in the
* ClientModel.
*/
enum ClientSwitchingMode {
FocusChainSwitching, ///< Sort by recently used. Most recently used TabBoxClient is the first
FocusChainSwitching, ///< Sort by recently used. Most recently used Window is the first
StackingOrderSwitching ///< Sort by current stacking order
};
TabBoxConfig();

View file

@ -15,6 +15,7 @@
#include "scripting/scripting.h"
#include "switcheritem.h"
#include "tabbox_logging.h"
#include "window.h"
// Qt
#include <QKeyEvent>
#include <QQmlComponent>
@ -73,7 +74,7 @@ public:
* Indicates if the tabbox is shown.
*/
bool isShown;
TabBoxClient *lastRaisedClient, *lastRaisedClientSucc;
Window *lastRaisedClient, *lastRaisedClientSucc;
int wheelAngleDelta = 0;
private:
@ -144,7 +145,7 @@ void TabBoxHandlerPrivate::updateHighlightWindows()
return;
}
TabBoxClient *currentClient = q->client(index);
Window *currentClient = q->client(index);
QWindow *w = window();
if (q->isKWinCompositing()) {
@ -153,7 +154,7 @@ void TabBoxHandlerPrivate::updateHighlightWindows()
}
lastRaisedClient = currentClient;
// don't elevate desktop
const auto desktop = q->desktopClient().lock();
const auto desktop = q->desktopClient();
if (currentClient && (!desktop || currentClient->internalId() != desktop->internalId())) {
q->elevateClient(currentClient, w, true);
}
@ -171,15 +172,15 @@ void TabBoxHandlerPrivate::updateHighlightWindows()
q->shadeClient(lastRaisedClient, false);
// TODO if ( (lastRaisedClientWasMinimized = lastRaisedClient->isMinimized()) )
// lastRaisedClient->setMinimized( false );
TabBoxClientList order = q->stackingOrder();
QList<Window *> order = q->stackingOrder();
int succIdx = order.count() + 1;
for (int i = 0; i < order.count(); ++i) {
if (order.at(i).lock().get() == lastRaisedClient) {
if (order.at(i) == lastRaisedClient) {
succIdx = i + 1;
break;
}
}
lastRaisedClientSucc = (succIdx < order.count()) ? order.at(succIdx).lock().get() : nullptr;
lastRaisedClientSucc = (succIdx < order.count()) ? order.at(succIdx) : nullptr;
q->raiseClient(lastRaisedClient);
}
}
@ -193,14 +194,12 @@ void TabBoxHandlerPrivate::updateHighlightWindows()
void TabBoxHandlerPrivate::endHighlightWindows(bool abort)
{
TabBoxClient *currentClient = q->client(index);
Window *currentClient = q->client(index);
if (isHighlightWindows() && q->isKWinCompositing()) {
const auto stackingOrder = q->stackingOrder();
for (const std::weak_ptr<TabBoxClient> &clientPointer : stackingOrder) {
if (std::shared_ptr<TabBoxClient> client = clientPointer.lock()) {
if (client.get() != currentClient) { // to not mess up with wanted ShadeActive/ShadeHover state
q->shadeClient(client.get(), true);
}
for (Window *window : stackingOrder) {
if (window != currentClient) { // to not mess up with wanted ShadeActive/ShadeHover state
q->shadeClient(window, true);
}
}
}
@ -377,10 +376,8 @@ void TabBoxHandler::initHighlightWindows()
{
if (isKWinCompositing()) {
const auto stack = stackingOrder();
for (const std::weak_ptr<TabBoxClient> &clientPointer : stack) {
if (std::shared_ptr<TabBoxClient> client = clientPointer.lock()) {
shadeClient(client.get(), false);
}
for (Window *window : stack) {
shadeClient(window, false);
}
}
d->updateHighlightWindows();
@ -490,22 +487,22 @@ bool TabBoxHandler::containsPos(const QPoint &pos) const
return false;
}
QModelIndex TabBoxHandler::index(std::weak_ptr<KWin::TabBox::TabBoxClient> client) const
QModelIndex TabBoxHandler::index(Window *client) const
{
return d->clientModel()->index(client);
}
TabBoxClientList TabBoxHandler::clientList() const
QList<Window *> TabBoxHandler::clientList() const
{
return d->clientModel()->clientList();
}
TabBoxClient *TabBoxHandler::client(const QModelIndex &index) const
Window *TabBoxHandler::client(const QModelIndex &index) const
{
if (!index.isValid()) {
return nullptr;
}
TabBoxClient *c = static_cast<TabBoxClient *>(
Window *c = static_cast<Window *>(
d->clientModel()->data(index, ClientModel::ClientRole).value<void *>());
return c;
}
@ -517,15 +514,11 @@ void TabBoxHandler::createModel(bool partialReset)
bool lastRaised = false;
bool lastRaisedSucc = false;
const auto clients = stackingOrder();
for (const auto &clientPointer : clients) {
std::shared_ptr<TabBoxClient> client = clientPointer.lock();
if (!client) {
continue;
}
if (client.get() == d->lastRaisedClient) {
for (Window *window : clients) {
if (window == d->lastRaisedClient) {
lastRaised = true;
}
if (client.get() == d->lastRaisedClientSucc) {
if (window == d->lastRaisedClientSucc) {
lastRaisedSucc = true;
}
}
@ -571,13 +564,5 @@ bool TabBoxHandler::eventFilter(QObject *watched, QEvent *e)
TabBoxHandler *tabBox = nullptr;
TabBoxClient::TabBoxClient()
{
}
TabBoxClient::~TabBoxClient()
{
}
} // namespace TabBox
} // namespace KWin

View file

@ -18,8 +18,6 @@
/**
* @file
* This file contains the classes which hide KWin core from tabbox.
* It defines the pure virtual classes TabBoxHandler and TabBoxClient.
* The classes have to be implemented in KWin Core.
*
* @author Martin Gräßlin <mgraesslin@kde.org>
* @since 4.4
@ -29,13 +27,15 @@ class QKeyEvent;
namespace KWin
{
class Window;
/**
* The TabBox is a model based view for displaying a list while switching windows.
* This functionality is mostly referred to as Alt+Tab. TabBox itself does not provide support for
* switching windows. This has to be done outside of TabBox inside an independent controller.
*
* The main entrance point to TabBox is the class TabBoxHandler, which has to be subclassed and implemented.
* The class TabBoxClient, which represents a window client inside TabBox, has to be implemented as well.
*
* The behavior of the TabBox is defined by the TabBoxConfig and has to be set in the TabBoxHandler.
*
@ -62,9 +62,7 @@ namespace TabBox
{
class ClientModel;
class TabBoxConfig;
class TabBoxClient;
class TabBoxHandlerPrivate;
typedef QList<std::weak_ptr<TabBoxClient>> TabBoxClientList;
/**
* This class is a wrapper around KWin Workspace. It is used for accessing the
@ -85,15 +83,15 @@ public:
*/
virtual int activeScreen() const = 0;
/**
* @return The current active TabBoxClient or NULL
* @return The current active Window or NULL
* if there is no active client.
*/
virtual std::weak_ptr<TabBoxClient> activeClient() const = 0;
virtual Window *activeClient() const = 0;
/**
* @param client The client which is starting point to find the next client
* @return The next TabBoxClient in focus chain
* @return The next Window in focus chain
*/
virtual std::weak_ptr<TabBoxClient> nextClientFocusChain(TabBoxClient *client) const = 0;
virtual Window *nextClientFocusChain(Window *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.
@ -101,7 +99,7 @@ public:
* @return The first Client of the focus chain
* @since 4.9.1
*/
virtual std::weak_ptr<TabBoxClient> firstClientFocusChain() const = 0;
virtual Window *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
@ -115,13 +113,13 @@ public:
* @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;
virtual bool isInFocusChain(Window *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
* @return The desktop name of the given Window. If the client is
* on all desktops the name of current desktop will be returned.
*/
virtual QString desktopName(TabBoxClient *client) const = 0;
virtual QString desktopName(Window *client) const = 0;
/**
* @return The number of current desktop
*/
@ -135,32 +133,32 @@ public:
/**
* De-/Elevate a client using the compositor (if enabled)
*/
virtual void elevateClient(TabBoxClient *c, QWindow *tabbox, bool elevate) const = 0;
virtual void elevateClient(Window *c, QWindow *tabbox, bool elevate) const = 0;
/**
* Raise a client (w/o activating it)
*/
virtual void raiseClient(TabBoxClient *c) const = 0;
virtual void raiseClient(Window *c) const = 0;
/**
* @param c The client to be restacked
* @param under The client the other one will be placed below
*/
virtual void restack(TabBoxClient *c, TabBoxClient *under) = 0;
virtual void restack(Window *c, Window *under) = 0;
/**
* Toggle between ShadeHover and ShadeNormal - not shaded windows are unaffected
* @param c The client to be shaded
* @param b Whether to un- or shade
*/
virtual void shadeClient(TabBoxClient *c, bool b) const = 0;
virtual void shadeClient(Window *c, bool b) const = 0;
virtual void highlightWindows(TabBoxClient *window = nullptr, QWindow *controller = nullptr) = 0;
virtual void highlightWindows(Window *window = nullptr, QWindow *controller = nullptr) = 0;
/**
* @return The current stacking order of TabBoxClients
* @return The current stacking order of Windows
*/
virtual TabBoxClientList stackingOrder() const = 0;
virtual QList<Window *> stackingOrder() const = 0;
/**
* Determines if given client will be added to the list:
* <UL>
@ -177,11 +175,11 @@ public:
* @param allDesktops Add clients from all desktops or only from current
* @return The client to be included in the list or NULL if it isn't to be included
*/
virtual std::weak_ptr<TabBoxClient> clientToAddToList(TabBoxClient *client, int desktop) const = 0;
virtual Window *clientToAddToList(Window *client, int desktop) const = 0;
/**
* @return The first desktop window in the stacking order.
*/
virtual std::weak_ptr<TabBoxClient> desktopClient() const = 0;
virtual Window *desktopClient() const = 0;
/**
* Activates the currently selected client and closes the TabBox.
*/
@ -253,24 +251,24 @@ public:
*/
bool containsPos(const QPoint &pos) const;
/**
* @param client The TabBoxClient whose index should be returned
* @return Returns the ModelIndex of given TabBoxClient or an invalid ModelIndex
* if the model does not contain the given TabBoxClient.
* @param client The Window whose index should be returned
* @return Returns the ModelIndex of given Window or an invalid ModelIndex
* if the model does not contain the given Window.
* @see ClientModel::index
*/
QModelIndex index(std::weak_ptr<TabBoxClient> client) const;
QModelIndex index(Window *client) const;
/**
* @return Returns the current list of TabBoxClients.
* @return Returns the current list of Windows.
* @see ClientModel::clientList
*/
TabBoxClientList clientList() const;
QList<Window *> clientList() const;
/**
* @param index The index of the client to be returned
* @return Returns the TabBoxClient at given model index. If
* @return Returns the Window at given model index. If
* the index is invalid, does not point to a Client or the list
* is empty, NULL will be returned.
*/
TabBoxClient *client(const QModelIndex &index) const;
Window *client(const QModelIndex &index) const;
/**
* @return The first model index. That is the model index at position 0, 0.
* It is valid, as desktop has at least one desktop and if there are no
@ -302,41 +300,6 @@ private:
TabBoxHandlerPrivate *d;
};
/**
* This class is a wrapper around a KWin Client. It is used for accessing the
* required client methods from inside TabBox and has to be implemented in KWin core.
*
* @author Martin Gräßlin <mgraesslin@kde.org>
* @since 4.4
*/
class TabBoxClient
{
public:
TabBoxClient();
virtual ~TabBoxClient();
/**
* @return The caption of the client
*/
virtual QString caption() const = 0;
/**
* @param size Requested size of the icon
* @return The icon of the client
*/
virtual QIcon icon() const = 0;
/**
* @return Minimized state of the client
*/
virtual bool isMinimized() const = 0;
virtual int x() const = 0;
virtual int y() const = 0;
virtual int width() const = 0;
virtual int height() const = 0;
virtual bool isCloseable() const = 0;
virtual void close() = 0;
virtual QUuid internalId() const = 0;
};
/**
* Pointer to the global TabBoxHandler object.
*/

View file

@ -76,9 +76,6 @@ Window::Window()
, m_clientMachine(new ClientMachine(this))
, m_wmClientLeader(XCB_WINDOW_NONE)
, m_skipCloseAnimation(false)
#if KWIN_BUILD_TABBOX
, m_tabBoxClient(std::make_shared<TabBox::TabBoxClientImpl>(this))
#endif
, m_colorScheme(QStringLiteral("kdeglobals"))
, m_moveResizeOutput(workspace()->activeOutput())
{

View file

@ -66,11 +66,6 @@ enum class ReleaseReason {
KWinShutsDown ///< Release on KWin Shutdown (window still valid)
};
namespace TabBox
{
class TabBoxClientImpl;
}
namespace Decoration
{
class DecoratedClientImpl;
@ -821,10 +816,6 @@ public:
int stackingOrder() const;
void setStackingOrder(int order); ///< @internal
std::weak_ptr<TabBox::TabBoxClientImpl> tabBoxClient() const
{
return m_tabBoxClient;
}
bool skipSwitcher() const
{
return m_skipSwitcher;
@ -1886,7 +1877,6 @@ private:
QRectF moveToArea(const QRectF &geometry, const QRectF &oldArea, const QRectF &newArea);
QRectF ensureSpecialStateGeometry(const QRectF &geometry);
std::shared_ptr<TabBox::TabBoxClientImpl> m_tabBoxClient;
bool m_skipTaskbar = false;
/**
* Unaffected by KWin