scripting: Drop org.kde.kwin 2.x

It's superseded by 3.x.
This commit is contained in:
Vlad Zahorodnii 2023-01-29 12:33:02 +02:00
parent 2ca4627207
commit 600de787d8
10 changed files with 1 additions and 1359 deletions

View file

@ -145,7 +145,6 @@ target_sources(kwin PRIVATE
scripting/scripting_logging.cpp
scripting/scriptingutils.cpp
scripting/tilemodel.cpp
scripting/v2/clientmodel.cpp
scripting/v3/clientmodel.cpp
scripting/v3/virtualdesktopmodel.cpp
scripting/windowthumbnailitem.cpp

View file

@ -31,11 +31,9 @@ LayoutPreview::LayoutPreview(const QString &path, bool showDesktopThumbnail, QOb
{
QQmlEngine *engine = new QQmlEngine(this);
QQmlComponent *component = new QQmlComponent(engine, this);
qmlRegisterType<WindowThumbnailItem>("org.kde.kwin", 2, 0, "ThumbnailItem");
qmlRegisterType<SwitcherItem>("org.kde.kwin", 2, 0, "Switcher");
qmlRegisterType<WindowThumbnailItem>("org.kde.kwin", 3, 0, "WindowThumbnailItem");
qmlRegisterType<SwitcherItem>("org.kde.kwin", 3, 0, "TabBoxSwitcher");
qmlRegisterAnonymousType<QAbstractItemModel>("org.kde.kwin", 2);
qmlRegisterAnonymousType<QAbstractItemModel>("org.kde.kwin", 3);
component->loadUrl(QUrl::fromLocalFile(path));
if (component->isError()) {
qDebug() << component->errorString();

View file

@ -1,5 +1,3 @@
add_subdirectory(v2)
if (KWIN_BUILD_KCMS)
set(kcm_kwin4_genericscripted_SRCS genericscriptedconfig.cpp)
qt_add_dbus_interface(kcm_kwin4_genericscripted_SRCS ${kwin_effects_dbus_xml} kwineffects_interface)

View file

@ -20,7 +20,6 @@
#include "windowthumbnailitem.h"
#include "workspace_wrapper.h"
#include "v2/clientmodel.h"
#include "v3/clientmodel.h"
#include "v3/virtualdesktopmodel.h"
@ -672,16 +671,6 @@ KWin::Scripting::Scripting(QObject *parent)
void KWin::Scripting::init()
{
qmlRegisterType<WindowThumbnailItem>("org.kde.kwin", 2, 0, "ThumbnailItem");
qmlRegisterType<DBusCall>("org.kde.kwin", 2, 0, "DBusCall");
qmlRegisterType<ScreenEdgeItem>("org.kde.kwin", 2, 0, "ScreenEdgeItem");
qmlRegisterAnonymousType<ScriptingModels::V2::ClientModel>("org.kde.kwin", 2);
qmlRegisterType<ScriptingModels::V2::SimpleClientModel>("org.kde.kwin", 2, 0, "ClientModel");
qmlRegisterType<ScriptingModels::V2::ClientModelByScreen>("org.kde.kwin", 2, 0, "ClientModelByScreen");
qmlRegisterType<ScriptingModels::V2::ClientModelByScreenAndDesktop>("org.kde.kwin", 2, 0, "ClientModelByScreenAndDesktop");
qmlRegisterType<ScriptingModels::V2::ClientModelByScreenAndActivity>("org.kde.kwin", 2, 1, "ClientModelByScreenAndActivity");
qmlRegisterType<ScriptingModels::V2::ClientFilterModel>("org.kde.kwin", 2, 0, "ClientFilterModel");
qmlRegisterType<DesktopBackgroundItem>("org.kde.kwin", 3, 0, "DesktopBackgroundItem");
qmlRegisterType<WindowThumbnailItem>("org.kde.kwin", 3, 0, "WindowThumbnailItem");
qmlRegisterType<DBusCall>("org.kde.kwin", 3, 0, "DBusCall");
@ -696,10 +685,6 @@ void KWin::Scripting::init()
});
qmlRegisterSingletonInstance("org.kde.kwin", 3, 0, "Options", options);
qmlRegisterAnonymousType<KWin::Window>("org.kde.kwin", 2);
qmlRegisterAnonymousType<KWin::VirtualDesktop>("org.kde.kwin", 2);
qmlRegisterAnonymousType<KWin::X11Window>("org.kde.kwin", 2);
qmlRegisterAnonymousType<QAbstractItemModel>("org.kde.kwin", 2);
qmlRegisterAnonymousType<KWin::Window>("org.kde.kwin", 3);
qmlRegisterAnonymousType<KWin::VirtualDesktop>("org.kde.kwin", 3);
qmlRegisterAnonymousType<KWin::X11Window>("org.kde.kwin", 3);
@ -708,15 +693,6 @@ void KWin::Scripting::init()
// TODO: call the qml types as the C++ types?
qmlRegisterUncreatableType<KWin::CustomTile>("org.kde.kwin", 3, 0, "CustomTile", QStringLiteral("Cannot create objects of type Tile"));
qmlRegisterUncreatableType<KWin::Tile>("org.kde.kwin", 3, 0, "Tile", QStringLiteral("Cannot create objects of type AbstractTile"));
// TODO Plasma 6: Drop context properties.
m_qmlEngine->rootContext()->setContextProperty(QStringLiteral("workspace"), m_workspaceWrapper);
m_qmlEngine->rootContext()->setContextProperty(QStringLiteral("options"), options);
m_declarativeScriptSharedContext->setContextProperty(QStringLiteral("workspace"), new DeclarativeScriptWorkspaceWrapper(this));
// QQmlListProperty interfaces only work via properties, rebind them as functions here
QQmlExpression expr(m_declarativeScriptSharedContext, nullptr, "workspace.clientList = function() { return workspace.clients }");
expr.evaluate();
}
void KWin::Scripting::start()

View file

@ -1,6 +0,0 @@
# SPDX-FileCopyrightText: 2022 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
#
# SPDX-License-Identifier: BSD-3-Clause
install(DIRECTORY qml/
DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/kwin.2)

View file

@ -1,905 +0,0 @@
/*
KWin - the KDE window manager
This file is part of the KDE project.
SPDX-FileCopyrightText: 2013 Martin Gräßlin <mgraesslin@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "clientmodel.h"
#include <config-kwin.h>
#if KWIN_BUILD_ACTIVITIES
#include "activities.h"
#endif
#include "core/output.h"
#include "virtualdesktops.h"
#include "window.h"
#include "workspace.h"
namespace KWin::ScriptingModels::V2
{
static quint32 nextId()
{
static quint32 counter = 0;
return ++counter;
}
ClientLevel::ClientLevel(ClientModel *model, AbstractLevel *parent)
: AbstractLevel(model, parent)
{
#if KWIN_BUILD_ACTIVITIES
if (Activities *activities = Workspace::self()->activities()) {
connect(activities, &Activities::currentChanged, this, &ClientLevel::reInit);
}
#endif
connect(VirtualDesktopManager::self(), &VirtualDesktopManager::currentChanged, this, &ClientLevel::reInit);
connect(Workspace::self(), &Workspace::windowAdded, this, &ClientLevel::clientAdded);
connect(Workspace::self(), &Workspace::windowRemoved, this, &ClientLevel::clientRemoved);
connect(model, &ClientModel::exclusionsChanged, this, &ClientLevel::reInit);
}
ClientLevel::~ClientLevel()
{
}
void ClientLevel::clientAdded(Window *client)
{
setupClientConnections(client);
checkClient(client);
}
void ClientLevel::clientRemoved(Window *client)
{
removeClient(client);
}
void ClientLevel::setupClientConnections(Window *client)
{
auto check = [this, client] {
checkClient(client);
};
connect(client, &Window::desktopChanged, this, check);
connect(client, &Window::screenChanged, this, check);
connect(client, &Window::activitiesChanged, this, check);
connect(client, &Window::windowHidden, this, check);
connect(client, &Window::windowShown, this, check);
}
void ClientLevel::checkClient(Window *client)
{
const bool shouldInclude = !exclude(client) && shouldAdd(client);
const bool contains = containsClient(client);
if (shouldInclude && !contains) {
addClient(client);
} else if (!shouldInclude && contains) {
removeClient(client);
}
}
bool ClientLevel::exclude(Window *client) const
{
ClientModel::Exclusions exclusions = model()->exclusions();
if (exclusions == ClientModel::NoExclusion) {
return false;
}
if (exclusions & ClientModel::DesktopWindowsExclusion) {
if (client->isDesktop()) {
return true;
}
}
if (exclusions & ClientModel::DockWindowsExclusion) {
if (client->isDock()) {
return true;
}
}
if (exclusions & ClientModel::UtilityWindowsExclusion) {
if (client->isUtility()) {
return true;
}
}
if (exclusions & ClientModel::SpecialWindowsExclusion) {
if (client->isSpecialWindow()) {
return true;
}
}
if (exclusions & ClientModel::SkipTaskbarExclusion) {
if (client->skipTaskbar()) {
return true;
}
}
if (exclusions & ClientModel::SkipPagerExclusion) {
if (client->skipPager()) {
return true;
}
}
if (exclusions & ClientModel::SwitchSwitcherExclusion) {
if (client->skipSwitcher()) {
return true;
}
}
if (exclusions & ClientModel::OtherDesktopsExclusion) {
if (!client->isOnCurrentDesktop()) {
return true;
}
}
if (exclusions & ClientModel::OtherActivitiesExclusion) {
if (!client->isOnCurrentActivity()) {
return true;
}
}
if (exclusions & ClientModel::MinimizedExclusion) {
if (client->isMinimized()) {
return true;
}
}
if (exclusions & ClientModel::NotAcceptingFocusExclusion) {
if (!client->wantsInput()) {
return true;
}
}
return false;
}
bool ClientLevel::shouldAdd(Window *client) const
{
if (restrictions() == ClientModel::NoRestriction) {
return true;
}
if (restrictions() & ClientModel::ActivityRestriction) {
if (!client->isOnActivity(activity())) {
return false;
}
}
if (restrictions() & ClientModel::VirtualDesktopRestriction) {
if (!client->isOnDesktop(virtualDesktop())) {
return false;
}
}
if (restrictions() & ClientModel::ScreenRestriction) {
if (client->screen() != int(screen())) {
return false;
}
}
return true;
}
void ClientLevel::addClient(Window *client)
{
if (containsClient(client)) {
return;
}
Q_EMIT beginInsert(m_clients.count(), m_clients.count(), id());
m_clients.insert(nextId(), client);
Q_EMIT endInsert();
}
void ClientLevel::removeClient(Window *client)
{
int index = 0;
auto it = m_clients.begin();
for (; it != m_clients.end(); ++it, ++index) {
if (it.value() == client) {
break;
}
}
if (it == m_clients.end()) {
return;
}
Q_EMIT beginRemove(index, index, id());
m_clients.erase(it);
Q_EMIT endRemove();
}
void ClientLevel::init()
{
const QList<Window *> &clients = workspace()->allClientList();
for (auto it = clients.begin(); it != clients.end(); ++it) {
Window *client = *it;
setupClientConnections(client);
if (!exclude(client) && shouldAdd(client)) {
m_clients.insert(nextId(), client);
}
}
}
void ClientLevel::reInit()
{
const QList<Window *> &clients = workspace()->allClientList();
for (auto it = clients.begin(); it != clients.end(); ++it) {
checkClient((*it));
}
}
quint32 ClientLevel::idForRow(int row) const
{
if (row >= m_clients.size()) {
return 0;
}
auto it = m_clients.constBegin();
for (int i = 0; i < row; ++i) {
++it;
}
return it.key();
}
bool ClientLevel::containsId(quint32 id) const
{
return m_clients.contains(id);
}
int ClientLevel::rowForId(quint32 id) const
{
int row = 0;
for (auto it = m_clients.constBegin();
it != m_clients.constEnd();
++it, ++row) {
if (it.key() == id) {
return row;
}
}
return -1;
}
Window *ClientLevel::clientForId(quint32 child) const
{
auto it = m_clients.constFind(child);
if (it == m_clients.constEnd()) {
return nullptr;
}
return it.value();
}
bool ClientLevel::containsClient(Window *client) const
{
for (auto it = m_clients.constBegin();
it != m_clients.constEnd();
++it) {
if (it.value() == client) {
return true;
}
}
return false;
}
const AbstractLevel *ClientLevel::levelForId(quint32 id) const
{
if (id == AbstractLevel::id()) {
return this;
}
return nullptr;
}
AbstractLevel *ClientLevel::parentForId(quint32 child) const
{
if (child == id()) {
return parentLevel();
}
if (m_clients.contains(child)) {
return const_cast<ClientLevel *>(this);
}
return nullptr;
}
AbstractLevel *AbstractLevel::create(const QList<ClientModel::LevelRestriction> &restrictions, ClientModel::LevelRestrictions parentRestrictions, ClientModel *model, AbstractLevel *parent)
{
if (restrictions.isEmpty() || restrictions.first() == ClientModel::NoRestriction) {
ClientLevel *leaf = new ClientLevel(model, parent);
leaf->setRestrictions(parentRestrictions);
if (!parent) {
leaf->setParent(model);
}
return leaf;
}
// create a level
QList<ClientModel::LevelRestriction> childRestrictions(restrictions);
ClientModel::LevelRestriction restriction = childRestrictions.takeFirst();
ClientModel::LevelRestrictions childrenRestrictions = restriction | parentRestrictions;
ForkLevel *currentLevel = new ForkLevel(childRestrictions, model, parent);
currentLevel->setRestrictions(childrenRestrictions);
currentLevel->setRestriction(restriction);
if (!parent) {
currentLevel->setParent(model);
}
switch (restriction) {
case ClientModel::ActivityRestriction: {
#if KWIN_BUILD_ACTIVITIES
if (Workspace::self()->activities()) {
const QStringList &activities = Workspace::self()->activities()->all();
for (QStringList::const_iterator it = activities.begin(); it != activities.end(); ++it) {
AbstractLevel *childLevel = create(childRestrictions, childrenRestrictions, model, currentLevel);
if (!childLevel) {
continue;
}
childLevel->setActivity(*it);
currentLevel->addChild(childLevel);
}
}
break;
#else
return nullptr;
#endif
}
case ClientModel::ScreenRestriction:
for (int i = 0; i < workspace()->outputs().count(); ++i) {
AbstractLevel *childLevel = create(childRestrictions, childrenRestrictions, model, currentLevel);
if (!childLevel) {
continue;
}
childLevel->setScreen(i);
currentLevel->addChild(childLevel);
}
break;
case ClientModel::VirtualDesktopRestriction:
for (uint i = 1; i <= VirtualDesktopManager::self()->count(); ++i) {
AbstractLevel *childLevel = create(childRestrictions, childrenRestrictions, model, currentLevel);
if (!childLevel) {
continue;
}
childLevel->setVirtualDesktop(i);
currentLevel->addChild(childLevel);
}
break;
default:
// invalid
return nullptr;
}
return currentLevel;
}
AbstractLevel::AbstractLevel(ClientModel *model, AbstractLevel *parent)
: QObject(parent)
, m_model(model)
, m_parent(parent)
, m_screen(0)
, m_virtualDesktop(0)
, m_activity()
, m_restriction(ClientModel::ClientModel::NoRestriction)
, m_restrictions(ClientModel::NoRestriction)
, m_id(nextId())
{
}
AbstractLevel::~AbstractLevel()
{
}
void AbstractLevel::setRestriction(ClientModel::LevelRestriction restriction)
{
m_restriction = restriction;
}
void AbstractLevel::setActivity(const QString &activity)
{
m_activity = activity;
}
void AbstractLevel::setScreen(uint screen)
{
m_screen = screen;
}
void AbstractLevel::setVirtualDesktop(uint virtualDesktop)
{
m_virtualDesktop = virtualDesktop;
}
void AbstractLevel::setRestrictions(ClientModel::LevelRestrictions restrictions)
{
m_restrictions = restrictions;
}
ForkLevel::ForkLevel(const QList<ClientModel::LevelRestriction> &childRestrictions, ClientModel *model, AbstractLevel *parent)
: AbstractLevel(model, parent)
, m_childRestrictions(childRestrictions)
{
connect(VirtualDesktopManager::self(), &VirtualDesktopManager::countChanged, this, &ForkLevel::desktopCountChanged);
connect(workspace(), &Workspace::outputAdded, this, &ForkLevel::outputAdded);
connect(workspace(), &Workspace::outputRemoved, this, &ForkLevel::outputRemoved);
#if KWIN_BUILD_ACTIVITIES
if (Activities *activities = Workspace::self()->activities()) {
connect(activities, &Activities::added, this, &ForkLevel::activityAdded);
connect(activities, &Activities::removed, this, &ForkLevel::activityRemoved);
}
#endif
}
ForkLevel::~ForkLevel()
{
}
void ForkLevel::desktopCountChanged(uint previousCount, uint newCount)
{
if (restriction() != ClientModel::ClientModel::VirtualDesktopRestriction) {
return;
}
if (previousCount != uint(count())) {
return;
}
if (previousCount > newCount) {
// desktops got removed
Q_EMIT beginRemove(newCount, previousCount - 1, id());
while (uint(m_children.count()) > newCount) {
delete m_children.takeLast();
}
Q_EMIT endRemove();
} else {
// desktops got added
Q_EMIT beginInsert(previousCount, newCount - 1, id());
for (uint i = previousCount + 1; i <= newCount; ++i) {
AbstractLevel *childLevel = AbstractLevel::create(m_childRestrictions, restrictions(), model(), this);
if (!childLevel) {
continue;
}
childLevel->setVirtualDesktop(i);
childLevel->init();
addChild(childLevel);
}
Q_EMIT endInsert();
}
}
void ForkLevel::outputAdded()
{
if (restriction() != ClientModel::ClientModel::ClientModel::ScreenRestriction) {
return;
}
const int row = count();
AbstractLevel *childLevel = AbstractLevel::create(m_childRestrictions, restrictions(), model(), this);
if (!childLevel) {
return;
}
Q_EMIT beginInsert(row, row, id());
childLevel->setScreen(row);
childLevel->init();
addChild(childLevel);
Q_EMIT endInsert();
}
void ForkLevel::outputRemoved()
{
if (restriction() != ClientModel::ClientModel::ClientModel::ScreenRestriction) {
return;
}
const int row = count() - 1;
Q_EMIT beginRemove(row, row, id());
delete m_children.takeLast();
Q_EMIT endRemove();
}
void ForkLevel::activityAdded(const QString &activityId)
{
#if KWIN_BUILD_ACTIVITIES
if (restriction() != ClientModel::ClientModel::ActivityRestriction) {
return;
}
// verify that our children do not contain this activity
for (AbstractLevel *child : std::as_const(m_children)) {
if (child->activity() == activityId) {
return;
}
}
Q_EMIT beginInsert(m_children.count(), m_children.count(), id());
AbstractLevel *childLevel = AbstractLevel::create(m_childRestrictions, restrictions(), model(), this);
if (!childLevel) {
Q_EMIT endInsert();
return;
}
childLevel->setActivity(activityId);
childLevel->init();
addChild(childLevel);
Q_EMIT endInsert();
#endif
}
void ForkLevel::activityRemoved(const QString &activityId)
{
#if KWIN_BUILD_ACTIVITIES
if (restriction() != ClientModel::ClientModel::ActivityRestriction) {
return;
}
for (int i = 0; i < m_children.length(); ++i) {
if (m_children.at(i)->activity() == activityId) {
Q_EMIT beginRemove(i, i, id());
delete m_children.takeAt(i);
Q_EMIT endRemove();
break;
}
}
#endif
}
int ForkLevel::count() const
{
return m_children.count();
}
void ForkLevel::addChild(AbstractLevel *child)
{
m_children.append(child);
connect(child, &AbstractLevel::beginInsert, this, &AbstractLevel::beginInsert);
connect(child, &AbstractLevel::beginRemove, this, &AbstractLevel::beginRemove);
connect(child, &AbstractLevel::endInsert, this, &AbstractLevel::endInsert);
connect(child, &AbstractLevel::endRemove, this, &AbstractLevel::endRemove);
}
void ForkLevel::setActivity(const QString &activity)
{
AbstractLevel::setActivity(activity);
for (QList<AbstractLevel *>::iterator it = m_children.begin(); it != m_children.end(); ++it) {
(*it)->setActivity(activity);
}
}
void ForkLevel::setScreen(uint screen)
{
AbstractLevel::setScreen(screen);
for (QList<AbstractLevel *>::iterator it = m_children.begin(); it != m_children.end(); ++it) {
(*it)->setScreen(screen);
}
}
void ForkLevel::setVirtualDesktop(uint virtualDesktop)
{
AbstractLevel::setVirtualDesktop(virtualDesktop);
for (QList<AbstractLevel *>::iterator it = m_children.begin(); it != m_children.end(); ++it) {
(*it)->setVirtualDesktop(virtualDesktop);
}
}
void ForkLevel::init()
{
for (QList<AbstractLevel *>::iterator it = m_children.begin(); it != m_children.end(); ++it) {
(*it)->init();
}
}
quint32 ForkLevel::idForRow(int row) const
{
if (row >= m_children.length()) {
return 0;
}
return m_children.at(row)->id();
}
const AbstractLevel *ForkLevel::levelForId(quint32 id) const
{
if (id == AbstractLevel::id()) {
return this;
}
for (QList<AbstractLevel *>::const_iterator it = m_children.constBegin(); it != m_children.constEnd(); ++it) {
if (const AbstractLevel *child = (*it)->levelForId(id)) {
return child;
}
}
// not found
return nullptr;
}
AbstractLevel *ForkLevel::parentForId(quint32 child) const
{
if (child == id()) {
return parentLevel();
}
for (QList<AbstractLevel *>::const_iterator it = m_children.constBegin(); it != m_children.constEnd(); ++it) {
if (AbstractLevel *parent = (*it)->parentForId(child)) {
return parent;
}
}
// not found
return nullptr;
}
int ForkLevel::rowForId(quint32 child) const
{
if (id() == child) {
return 0;
}
for (int i = 0; i < m_children.count(); ++i) {
if (m_children.at(i)->id() == child) {
return i;
}
}
// do recursion
for (QList<AbstractLevel *>::const_iterator it = m_children.constBegin(); it != m_children.constEnd(); ++it) {
int row = (*it)->rowForId(child);
if (row != -1) {
return row;
}
}
// not found
return -1;
}
Window *ForkLevel::clientForId(quint32 child) const
{
for (QList<AbstractLevel *>::const_iterator it = m_children.constBegin(); it != m_children.constEnd(); ++it) {
if (Window *client = (*it)->clientForId(child)) {
return client;
}
}
// not found
return nullptr;
}
ClientModel::ClientModel(QObject *parent)
: QAbstractItemModel(parent)
, m_root(nullptr)
, m_exclusions(NoExclusion)
{
}
ClientModel::~ClientModel()
{
}
void ClientModel::setLevels(QList<ClientModel::LevelRestriction> restrictions)
{
beginResetModel();
if (m_root) {
delete m_root;
}
m_root = AbstractLevel::create(restrictions, NoRestriction, this);
connect(m_root, &AbstractLevel::beginInsert, this, &ClientModel::levelBeginInsert);
connect(m_root, &AbstractLevel::beginRemove, this, &ClientModel::levelBeginRemove);
connect(m_root, &AbstractLevel::endInsert, this, &ClientModel::levelEndInsert);
connect(m_root, &AbstractLevel::endRemove, this, &ClientModel::levelEndRemove);
m_root->init();
endResetModel();
}
void ClientModel::setExclusions(ClientModel::Exclusions exclusions)
{
if (exclusions == m_exclusions) {
return;
}
m_exclusions = exclusions;
Q_EMIT exclusionsChanged();
}
QVariant ClientModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid() || index.column() != 0) {
return QVariant();
}
if (const AbstractLevel *level = getLevel(index)) {
LevelRestriction restriction = level->restriction();
if (restriction == ActivityRestriction && (role == Qt::DisplayRole || role == ActivityRole)) {
return level->activity();
} else if (restriction == VirtualDesktopRestriction && (role == Qt::DisplayRole || role == DesktopRole)) {
return level->virtualDesktop();
} else if (restriction == ScreenRestriction && (role == Qt::DisplayRole || role == ScreenRole)) {
return level->screen();
} else {
return QVariant();
}
}
if (role == Qt::DisplayRole || role == ClientRole) {
if (Window *client = m_root->clientForId(index.internalId())) {
return QVariant::fromValue(client);
}
}
return QVariant();
}
int ClientModel::columnCount(const QModelIndex &parent) const
{
return 1;
}
int ClientModel::rowCount(const QModelIndex &parent) const
{
if (!m_root) {
return 0;
}
if (!parent.isValid()) {
return m_root->count();
}
if (const AbstractLevel *level = getLevel(parent)) {
if (level->id() != parent.internalId()) {
// not a real level - no children
return 0;
}
return level->count();
}
return 0;
}
QHash<int, QByteArray> ClientModel::roleNames() const
{
return {
{Qt::DisplayRole, QByteArrayLiteral("display")},
{ClientRole, QByteArrayLiteral("client")},
{ScreenRole, QByteArrayLiteral("screen")},
{DesktopRole, QByteArrayLiteral("desktop")},
{ActivityRole, QByteArrayLiteral("activity")},
};
}
QModelIndex ClientModel::parent(const QModelIndex &child) const
{
if (!child.isValid() || child.column() != 0) {
return QModelIndex();
}
return parentForId(child.internalId());
}
QModelIndex ClientModel::parentForId(quint32 childId) const
{
if (childId == m_root->id()) {
// asking for parent of our toplevel
return QModelIndex();
}
if (AbstractLevel *parentLevel = m_root->parentForId(childId)) {
if (parentLevel == m_root) {
return QModelIndex();
}
const int row = m_root->rowForId(parentLevel->id());
if (row == -1) {
// error
return QModelIndex();
}
return createIndex(row, 0, parentLevel->id());
}
return QModelIndex();
}
QModelIndex ClientModel::index(int row, int column, const QModelIndex &parent) const
{
if (column != 0 || row < 0 || !m_root) {
return QModelIndex();
}
if (!parent.isValid()) {
if (row >= rowCount()) {
return QModelIndex();
}
return createIndex(row, 0, m_root->idForRow(row));
}
const AbstractLevel *parentLevel = getLevel(parent);
if (!parentLevel) {
return QModelIndex();
}
if (row >= parentLevel->count()) {
return QModelIndex();
}
const quint32 id = parentLevel->idForRow(row);
if (id == 0) {
return QModelIndex();
}
return createIndex(row, column, id);
}
const AbstractLevel *ClientModel::getLevel(const QModelIndex &index) const
{
if (!index.isValid()) {
return m_root;
}
return m_root->levelForId(index.internalId());
}
void ClientModel::levelBeginInsert(int rowStart, int rowEnd, quint32 id)
{
const int row = m_root->rowForId(id);
QModelIndex parent;
if (row != -1) {
parent = createIndex(row, 0, id);
}
beginInsertRows(parent, rowStart, rowEnd);
}
void ClientModel::levelBeginRemove(int rowStart, int rowEnd, quint32 id)
{
const int row = m_root->rowForId(id);
QModelIndex parent;
if (row != -1) {
parent = createIndex(row, 0, id);
}
beginRemoveRows(parent, rowStart, rowEnd);
}
void ClientModel::levelEndInsert()
{
endInsertRows();
}
void ClientModel::levelEndRemove()
{
endRemoveRows();
}
#define CLIENT_MODEL_WRAPPER(name, levels) \
name::name(QObject *parent) \
: ClientModel(parent) \
{ \
setLevels(levels); \
} \
name::~name() \
{ \
}
CLIENT_MODEL_WRAPPER(SimpleClientModel, QList<LevelRestriction>())
CLIENT_MODEL_WRAPPER(ClientModelByScreen, QList<LevelRestriction>() << ScreenRestriction)
CLIENT_MODEL_WRAPPER(ClientModelByScreenAndDesktop, QList<LevelRestriction>() << ScreenRestriction << VirtualDesktopRestriction)
CLIENT_MODEL_WRAPPER(ClientModelByScreenAndActivity, QList<LevelRestriction>() << ScreenRestriction << ActivityRestriction)
#undef CLIENT_MODEL_WRAPPER
ClientFilterModel::ClientFilterModel(QObject *parent)
: QSortFilterProxyModel(parent)
, m_clientModel(nullptr)
{
}
ClientFilterModel::~ClientFilterModel()
{
}
void ClientFilterModel::setClientModel(ClientModel *clientModel)
{
if (clientModel == m_clientModel) {
return;
}
m_clientModel = clientModel;
setSourceModel(m_clientModel);
Q_EMIT clientModelChanged();
}
void ClientFilterModel::setFilter(const QString &filter)
{
if (filter == m_filter) {
return;
}
m_filter = filter;
Q_EMIT filterChanged();
invalidateFilter();
}
bool ClientFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
{
if (!m_clientModel) {
return false;
}
if (m_filter.isEmpty()) {
return true;
}
QModelIndex index = m_clientModel->index(sourceRow, 0, sourceParent);
if (!index.isValid()) {
return false;
}
QVariant data = index.data();
if (!data.isValid()) {
// an invalid QVariant is valid data
return true;
}
// TODO: introduce a type as a data role and properly check, this seems dangerous
if (data.type() == QVariant::Int || data.type() == QVariant::UInt || data.type() == QVariant::String) {
// we do not filter out screen, desktop and activity
return true;
}
Window *client = qvariant_cast<KWin::Window *>(data);
if (!client) {
return false;
}
if (client->caption().contains(m_filter, Qt::CaseInsensitive)) {
return true;
}
if (client->windowRole().contains(m_filter, Qt::CaseInsensitive)) {
return true;
}
if (client->resourceName().contains(m_filter, Qt::CaseInsensitive)) {
return true;
}
if (client->resourceClass().contains(m_filter, Qt::CaseInsensitive)) {
return true;
}
return false;
}
} // namespace KWin

View file

@ -1,369 +0,0 @@
/*
KWin - the KDE window manager
This file is part of the KDE project.
SPDX-FileCopyrightText: 2013 Martin Gräßlin <mgraesslin@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
#include <QAbstractItemModel>
#include <QList>
#include <QSortFilterProxyModel>
namespace KWin
{
class Window;
class Client;
namespace ScriptingModels::V2
{
class AbstractLevel;
class ClientModel : public QAbstractItemModel
{
Q_OBJECT
Q_ENUMS(Exclude)
Q_PROPERTY(Exclusions exclusions READ exclusions WRITE setExclusions NOTIFY exclusionsChanged)
public:
enum Exclusion {
NoExclusion = 0,
// window types
DesktopWindowsExclusion = 1 << 0,
DockWindowsExclusion = 1 << 1,
UtilityWindowsExclusion = 1 << 2,
SpecialWindowsExclusion = 1 << 3,
// windows with flags
SkipTaskbarExclusion = 1 << 4,
SkipPagerExclusion = 1 << 5,
SwitchSwitcherExclusion = 1 << 6,
// based on state
OtherDesktopsExclusion = 1 << 7,
OtherActivitiesExclusion = 1 << 8,
MinimizedExclusion = 1 << 9,
NonSelectedWindowTabExclusion = 1 << 10,
NotAcceptingFocusExclusion = 1 << 11
};
Q_DECLARE_FLAGS(Exclusions, Exclusion)
Q_FLAGS(Exclusions)
Q_ENUM(Exclusion)
enum LevelRestriction {
NoRestriction = 0,
VirtualDesktopRestriction = 1 << 0,
ScreenRestriction = 1 << 1,
ActivityRestriction = 1 << 2
};
Q_DECLARE_FLAGS(LevelRestrictions, LevelRestriction)
Q_FLAGS(LevelRestrictions)
Q_ENUM(LevelRestriction)
explicit ClientModel(QObject *parent);
~ClientModel() override;
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
QModelIndex parent(const QModelIndex &child) const override;
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
QHash<int, QByteArray> roleNames() const override;
void setExclusions(ClientModel::Exclusions exclusions);
Exclusions exclusions() const;
Q_SIGNALS:
void exclusionsChanged();
private Q_SLOTS:
void levelBeginInsert(int rowStart, int rowEnd, quint32 parentId);
void levelEndInsert();
void levelBeginRemove(int rowStart, int rowEnd, quint32 parentId);
void levelEndRemove();
protected:
enum ClientModelRoles {
ClientRole = Qt::UserRole,
ScreenRole,
DesktopRole,
ActivityRole
};
void setLevels(QList<LevelRestriction> restrictions);
private:
QModelIndex parentForId(quint32 childId) const;
const AbstractLevel *getLevel(const QModelIndex &index) const;
AbstractLevel *m_root;
Exclusions m_exclusions;
};
/**
* @brief The data structure of the Model.
*
* The model is implemented as a Tree consisting of AbstractLevels as the levels of the tree.
* A non leaf level is represented by the inheriting class ForkLevel, the last level above a
* leaf is represented by the inheriting class ClientLevel, which contains the Clients - each
* Client is one leaf.
*
* In case the tree would only consist of Clients - leafs - it has always one ClientLevel as the root
* of the tree.
*
* The number of levels in the tree is controlled by the LevelRestrictions. For each existing
* LevelRestriction a new Level is created, if there are no more restrictions a ClientLevel is created.
*
* To build up the tree the static factory method @ref create has to be used. It will recursively
* build up the tree. After the tree has been build up use @ref init to initialize the tree which
* will add the Clients to the ClientLevel.
*
* Each element of the tree has a unique id which can be used by the QAbstractItemModel as the
* internal id for its QModelIndex. Note: the ids have no ordering, if trying to get a specific element
* the tree performs a depth-first search.
*/
class AbstractLevel : public QObject
{
Q_OBJECT
public:
~AbstractLevel() override;
virtual int count() const = 0;
virtual void init() = 0;
virtual quint32 idForRow(int row) const = 0;
uint screen() const;
uint virtualDesktop() const;
const QString &activity() const;
ClientModel::LevelRestrictions restrictions() const;
void setRestrictions(ClientModel::LevelRestrictions restrictions);
ClientModel::LevelRestriction restriction() const;
void setRestriction(ClientModel::LevelRestriction restriction);
quint32 id() const;
AbstractLevel *parentLevel() const;
virtual const AbstractLevel *levelForId(quint32 id) const = 0;
virtual AbstractLevel *parentForId(quint32 child) const = 0;
virtual int rowForId(quint32 child) const = 0;
virtual Window *clientForId(quint32 child) const = 0;
virtual void setScreen(uint screen);
virtual void setVirtualDesktop(uint virtualDesktop);
virtual void setActivity(const QString &activity);
static AbstractLevel *create(const QList<ClientModel::LevelRestriction> &restrictions, ClientModel::LevelRestrictions parentRestrictions, ClientModel *model, AbstractLevel *parent = nullptr);
Q_SIGNALS:
void beginInsert(int rowStart, int rowEnd, quint32 parentId);
void endInsert();
void beginRemove(int rowStart, int rowEnd, quint32 parentId);
void endRemove();
protected:
AbstractLevel(ClientModel *model, AbstractLevel *parent);
ClientModel *model() const;
private:
ClientModel *m_model;
AbstractLevel *m_parent;
uint m_screen;
uint m_virtualDesktop;
QString m_activity;
ClientModel::LevelRestriction m_restriction;
ClientModel::LevelRestrictions m_restrictions;
quint32 m_id;
};
class ForkLevel : public AbstractLevel
{
Q_OBJECT
public:
ForkLevel(const QList<ClientModel::LevelRestriction> &childRestrictions, ClientModel *model, AbstractLevel *parent);
~ForkLevel() override;
int count() const override;
void init() override;
quint32 idForRow(int row) const override;
void addChild(AbstractLevel *child);
void setScreen(uint screen) override;
void setVirtualDesktop(uint virtualDesktop) override;
void setActivity(const QString &activity) override;
const AbstractLevel *levelForId(quint32 id) const override;
AbstractLevel *parentForId(quint32 child) const override;
int rowForId(quint32 child) const override;
Window *clientForId(quint32 child) const override;
private Q_SLOTS:
void desktopCountChanged(uint previousCount, uint newCount);
void activityAdded(const QString &id);
void activityRemoved(const QString &id);
void outputAdded();
void outputRemoved();
private:
QList<AbstractLevel *> m_children;
QList<ClientModel::LevelRestriction> m_childRestrictions;
};
/**
* @brief The actual leafs of the model's tree containing the Client's in this branch of the tree.
*
* This class groups all the Clients of one branch of the tree and takes care of updating the tree
* when a Client changes its state in a way that it should be excluded/included or gets added or
* removed.
*
* The Clients in this group are not sorted in any particular way. It's a simple list which only
* gets added to. If some sorting should be applied, use a QSortFilterProxyModel.
*/
class ClientLevel : public AbstractLevel
{
Q_OBJECT
public:
explicit ClientLevel(ClientModel *model, AbstractLevel *parent);
~ClientLevel() override;
void init() override;
int count() const override;
quint32 idForRow(int row) const override;
bool containsId(quint32 id) const;
int rowForId(quint32 row) const override;
Window *clientForId(quint32 child) const override;
const AbstractLevel *levelForId(quint32 id) const override;
AbstractLevel *parentForId(quint32 child) const override;
public Q_SLOTS:
void clientAdded(KWin::Window *client);
void clientRemoved(KWin::Window *client);
private Q_SLOTS:
// uses sender()
void reInit();
private:
void checkClient(KWin::Window *client);
void setupClientConnections(Window *client);
void addClient(Window *client);
void removeClient(Window *client);
bool shouldAdd(Window *client) const;
bool exclude(Window *client) const;
bool containsClient(Window *client) const;
QMap<quint32, Window *> m_clients;
};
class SimpleClientModel : public ClientModel
{
Q_OBJECT
public:
SimpleClientModel(QObject *parent = nullptr);
~SimpleClientModel() override;
};
class ClientModelByScreen : public ClientModel
{
Q_OBJECT
public:
ClientModelByScreen(QObject *parent = nullptr);
~ClientModelByScreen() override;
};
class ClientModelByScreenAndDesktop : public ClientModel
{
Q_OBJECT
public:
ClientModelByScreenAndDesktop(QObject *parent = nullptr);
~ClientModelByScreenAndDesktop() override;
};
class ClientModelByScreenAndActivity : public ClientModel
{
Q_OBJECT
public:
ClientModelByScreenAndActivity(QObject *parent = nullptr);
~ClientModelByScreenAndActivity() override;
};
/**
* @brief Custom QSortFilterProxyModel to filter on Client caption, role and class.
*/
class ClientFilterModel : public QSortFilterProxyModel
{
Q_OBJECT
Q_PROPERTY(KWin::ScriptingModels::V2::ClientModel *clientModel READ clientModel WRITE setClientModel NOTIFY clientModelChanged)
Q_PROPERTY(QString filter READ filter WRITE setFilter NOTIFY filterChanged)
public:
ClientFilterModel(QObject *parent = nullptr);
~ClientFilterModel() override;
ClientModel *clientModel() const;
const QString &filter() const;
public Q_SLOTS:
void setClientModel(ClientModel *clientModel);
void setFilter(const QString &filter);
protected:
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override;
Q_SIGNALS:
void clientModelChanged();
void filterChanged();
private:
ClientModel *m_clientModel;
QString m_filter;
};
inline int ClientLevel::count() const
{
return m_clients.count();
}
inline const QString &AbstractLevel::activity() const
{
return m_activity;
}
inline AbstractLevel *AbstractLevel::parentLevel() const
{
return m_parent;
}
inline ClientModel *AbstractLevel::model() const
{
return m_model;
}
inline uint AbstractLevel::screen() const
{
return m_screen;
}
inline uint AbstractLevel::virtualDesktop() const
{
return m_virtualDesktop;
}
inline ClientModel::LevelRestriction AbstractLevel::restriction() const
{
return m_restriction;
}
inline ClientModel::LevelRestrictions AbstractLevel::restrictions() const
{
return m_restrictions;
}
inline quint32 AbstractLevel::id() const
{
return m_id;
}
inline ClientModel::Exclusions ClientModel::exclusions() const
{
return m_exclusions;
}
inline ClientModel *ClientFilterModel::clientModel() const
{
return m_clientModel;
}
inline const QString &ClientFilterModel::filter() const
{
return m_filter;
}
} // namespace Scripting
} // namespace KWin
Q_DECLARE_OPERATORS_FOR_FLAGS(KWin::ScriptingModels::V2::ClientModel::Exclusions)
Q_DECLARE_OPERATORS_FOR_FLAGS(KWin::ScriptingModels::V2::ClientModel::LevelRestrictions)

View file

@ -1,41 +0,0 @@
/*
SPDX-FileCopyrightText: 2022 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
import QtQuick 2.12
import org.kde.kwin 2.0 as KWinComponents
Item {
id: root
property int desktop: 1
// These unused properties exist for compatibility reasons.
property real brightness: 1
property real saturation: 1
property Item clipTo: null
Item {
id: container
anchors.centerIn: parent
width: workspace.virtualScreenSize.width
height: workspace.virtualScreenSize.height
scale: Math.min(parent.width / container.width, parent.height / container.height)
Repeater {
model: KWinComponents.ClientModel {
exclusions: KWinComponents.ClientModel.OtherActivitiesExclusion
}
KWinComponents.ThumbnailItem {
client: model.client
x: model.client.x
y: model.client.y
z: model.client.stackingOrder
visible: (model.client.desktop === -1 || model.client.desktop === root.desktop) && !model.client.minimized
}
}
}
}

View file

@ -1,7 +0,0 @@
# SPDX-FileCopyrightText: 2022 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
#
# SPDX-License-Identifier: CC0-1.0
module org.kde.kwin
DesktopThumbnailItem 2.0 DesktopThumbnailItem.qml

View file

@ -309,7 +309,6 @@ void TabBoxHandlerPrivate::show()
{
#ifndef KWIN_UNIT_TEST
if (!m_qmlContext) {
qmlRegisterType<SwitcherItem>("org.kde.kwin", 2, 0, "Switcher");
qmlRegisterType<SwitcherItem>("org.kde.kwin", 3, 0, "TabBoxSwitcher");
m_qmlContext.reset(new QQmlContext(Scripting::self()->qmlEngine()));
}