File indexing completed on 2024-11-10 04:57:24

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