/* SPDX-FileCopyrightText: 2015 Martin Gräßlin 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 #include #include #include #include #include #include #include #include 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 windows; QPointer plasmaVirtualDesktopManagementInterface = nullptr; quint32 windowIdCounter = 0; QVector stackingOrder; QVector 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 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(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; } 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 PlasmaWindowManagementInterface::windows() const { return d->windows; } void PlasmaWindowManagementInterface::setStackingOrder(const QVector &stackingOrder) { if (d->stackingOrder == stackingOrder) { return; } d->stackingOrder = stackingOrder; d->sendStackingOrderChanged(); } void PlasmaWindowManagementInterface::setStackingOrderUuids(const QVector &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) emit q->enterPlasmaVirtualDesktopRequested(id); } void PlasmaWindowInterfacePrivate::org_kde_plasma_window_request_enter_new_virtual_desktop(Resource *resource) { Q_UNUSED(resource) emit q->enterNewPlasmaVirtualDesktopRequested(); } void PlasmaWindowInterfacePrivate::org_kde_plasma_window_request_leave_virtual_desktop(Resource *resource, const QString &id) { Q_UNUSED(resource) emit q->leavePlasmaVirtualDesktopRequested(id); } void PlasmaWindowInterfacePrivate::org_kde_plasma_window_request_enter_activity(Resource *resource, const QString &id) { Q_UNUSED(resource) emit q->enterPlasmaActivityRequested(id); } void PlasmaWindowInterfacePrivate::org_kde_plasma_window_request_leave_activity(Resource *resource, const QString &id) { Q_UNUSED(resource) 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) emit q->closeRequested(); } void PlasmaWindowInterfacePrivate::org_kde_plasma_window_request_move(Resource *resource) { Q_UNUSED(resource) emit q->moveRequested(); } void PlasmaWindowInterfacePrivate::org_kde_plasma_window_request_resize(Resource *resource) { Q_UNUSED(resource) emit q->resizeRequested(); } void PlasmaWindowInterfacePrivate::org_kde_plasma_window_set_virtual_desktop(Resource *resource, uint32_t number) { Q_UNUSED(resource) 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) { emit q->activeRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_ACTIVE); } if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MINIMIZED) { emit q->minimizedRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MINIMIZED); } if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MAXIMIZED) { emit q->maximizedRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MAXIMIZED); } if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_FULLSCREEN) { emit q->fullscreenRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_FULLSCREEN); } if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_KEEP_ABOVE) { emit q->keepAboveRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_KEEP_ABOVE); } if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_KEEP_BELOW) { emit q->keepBelowRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_KEEP_BELOW); } if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_DEMANDS_ATTENTION) { emit q->demandsAttentionRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_DEMANDS_ATTENTION); } if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_CLOSEABLE) { emit q->closeableRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_CLOSEABLE); } if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MINIMIZABLE) { emit q->minimizeableRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MINIMIZABLE); } if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MAXIMIZABLE) { emit q->maximizeableRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MAXIMIZABLE); } if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_FULLSCREENABLE) { emit q->fullscreenableRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_FULLSCREENABLE); } if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SKIPTASKBAR) { emit q->skipTaskbarRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SKIPTASKBAR); } if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SKIPSWITCHER) { emit q->skipSwitcherRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SKIPSWITCHER); } if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SHADEABLE) { emit q->shadeableRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SHADEABLE); } if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SHADED) { emit q->shadedRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_SHADED); } if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MOVABLE) { emit q->movableRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_MOVABLE); } if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_RESIZABLE) { emit q->resizableRequested(state & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_RESIZABLE); } if (flags & ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_VIRTUAL_DESKTOP_CHANGEABLE) { 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); emit q->minimizedGeometriesChanged(); QObject::connect(panelSurface, &QObject::destroyed, q, [this, panelSurface] () { if (minimizedGeometries.remove(panelSurface)) { 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); 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 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; } }