File indexing completed on 2024-05-19 16:35:16

0001 /*
0002     SPDX-FileCopyrightText: 2017 David Edmundson <kde@davidedmundson.co.uk>
0003 
0004     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0005 */
0006 #include "appmenu_interface.h"
0007 #include "display.h"
0008 #include "surface_interface.h"
0009 
0010 #include <QtGlobal>
0011 
0012 #include "qwayland-server-appmenu.h"
0013 
0014 namespace KWaylandServer
0015 {
0016 static const quint32 s_version = 1;
0017 
0018 class AppMenuManagerInterfacePrivate : public QtWaylandServer::org_kde_kwin_appmenu_manager
0019 {
0020 public:
0021     AppMenuManagerInterfacePrivate(AppMenuManagerInterface *q, Display *d);
0022 
0023     QVector<AppMenuInterface *> appmenus;
0024     AppMenuManagerInterface *q;
0025 
0026 protected:
0027     void org_kde_kwin_appmenu_manager_create(Resource *resource, uint32_t id, wl_resource *surface) override;
0028 };
0029 
0030 void AppMenuManagerInterfacePrivate::org_kde_kwin_appmenu_manager_create(Resource *resource, uint32_t id, wl_resource *surface)
0031 {
0032     SurfaceInterface *s = SurfaceInterface::get(surface);
0033     if (!s) {
0034         wl_resource_post_error(resource->handle, 0, "Invalid  surface");
0035         return;
0036     }
0037     wl_resource *appmenu_resource = wl_resource_create(resource->client(), &org_kde_kwin_appmenu_interface, resource->version(), id);
0038     if (!appmenu_resource) {
0039         wl_client_post_no_memory(resource->client());
0040         return;
0041     }
0042     auto appmenu = new AppMenuInterface(s, appmenu_resource);
0043 
0044     appmenus.append(appmenu);
0045     QObject::connect(appmenu, &QObject::destroyed, q, [=, this]() {
0046         appmenus.removeOne(appmenu);
0047     });
0048     Q_EMIT q->appMenuCreated(appmenu);
0049 }
0050 
0051 AppMenuManagerInterfacePrivate::AppMenuManagerInterfacePrivate(AppMenuManagerInterface *_q, Display *d)
0052     : QtWaylandServer::org_kde_kwin_appmenu_manager(*d, s_version)
0053     , q(_q)
0054 {
0055 }
0056 
0057 class AppMenuInterfacePrivate : public QtWaylandServer::org_kde_kwin_appmenu
0058 {
0059 public:
0060     AppMenuInterfacePrivate(AppMenuInterface *q, SurfaceInterface *surface, wl_resource *resource);
0061 
0062     AppMenuInterface *q;
0063     QPointer<SurfaceInterface> surface;
0064     AppMenuInterface::InterfaceAddress address;
0065 
0066 protected:
0067     void org_kde_kwin_appmenu_destroy_resource(Resource *resource) override;
0068     void org_kde_kwin_appmenu_set_address(Resource *resource, const QString &service_name, const QString &object_path) override;
0069     void org_kde_kwin_appmenu_release(Resource *resource) override;
0070 };
0071 
0072 AppMenuInterfacePrivate::AppMenuInterfacePrivate(AppMenuInterface *_q, SurfaceInterface *s, wl_resource *resource)
0073     : QtWaylandServer::org_kde_kwin_appmenu(resource)
0074     , q(_q)
0075     , surface(s)
0076 {
0077 }
0078 
0079 void AppMenuInterfacePrivate::org_kde_kwin_appmenu_destroy_resource(QtWaylandServer::org_kde_kwin_appmenu::Resource *resource)
0080 {
0081     delete q;
0082 }
0083 
0084 void AppMenuInterfacePrivate::org_kde_kwin_appmenu_set_address(Resource *resource, const QString &service_name, const QString &object_path)
0085 {
0086     if (address.serviceName == service_name && address.objectPath == object_path) {
0087         return;
0088     }
0089 
0090     address.serviceName = service_name;
0091     address.objectPath = object_path;
0092     Q_EMIT q->addressChanged(address);
0093 }
0094 
0095 void AppMenuInterfacePrivate::org_kde_kwin_appmenu_release(QtWaylandServer::org_kde_kwin_appmenu::Resource *resource)
0096 {
0097     wl_resource_destroy(resource->handle);
0098 }
0099 
0100 AppMenuManagerInterface::AppMenuManagerInterface(Display *display, QObject *parent)
0101     : QObject(parent)
0102     , d(new AppMenuManagerInterfacePrivate(this, display))
0103 {
0104 }
0105 
0106 AppMenuManagerInterface::~AppMenuManagerInterface()
0107 {
0108 }
0109 
0110 AppMenuInterface *AppMenuManagerInterface::appMenuForSurface(SurfaceInterface *surface)
0111 {
0112     for (AppMenuInterface *menu : d->appmenus) {
0113         if (menu->surface() == surface) {
0114             return menu;
0115         }
0116     }
0117     return nullptr;
0118 }
0119 
0120 AppMenuInterface::AppMenuInterface(SurfaceInterface *surface, wl_resource *resource)
0121     : QObject()
0122     , d(new AppMenuInterfacePrivate(this, surface, resource))
0123 {
0124 }
0125 
0126 AppMenuInterface::~AppMenuInterface()
0127 {
0128 }
0129 
0130 AppMenuInterface::InterfaceAddress AppMenuInterface::address() const
0131 {
0132     return d->address;
0133 }
0134 
0135 SurfaceInterface *AppMenuInterface::surface() const
0136 {
0137     return d->surface.data();
0138 }
0139 
0140 } // namespace