kwin/src/wayland/plasmawindowmanagement_interface.cpp
2021-05-13 11:33:08 +02:00

1023 lines
33 KiB
C++

/*
SPDX-FileCopyrightText: 2015 Martin Gräßlin <mgraesslin@kde.org>
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
*/
#include "plasmawindowmanagement_interface.h"
#include "display.h"
#include "logging.h"
#include "surface_interface.h"
#include "plasmavirtualdesktop_interface.h"
#include <QtConcurrentRun>
#include <QFile>
#include <QIcon>
#include <QList>
#include <QVector>
#include <QRect>
#include <QHash>
#include <QUuid>
#include <qwayland-server-plasma-window-management.h>
namespace KWaylandServer
{
static const quint32 s_version = 14;
class PlasmaWindowManagementInterfacePrivate : public QtWaylandServer::org_kde_plasma_window_management
{
public:
PlasmaWindowManagementInterfacePrivate(PlasmaWindowManagementInterface *_q, Display *display);
void sendShowingDesktopState();
void sendShowingDesktopState(wl_resource *resource);
void sendStackingOrderChanged();
void sendStackingOrderChanged(wl_resource *resource);
void sendStackingOrderUuidsChanged();
void sendStackingOrderUuidsChanged(wl_resource *resource);
PlasmaWindowManagementInterface::ShowingDesktopState state = PlasmaWindowManagementInterface::ShowingDesktopState::Disabled;
QList<PlasmaWindowInterface*> windows;
QPointer<PlasmaVirtualDesktopManagementInterface> plasmaVirtualDesktopManagementInterface = nullptr;
quint32 windowIdCounter = 0;
QVector<quint32> stackingOrder;
QVector<QString> stackingOrderUuids;
PlasmaWindowManagementInterface *q;
protected:
void org_kde_plasma_window_management_bind_resource(Resource *resource) override;
void org_kde_plasma_window_management_show_desktop(Resource *resource, uint32_t state) override;
void org_kde_plasma_window_management_get_window(Resource *resource, uint32_t id, uint32_t internal_window_id) override;
void org_kde_plasma_window_management_get_window_by_uuid(Resource *resource, uint32_t id, const QString &internal_window_uuid) override;
};
class PlasmaWindowInterfacePrivate : public QtWaylandServer::org_kde_plasma_window
{
public:
PlasmaWindowInterfacePrivate(PlasmaWindowManagementInterface *wm, PlasmaWindowInterface *q);
~PlasmaWindowInterfacePrivate();
void setTitle(const QString &title);
void setAppId(const QString &appId);
void setPid(quint32 pid);
void setThemedIconName(const QString &iconName);
void setIcon(const QIcon &icon);
void setVirtualDesktop(quint32 desktop);
void unmap();
void setState(org_kde_plasma_window_management_state flag, bool set);
void setParentWindow(PlasmaWindowInterface *parent);
void setGeometry(const QRect &geometry);
void setApplicationMenuPaths(const QString &service, const QString &object);
wl_resource *resourceForParent(PlasmaWindowInterface *parent, Resource *child) const;
quint32 windowId = 0;
QHash<SurfaceInterface*, QRect> minimizedGeometries;
PlasmaWindowManagementInterface *wm;
bool unmapped = false;
PlasmaWindowInterface *parentWindow = nullptr;
QMetaObject::Connection parentWindowDestroyConnection;
QStringList plasmaVirtualDesktops;
QStringList plasmaActivities;
QRect geometry;
PlasmaWindowInterface *q;
QString m_title;
QString m_appId;
quint32 m_pid = 0;
QString m_themedIconName;
QString m_appServiceName;
QString m_appObjectPath;
QIcon m_icon;
quint32 m_virtualDesktop = 0;
quint32 m_state = 0;
QString uuid;
protected:
void org_kde_plasma_window_bind_resource(Resource *resource) override;
void org_kde_plasma_window_set_state(Resource *resource, uint32_t flags, uint32_t state) override;
void org_kde_plasma_window_set_virtual_desktop(Resource *resource, uint32_t number) override;
void org_kde_plasma_window_set_minimized_geometry(Resource *resource, wl_resource *panel, uint32_t x, uint32_t y, uint32_t width, uint32_t height) override;
void org_kde_plasma_window_unset_minimized_geometry(Resource *resource, wl_resource *panel) override;
void org_kde_plasma_window_close(Resource *resource) override;
void org_kde_plasma_window_request_move(Resource *resource) override;
void org_kde_plasma_window_request_resize(Resource *resource) override;
void org_kde_plasma_window_destroy(Resource *resource) override;
void org_kde_plasma_window_get_icon(Resource *resource, int32_t fd) override;
void org_kde_plasma_window_request_enter_virtual_desktop(Resource *resource, const QString &id) override;
void org_kde_plasma_window_request_enter_new_virtual_desktop(Resource *resource) override;
void org_kde_plasma_window_request_leave_virtual_desktop(Resource *resource, const QString &id) override;
void org_kde_plasma_window_request_enter_activity(Resource *resource, const QString &id) override;
void org_kde_plasma_window_request_leave_activity(Resource *resource, const QString &id) override;
};
PlasmaWindowManagementInterfacePrivate::PlasmaWindowManagementInterfacePrivate(PlasmaWindowManagementInterface *_q, Display *display)
: QtWaylandServer::org_kde_plasma_window_management(*display, s_version)
, q(_q)
{
}
void PlasmaWindowManagementInterfacePrivate::sendShowingDesktopState()
{
const auto clientResources = resourceMap();
for (auto resource : clientResources) {
sendShowingDesktopState(resource->handle);
}
}
void PlasmaWindowManagementInterfacePrivate::sendShowingDesktopState(wl_resource *r)
{
uint32_t s = 0;
switch (state) {
case PlasmaWindowManagementInterface::ShowingDesktopState::Enabled:
s = QtWaylandServer::org_kde_plasma_window_management::show_desktop_enabled;
break;
case PlasmaWindowManagementInterface::ShowingDesktopState::Disabled:
s = QtWaylandServer::org_kde_plasma_window_management::show_desktop_disabled;
break;
default:
Q_UNREACHABLE();
break;
}
send_show_desktop_changed(r, s);
}
void PlasmaWindowManagementInterfacePrivate::sendStackingOrderChanged()
{
const auto clientResources = resourceMap();
for (auto resource : clientResources) {
sendStackingOrderChanged(resource->handle);
}
}
void PlasmaWindowManagementInterfacePrivate::sendStackingOrderChanged(wl_resource *r)
{
if (wl_resource_get_version(r) < ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STACKING_ORDER_CHANGED_SINCE_VERSION) {
return;
}
send_stacking_order_changed(r, QByteArray::fromRawData(reinterpret_cast<const char*>(stackingOrder.constData()), sizeof(uint32_t) * stackingOrder.size()));
}
void PlasmaWindowManagementInterfacePrivate::sendStackingOrderUuidsChanged()
{
const auto clientResources = resourceMap();
for (auto resource : clientResources) {
sendStackingOrderUuidsChanged(resource->handle);
}
}
void PlasmaWindowManagementInterfacePrivate::sendStackingOrderUuidsChanged(wl_resource *r)
{
if (wl_resource_get_version(r) < ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STACKING_ORDER_UUID_CHANGED_SINCE_VERSION) {
return;
}
QString uuids;
for (const auto &uuid : qAsConst(stackingOrderUuids)) {
uuids += uuid;
uuids += QLatin1Char(';');
}
// Remove the trailing ';', on the receiving side this is interpreted as an empty uuid.
if (stackingOrderUuids.size() > 0) {
uuids.remove(uuids.length() - 1, 1);
}
send_stacking_order_uuid_changed(r, uuids);
}
void PlasmaWindowManagementInterfacePrivate::org_kde_plasma_window_management_bind_resource(Resource *resource)
{
for (auto window : windows) {
if (resource->version() >= ORG_KDE_PLASMA_WINDOW_MANAGEMENT_WINDOW_WITH_UUID_SINCE_VERSION) {
send_window_with_uuid(resource->handle, window->d->windowId, window->d->uuid);
} else {
send_window(resource->handle, window->d->windowId);
}
}
sendStackingOrderChanged(resource->handle);
sendStackingOrderUuidsChanged(resource->handle);
}
void PlasmaWindowManagementInterfacePrivate::org_kde_plasma_window_management_show_desktop(Resource *resource, uint32_t state)
{
Q_UNUSED(resource)
PlasmaWindowManagementInterface::ShowingDesktopState s = PlasmaWindowManagementInterface::ShowingDesktopState::Disabled;
switch (state) {
case ORG_KDE_PLASMA_WINDOW_MANAGEMENT_SHOW_DESKTOP_ENABLED:
s = PlasmaWindowManagementInterface::ShowingDesktopState::Enabled;
break;
case ORG_KDE_PLASMA_WINDOW_MANAGEMENT_SHOW_DESKTOP_DISABLED:
default:
s = PlasmaWindowManagementInterface::ShowingDesktopState::Disabled;
break;
}
Q_EMIT q->requestChangeShowingDesktop(s);
}
void PlasmaWindowManagementInterfacePrivate::org_kde_plasma_window_management_get_window(Resource *resource, uint32_t id, uint32_t internal_window_id)
{
for (auto window : windows) {
if (window->d->windowId == internal_window_id) {
window->d->add(resource->client(), id, resource->version());
return;
}
}
// create a temp window just for the resource, bind then immediately delete it, sending an unmap event
PlasmaWindowInterface window(q, q);
window.d->add(resource->client(), id, resource->version());
}
void PlasmaWindowManagementInterfacePrivate::org_kde_plasma_window_management_get_window_by_uuid(Resource *resource, uint32_t id, const QString &internal_window_uuid)
{
auto it = std::find_if(windows.constBegin(), windows.constEnd(),
[internal_window_uuid] (PlasmaWindowInterface *window) {
return window->d->uuid == internal_window_uuid;
}
);
if (it == windows.constEnd()) {
qCWarning(KWAYLAND_SERVER) << "Could not find window with uuid" << internal_window_uuid;
// create a temp window just for the resource, bind then immediately delete it, sending an unmap event
PlasmaWindowInterface window(q, q);
window.d->add(resource->client(), id, resource->version());
return;
}
(*it)->d->add(resource->client(), id, resource->version());
}
PlasmaWindowManagementInterface::PlasmaWindowManagementInterface(Display *display, QObject *parent)
: QObject(parent)
, d(new PlasmaWindowManagementInterfacePrivate(this, display))
{
}
PlasmaWindowManagementInterface::~PlasmaWindowManagementInterface() = default;
void PlasmaWindowManagementInterface::setShowingDesktopState(PlasmaWindowManagementInterface::ShowingDesktopState state)
{
if (d->state == state) {
return;
}
d->state = state;
d->sendShowingDesktopState();
}
PlasmaWindowInterface *PlasmaWindowManagementInterface::createWindow(QObject *parent, const QUuid &uuid)
{
PlasmaWindowInterface *window = new PlasmaWindowInterface(this, parent);
window->d->uuid = uuid.toString();
window->d->windowId = ++d->windowIdCounter; //NOTE the window id is deprecated
const auto clientResources = d->resourceMap();
for (auto resource : clientResources) {
if (resource->version() >= ORG_KDE_PLASMA_WINDOW_MANAGEMENT_WINDOW_WITH_UUID_SINCE_VERSION) {
d->send_window_with_uuid(resource->handle, window->d->windowId, window->d->uuid);
} else {
d->send_window(resource->handle, window->d->windowId);
}
}
d->windows << window;
connect(window, &QObject::destroyed, this,
[this, window] {
d->windows.removeAll(window);
}
);
return window;
}
QList<PlasmaWindowInterface*> PlasmaWindowManagementInterface::windows() const
{
return d->windows;
}
void PlasmaWindowManagementInterface::setStackingOrder(const QVector<quint32> &stackingOrder)
{
if (d->stackingOrder == stackingOrder) {
return;
}
d->stackingOrder = stackingOrder;
d->sendStackingOrderChanged();
}
void PlasmaWindowManagementInterface::setStackingOrderUuids(const QVector<QString> &stackingOrderUuids)
{
if (d->stackingOrderUuids == stackingOrderUuids) {
return;
}
d->stackingOrderUuids = stackingOrderUuids;
d->sendStackingOrderUuidsChanged();
}
void PlasmaWindowManagementInterface::setPlasmaVirtualDesktopManagementInterface(PlasmaVirtualDesktopManagementInterface *manager)
{
if (d->plasmaVirtualDesktopManagementInterface == manager) {
return;
}
d->plasmaVirtualDesktopManagementInterface = manager;
}
PlasmaVirtualDesktopManagementInterface *PlasmaWindowManagementInterface::plasmaVirtualDesktopManagementInterface() const
{
return d->plasmaVirtualDesktopManagementInterface;
}
//////PlasmaWindow
PlasmaWindowInterfacePrivate::PlasmaWindowInterfacePrivate(PlasmaWindowManagementInterface *wm, PlasmaWindowInterface *q)
: QtWaylandServer::org_kde_plasma_window()
, wm(wm)
, q(q)
{
}
PlasmaWindowInterfacePrivate::~PlasmaWindowInterfacePrivate()
{
unmap();
}
void PlasmaWindowInterfacePrivate::org_kde_plasma_window_destroy(Resource *resource)
{
wl_resource_destroy(resource->handle);
}
void PlasmaWindowInterfacePrivate::org_kde_plasma_window_bind_resource(Resource *resource)
{
send_virtual_desktop_changed(resource->handle, m_virtualDesktop);
for (const auto &desk : plasmaVirtualDesktops) {
send_virtual_desktop_entered(resource->handle, desk);
}
for (const auto &activity : plasmaActivities) {
if (resource->version() >= ORG_KDE_PLASMA_WINDOW_ACTIVITY_ENTERED_SINCE_VERSION) {
send_activity_entered(resource->handle, activity);
}
}
if (!m_appId.isEmpty()) {
send_app_id_changed(resource->handle, m_appId);
}
if (m_pid != 0) {
send_pid_changed(resource->handle, m_pid);
}
if (!m_title.isEmpty()) {
send_title_changed(resource->handle, m_title);
}
if (!m_appObjectPath.isEmpty() || !m_appServiceName.isEmpty()) {
send_application_menu(resource->handle, m_appServiceName, m_appObjectPath);
}
send_state_changed(resource->handle, m_state);
if (!m_themedIconName.isEmpty()) {
send_themed_icon_name_changed(resource->handle, m_themedIconName);
} else if (!m_icon.isNull()) {
if (resource->version() >= ORG_KDE_PLASMA_WINDOW_ICON_CHANGED_SINCE_VERSION) {
send_icon_changed(resource->handle);
}
}
send_parent_window(resource->handle, resourceForParent(parentWindow, resource));
if (geometry.isValid() && resource->version() >= ORG_KDE_PLASMA_WINDOW_GEOMETRY_SINCE_VERSION) {
send_geometry(resource->handle, geometry.x(), geometry.y(), geometry.width(), geometry.height());
}
if (resource->version() >= ORG_KDE_PLASMA_WINDOW_INITIAL_STATE_SINCE_VERSION) {
send_initial_state(resource->handle);
}
}
void PlasmaWindowInterfacePrivate::setAppId(const QString &appId)
{
if (m_appId == appId) {
return;
}
m_appId = appId;
const auto clientResources = resourceMap();
for (auto resource : clientResources) {
send_app_id_changed(resource->handle,m_appId);
}
}
void PlasmaWindowInterfacePrivate::setPid(quint32 pid)
{
if (m_pid == pid) {
return;
}
m_pid = pid;
const auto clientResources = resourceMap();
for (auto resource : clientResources) {
send_pid_changed(resource->handle,pid);
}
}
void PlasmaWindowInterfacePrivate::setThemedIconName(const QString &iconName)
{
if (m_themedIconName == iconName) {
return;
}
m_themedIconName = iconName;
const auto clientResources = resourceMap();
for (auto resource : clientResources) {
send_themed_icon_name_changed(resource->handle, m_themedIconName);
}
}
void PlasmaWindowInterfacePrivate::setIcon(const QIcon &icon)
{
m_icon = icon;
setThemedIconName(m_icon.name());
const auto clientResources = resourceMap();
for (auto resource : clientResources) {
if (resource->version() >= ORG_KDE_PLASMA_WINDOW_ICON_CHANGED_SINCE_VERSION) {
send_icon_changed(resource->handle);
}
}
}
void PlasmaWindowInterfacePrivate::org_kde_plasma_window_get_icon(Resource *resource, int32_t fd)
{
Q_UNUSED(resource)
QtConcurrent::run(
[fd] (const QIcon &icon) {
QFile file;
file.open(fd, QIODevice::WriteOnly, QFileDevice::AutoCloseHandle);
QDataStream ds(&file);
ds << icon;
file.close();
}, m_icon
);
}
void PlasmaWindowInterfacePrivate::org_kde_plasma_window_request_enter_virtual_desktop(Resource *resource, const QString &id)
{
Q_UNUSED(resource)
Q_EMIT q->enterPlasmaVirtualDesktopRequested(id);
}
void PlasmaWindowInterfacePrivate::org_kde_plasma_window_request_enter_new_virtual_desktop(Resource *resource)
{
Q_UNUSED(resource)
Q_EMIT q->enterNewPlasmaVirtualDesktopRequested();
}
void PlasmaWindowInterfacePrivate::org_kde_plasma_window_request_leave_virtual_desktop(Resource *resource, const QString &id)
{
Q_UNUSED(resource)
Q_EMIT q->leavePlasmaVirtualDesktopRequested(id);
}
void PlasmaWindowInterfacePrivate::org_kde_plasma_window_request_enter_activity(Resource *resource, const QString &id)
{
Q_UNUSED(resource)
Q_EMIT q->enterPlasmaActivityRequested(id);
}
void PlasmaWindowInterfacePrivate::org_kde_plasma_window_request_leave_activity(Resource *resource, const QString &id)
{
Q_UNUSED(resource)
Q_EMIT q->leavePlasmaActivityRequested(id);
}
void PlasmaWindowInterfacePrivate::setTitle(const QString &title)
{
if (m_title == title) {
return;
}
m_title = title;
const auto clientResources = resourceMap();
for (auto resource : clientResources) {
send_title_changed(resource->handle, m_title);
}
}
void PlasmaWindowInterfacePrivate::setVirtualDesktop(quint32 desktop)
{
if (m_virtualDesktop == desktop) {
return;
}
m_virtualDesktop = desktop;
const auto clientResources = resourceMap();
for (auto resource : clientResources) {
send_virtual_desktop_changed(resource->handle, m_virtualDesktop);
}
}
void PlasmaWindowInterfacePrivate::unmap()
{
if (unmapped) {
return;
}
unmapped = true;
const auto clientResources = resourceMap();
for (auto resource : clientResources) {
send_unmapped(resource->handle);
}
}
void PlasmaWindowInterfacePrivate::setState(org_kde_plasma_window_management_state flag, bool set)
{
quint32 newState = m_state;
if (set) {
newState |= flag;
} else {
newState &= ~flag;
}
if (newState == m_state) {
return;
}
m_state = newState;
const auto clientResources = resourceMap();
for (auto resource : clientResources) {
send_state_changed(resource->handle, m_state);
}
}
wl_resource *PlasmaWindowInterfacePrivate::resourceForParent(PlasmaWindowInterface *parent, Resource *child) const
{
if (!parent) {
return nullptr;
}
const auto parentResource = parent->d->resourceMap();
for (auto resource : parentResource) {
if (child->client() == resource->client()) {
return resource->handle;
}
}
return nullptr;
}
void PlasmaWindowInterfacePrivate::setParentWindow(PlasmaWindowInterface *window)
{
if (parentWindow == window) {
return;
}
QObject::disconnect(parentWindowDestroyConnection);
parentWindowDestroyConnection = QMetaObject::Connection();
parentWindow = window;
if (parentWindow) {
parentWindowDestroyConnection = QObject::connect(window, &QObject::destroyed, q,
[this] {
parentWindow = nullptr;
parentWindowDestroyConnection = QMetaObject::Connection();
const auto clientResources = resourceMap();
for (auto resource : clientResources) {
send_parent_window(resource->handle, nullptr);
}
}
);
}
const auto clientResources = resourceMap();
for (auto resource : clientResources) {
send_parent_window(resource->handle, resourceForParent(window, resource));
}
}
void PlasmaWindowInterfacePrivate::setGeometry(const QRect &geo)
{
if (geometry == geo) {
return;
}
geometry = geo;
if (!geometry.isValid()) {
return;
}
const auto clientResources = resourceMap();
for (auto resource : clientResources) {
if (resource->version() < ORG_KDE_PLASMA_WINDOW_GEOMETRY_SINCE_VERSION) {
continue;
}
send_geometry(resource->handle, geometry.x(), geometry.y(), geometry.width(), geometry.height());
}
}
void PlasmaWindowInterfacePrivate::setApplicationMenuPaths(const QString &service, const QString &object)
{
if (m_appServiceName == service && m_appObjectPath == object) {
return;
}
m_appServiceName = service;
m_appObjectPath = object;
const auto clientResources = resourceMap();
for (auto resource : clientResources) {
if (resource->version() < ORG_KDE_PLASMA_WINDOW_APPLICATION_MENU_SINCE_VERSION) {
continue;
}
send_application_menu(resource->handle, service, object);
}
}
void PlasmaWindowInterfacePrivate::org_kde_plasma_window_close(Resource *resource)
{
Q_UNUSED(resource)
Q_EMIT q->closeRequested();
}
void PlasmaWindowInterfacePrivate::org_kde_plasma_window_request_move(Resource *resource)
{
Q_UNUSED(resource)
Q_EMIT q->moveRequested();
}
void PlasmaWindowInterfacePrivate::org_kde_plasma_window_request_resize(Resource *resource)
{
Q_UNUSED(resource)
Q_EMIT q->resizeRequested();
}
void PlasmaWindowInterfacePrivate::org_kde_plasma_window_set_virtual_desktop(Resource *resource, uint32_t number)
{
Q_UNUSED(resource)
Q_EMIT q->virtualDesktopRequested(number);
}
void PlasmaWindowInterfacePrivate::org_kde_plasma_window_set_state(Resource *resource, uint32_t flags, uint32_t state)
{
Q_UNUSED(resource)
if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_ACTIVE) {
Q_EMIT q->activeRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_ACTIVE);
}
if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MINIMIZED) {
Q_EMIT q->minimizedRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MINIMIZED);
}
if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MAXIMIZED) {
Q_EMIT q->maximizedRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MAXIMIZED);
}
if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_FULLSCREEN) {
Q_EMIT q->fullscreenRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_FULLSCREEN);
}
if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_KEEP_ABOVE) {
Q_EMIT q->keepAboveRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_KEEP_ABOVE);
}
if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_KEEP_BELOW) {
Q_EMIT q->keepBelowRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_KEEP_BELOW);
}
if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_DEMANDS_ATTENTION) {
Q_EMIT q->demandsAttentionRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_DEMANDS_ATTENTION);
}
if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_CLOSEABLE) {
Q_EMIT q->closeableRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_CLOSEABLE);
}
if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MINIMIZABLE) {
Q_EMIT q->minimizeableRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MINIMIZABLE);
}
if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MAXIMIZABLE) {
Q_EMIT q->maximizeableRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MAXIMIZABLE);
}
if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_FULLSCREENABLE) {
Q_EMIT q->fullscreenableRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_FULLSCREENABLE);
}
if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SKIPTASKBAR) {
Q_EMIT q->skipTaskbarRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SKIPTASKBAR);
}
if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SKIPSWITCHER) {
Q_EMIT q->skipSwitcherRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SKIPSWITCHER);
}
if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SHADEABLE) {
Q_EMIT q->shadeableRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SHADEABLE);
}
if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SHADED) {
Q_EMIT q->shadedRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SHADED);
}
if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MOVABLE) {
Q_EMIT q->movableRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MOVABLE);
}
if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_RESIZABLE) {
Q_EMIT q->resizableRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_RESIZABLE);
}
if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_VIRTUAL_DESKTOP_CHANGEABLE) {
Q_EMIT q->virtualDesktopChangeableRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_VIRTUAL_DESKTOP_CHANGEABLE);
}
}
void PlasmaWindowInterfacePrivate::org_kde_plasma_window_set_minimized_geometry(Resource *resource, wl_resource *panel, uint32_t x, uint32_t y, uint32_t width, uint32_t height)
{
Q_UNUSED(resource)
SurfaceInterface *panelSurface = SurfaceInterface::get(panel);
if (!panelSurface) {
return;
}
if (minimizedGeometries.value(panelSurface) == QRect(x, y, width, height)) {
return;
}
minimizedGeometries[panelSurface] = QRect(x, y, width, height);
Q_EMIT q->minimizedGeometriesChanged();
QObject::connect(panelSurface, &QObject::destroyed, q, [this, panelSurface] () {
if (minimizedGeometries.remove(panelSurface)) {
Q_EMIT q->minimizedGeometriesChanged();
}
});
}
void PlasmaWindowInterfacePrivate::org_kde_plasma_window_unset_minimized_geometry(Resource *resource, wl_resource *panel)
{
Q_UNUSED(resource)
SurfaceInterface *panelSurface = SurfaceInterface::get(panel);
if (!panelSurface) {
return;
}
if (!minimizedGeometries.contains(panelSurface)) {
return;
}
minimizedGeometries.remove(panelSurface);
Q_EMIT q->minimizedGeometriesChanged();
}
PlasmaWindowInterface::PlasmaWindowInterface(PlasmaWindowManagementInterface *wm, QObject *parent)
: QObject(parent)
, d(new PlasmaWindowInterfacePrivate(wm, this))
{
}
PlasmaWindowInterface::~PlasmaWindowInterface() = default;
void PlasmaWindowInterface::setAppId(const QString &appId)
{
d->setAppId(appId);
}
void PlasmaWindowInterface::setPid(quint32 pid)
{
d->setPid(pid);
}
void PlasmaWindowInterface::setTitle(const QString &title)
{
d->setTitle(title);
}
void PlasmaWindowInterface::setVirtualDesktop(quint32 desktop)
{
d->setVirtualDesktop(desktop);
}
void PlasmaWindowInterface::unmap()
{
d->unmap();
}
QHash<SurfaceInterface*, QRect> PlasmaWindowInterface::minimizedGeometries() const
{
return d->minimizedGeometries;
}
void PlasmaWindowInterface::setActive(bool set)
{
d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_ACTIVE, set);
}
void PlasmaWindowInterface::setFullscreen(bool set)
{
d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_FULLSCREEN, set);
}
void PlasmaWindowInterface::setKeepAbove(bool set)
{
d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_KEEP_ABOVE, set);
}
void PlasmaWindowInterface::setKeepBelow(bool set)
{
d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_KEEP_BELOW, set);
}
void PlasmaWindowInterface::setMaximized(bool set)
{
d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MAXIMIZED, set);
}
void PlasmaWindowInterface::setMinimized(bool set)
{
d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MINIMIZED, set);
}
void PlasmaWindowInterface::setOnAllDesktops(bool set)
{
//the deprecated vd management
d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_ON_ALL_DESKTOPS, set);
if (!d->wm->plasmaVirtualDesktopManagementInterface()) {
return;
}
const auto clientResources = d->resourceMap();
//the current vd management
if (set) {
if (d->plasmaVirtualDesktops.isEmpty()) {
return;
}
//leaving everything means on all desktops
for (auto desk : plasmaVirtualDesktops()) {
for (auto resource : clientResources) {
d->send_virtual_desktop_left(resource->handle, desk);
}
}
d->plasmaVirtualDesktops.clear();
} else {
if (!d->plasmaVirtualDesktops.isEmpty()) {
return;
}
//enters the desktops which are active (usually only one but not a given)
for (auto desk : d->wm->plasmaVirtualDesktopManagementInterface()->desktops()) {
if (desk->isActive() && !d->plasmaVirtualDesktops.contains(desk->id())) {
d->plasmaVirtualDesktops << desk->id();
for (auto resource : clientResources) {
d->send_virtual_desktop_entered(resource->handle, desk->id());
}
}
}
}
}
void PlasmaWindowInterface::setDemandsAttention(bool set)
{
d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_DEMANDS_ATTENTION, set);
}
void PlasmaWindowInterface::setCloseable(bool set)
{
d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_CLOSEABLE, set);
}
void PlasmaWindowInterface::setFullscreenable(bool set)
{
d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_FULLSCREENABLE, set);
}
void PlasmaWindowInterface::setMaximizeable(bool set)
{
d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MAXIMIZABLE, set);
}
void PlasmaWindowInterface::setMinimizeable(bool set)
{
d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MINIMIZABLE, set);
}
void PlasmaWindowInterface::setSkipTaskbar(bool set)
{
d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SKIPTASKBAR, set);
}
void PlasmaWindowInterface::setSkipSwitcher(bool skip)
{
d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SKIPSWITCHER, skip);
}
void PlasmaWindowInterface::setThemedIconName(const QString &iconName)
{
d->setThemedIconName(iconName);
}
void PlasmaWindowInterface::setIcon(const QIcon &icon)
{
d->setIcon(icon);
}
void PlasmaWindowInterface::addPlasmaVirtualDesktop(const QString &id)
{
//don't add a desktop we're not sure it exists
if (!d->wm->plasmaVirtualDesktopManagementInterface() || d->plasmaVirtualDesktops.contains(id)) {
return;
}
PlasmaVirtualDesktopInterface *desktop = d->wm->plasmaVirtualDesktopManagementInterface()->desktop(id);
if (!desktop) {
return;
}
d->plasmaVirtualDesktops << id;
//if the desktop dies, remove it from or list
connect(desktop, &QObject::destroyed,
this, [this, id](){removePlasmaVirtualDesktop(id);});
const auto clientResources = d->resourceMap();
for (auto resource : clientResources) {
d->send_virtual_desktop_entered(resource->handle, id);
}
}
void PlasmaWindowInterface::removePlasmaVirtualDesktop(const QString &id)
{
if (!d->plasmaVirtualDesktops.contains(id)) {
return;
}
d->plasmaVirtualDesktops.removeAll(id);
const auto clientResources = d->resourceMap();
for (auto resource : clientResources) {
d->send_virtual_desktop_left(resource->handle, id);
}
//we went on all desktops
if (d->plasmaVirtualDesktops.isEmpty()) {
setOnAllDesktops(true);
}
}
QStringList PlasmaWindowInterface::plasmaVirtualDesktops() const
{
return d->plasmaVirtualDesktops;
}
void PlasmaWindowInterface::addPlasmaActivity(const QString &id)
{
if (d->plasmaActivities.contains(id)) {
return;
}
d->plasmaActivities << id;
const auto clientResources = d->resourceMap();
for (auto resource : clientResources) {
if (resource->version() >= ORG_KDE_PLASMA_WINDOW_ACTIVITY_ENTERED_SINCE_VERSION) {
d->send_activity_entered(resource->handle, id);
}
}
}
void PlasmaWindowInterface::removePlasmaActivity(const QString &id)
{
if (!d->plasmaActivities.removeOne(id)) {
return;
}
const auto clientResources = d->resourceMap();
for (auto resource : clientResources) {
if (resource->version() >= ORG_KDE_PLASMA_WINDOW_ACTIVITY_LEFT_SINCE_VERSION) {
d->send_activity_left(resource->handle, id);
}
}
}
QStringList PlasmaWindowInterface::plasmaActivities() const
{
return d->plasmaActivities;
}
void PlasmaWindowInterface::setShadeable(bool set)
{
d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SHADEABLE, set);
}
void PlasmaWindowInterface::setShaded(bool set)
{
d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SHADED, set);
}
void PlasmaWindowInterface::setMovable(bool set)
{
d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MOVABLE, set);
}
void PlasmaWindowInterface::setResizable(bool set)
{
d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_RESIZABLE, set);
}
void PlasmaWindowInterface::setVirtualDesktopChangeable(bool set)
{
d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_VIRTUAL_DESKTOP_CHANGEABLE, set);
}
void PlasmaWindowInterface::setParentWindow(PlasmaWindowInterface *parentWindow)
{
d->setParentWindow(parentWindow);
}
void PlasmaWindowInterface::setGeometry(const QRect &geometry)
{
d->setGeometry(geometry);
}
void PlasmaWindowInterface::setApplicationMenuPaths(const QString &serviceName, const QString &objectPath)
{
d->setApplicationMenuPaths(serviceName, objectPath);
}
quint32 PlasmaWindowInterface::internalId() const
{
return d->windowId;
}
QString PlasmaWindowInterface::uuid() const
{
return d->uuid;
}
}