KWayland

appmenu_interface.cpp
1 /*
2  SPDX-FileCopyrightText: 2017 David Edmundson <[email protected]>
3 
4  SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
5 */
6 #include "appmenu_interface.h"
7 #include "display.h"
8 #include "global_p.h"
9 #include "logging.h"
10 #include "resource_p.h"
11 #include "surface_interface.h"
12 
13 #include <QtGlobal>
14 
15 #include <wayland-appmenu-server-protocol.h>
16 
17 namespace KWayland
18 {
19 namespace Server
20 {
21 class AppMenuManagerInterface::Private : public Global::Private
22 {
23 public:
24  Private(AppMenuManagerInterface *q, Display *d);
25 
27 
28 private:
29  void bind(wl_client *client, uint32_t version, uint32_t id) override;
30 
31  static void unbind(wl_resource *resource);
32  static Private *cast(wl_resource *r)
33  {
34  return reinterpret_cast<Private *>(wl_resource_get_user_data(r));
35  }
36 
37  static void createCallback(wl_client *client, wl_resource *resource, uint32_t id, wl_resource *surface);
38 
40  static const struct org_kde_kwin_appmenu_manager_interface s_interface;
41  static const quint32 s_version;
42 };
43 
44 const quint32 AppMenuManagerInterface::Private::s_version = 1;
45 
46 #ifndef K_DOXYGEN
47 const struct org_kde_kwin_appmenu_manager_interface AppMenuManagerInterface::Private::s_interface = {createCallback};
48 #endif
49 
50 void AppMenuManagerInterface::Private::createCallback(wl_client *client, wl_resource *resource, uint32_t id, wl_resource *surface)
51 {
52  auto p = reinterpret_cast<Private *>(wl_resource_get_user_data(resource));
53  Q_ASSERT(p);
54 
56  if (!s) {
57  // TODO: send error?
58  qCWarning(KWAYLAND_SERVER) << "ServerSideDecorationInterface requested for non existing SurfaceInterface";
59  return;
60  }
61  auto appmenu = new AppMenuInterface(p->q, s, resource);
62  appmenu->create(p->display->getConnection(client), wl_resource_get_version(resource), id);
63  if (!appmenu->resource()) {
64  wl_resource_post_no_memory(resource);
65  delete appmenu;
66  return;
67  }
68  p->appmenus.append(appmenu);
69  QObject::connect(appmenu, &QObject::destroyed, p->q, [=]() {
70  p->appmenus.removeOne(appmenu);
71  });
72  Q_EMIT p->q->appMenuCreated(appmenu);
73 }
74 
75 AppMenuManagerInterface::Private::Private(AppMenuManagerInterface *q, Display *d)
76  : Global::Private(d, &org_kde_kwin_appmenu_manager_interface, s_version)
77  , q(q)
78 {
79 }
80 
81 void AppMenuManagerInterface::Private::bind(wl_client *client, uint32_t version, uint32_t id)
82 {
83  auto c = display->getConnection(client);
84  wl_resource *resource = c->createResource(&org_kde_kwin_appmenu_manager_interface, qMin(version, s_version), id);
85  if (!resource) {
86  wl_client_post_no_memory(client);
87  return;
88  }
89  wl_resource_set_implementation(resource, &s_interface, this, unbind);
90 }
91 
92 void AppMenuManagerInterface::Private::unbind(wl_resource *resource)
93 {
94  Q_UNUSED(resource)
95 }
96 
97 class AppMenuInterface::Private : public Resource::Private
98 {
99 public:
100  Private(AppMenuInterface *q, AppMenuManagerInterface *c, SurfaceInterface *surface, wl_resource *parentResource);
101  ~Private();
102 
103  SurfaceInterface *surface;
104  InterfaceAddress address;
105 
106 private:
107  static void setAddressCallback(wl_client *client, wl_resource *resource, const char *service_name, const char *object_path);
108 
109  AppMenuInterface *q_func()
110  {
111  return reinterpret_cast<AppMenuInterface *>(q);
112  }
113  static AppMenuInterface *get(SurfaceInterface *s);
114  static const struct org_kde_kwin_appmenu_interface s_interface;
115 };
116 
117 #ifndef K_DOXYGEN
118 const struct org_kde_kwin_appmenu_interface AppMenuInterface::Private::s_interface = {setAddressCallback, resourceDestroyedCallback};
119 #endif
120 
121 void AppMenuInterface::Private::setAddressCallback(wl_client *client, wl_resource *resource, const char *service_name, const char *object_path)
122 {
123  Q_UNUSED(client);
124  auto p = reinterpret_cast<Private *>(wl_resource_get_user_data(resource));
125  Q_ASSERT(p);
126 
127  if (p->address.serviceName == QLatin1String(service_name) && p->address.objectPath == QLatin1String(object_path)) {
128  return;
129  }
130  p->address.serviceName = QString::fromLatin1(service_name);
131  p->address.objectPath = QString::fromLatin1(object_path);
132  Q_EMIT p->q_func()->addressChanged(p->address);
133 }
134 
135 AppMenuInterface::Private::Private(AppMenuInterface *q, AppMenuManagerInterface *c, SurfaceInterface *s, wl_resource *parentResource)
136  : Resource::Private(q, c, parentResource, &org_kde_kwin_appmenu_interface, &s_interface)
137  , surface(s)
138 {
139 }
140 
141 AppMenuInterface::Private::~Private()
142 {
143  if (resource) {
144  wl_resource_destroy(resource);
145  resource = nullptr;
146  }
147 }
148 
149 AppMenuManagerInterface::AppMenuManagerInterface(Display *display, QObject *parent)
150  : Global(new Private(this, display), parent)
151 {
152 }
153 
154 AppMenuManagerInterface::~AppMenuManagerInterface()
155 {
156 }
157 
158 AppMenuManagerInterface::Private *AppMenuManagerInterface::d_func() const
159 {
160  return reinterpret_cast<AppMenuManagerInterface::Private *>(d.data());
161 }
162 
164 {
165  Q_D();
166  for (AppMenuInterface *menu : d->appmenus) {
167  if (menu->surface() == surface) {
168  return menu;
169  }
170  }
171  return nullptr;
172 }
173 
174 AppMenuInterface::AppMenuInterface(AppMenuManagerInterface *parent, SurfaceInterface *s, wl_resource *parentResource)
175  : Resource(new Private(this, parent, s, parentResource))
176 {
177 }
178 
179 AppMenuInterface::Private *AppMenuInterface::d_func() const
180 {
181  return reinterpret_cast<AppMenuInterface::Private *>(d.data());
182 }
183 
184 AppMenuInterface::~AppMenuInterface()
185 {
186 }
187 
189 {
190  Q_D();
191  return d->address;
192 }
193 
195 {
196  Q_D();
197  return d->surface;
198 }
199 
200 } // namespace
201 }
ClientConnection * getConnection(wl_client *client)
Gets the ClientConnection for the given client.
Definition: display.cpp:673
static SurfaceInterface * get(wl_resource *native)
Resource representing a wl_surface.
Provides the DBus service name and object path to a AppMenu DBus interface.
Class holding the Wayland server display loop.
Definition: display.h:86
wl_resource * createResource(const wl_interface *interface, quint32 version, quint32 id)
Creates a new wl_resource for the provided interface.
Base class for all Globals.
Definition: global.h:46
Structure containing DBus service name and path.
Represents a bound Resource.
Definition: resource.h:31
AppMenuInterface * appMenuForSurface(SurfaceInterface *)
Returns any existing appMenu for a given surface This returns a null pointer if no AppMenuInterface e...
SurfaceInterface * surface() const
QString fromLatin1(const char *str, int size)
Provides the DBus service name and object path to a AppMenu DBus interface.
Display * display()
Definition: global.cpp:78
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QObject * parent() const const
void destroyed(QObject *obj)
Q_EMITQ_EMIT
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Sat Sep 25 2021 22:51:28 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.