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 "surface_interface.h"
9 #include "global_p.h"
10 #include "resource_p.h"
11 #include "logging.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 private:
28  void bind(wl_client *client, uint32_t version, uint32_t id) override;
29 
30  static void unbind(wl_resource *resource);
31  static Private *cast(wl_resource *r) {
32  return reinterpret_cast<Private*>(wl_resource_get_user_data(r));
33  }
34 
35  static void createCallback(wl_client *client, wl_resource *resource, uint32_t id, wl_resource * surface);
36 
38  static const struct org_kde_kwin_appmenu_manager_interface s_interface;
39  static const quint32 s_version;
40 };
41 
42 const quint32 AppMenuManagerInterface::Private::s_version = 1;
43 
44 #ifndef K_DOXYGEN
45 const struct org_kde_kwin_appmenu_manager_interface AppMenuManagerInterface::Private::s_interface = {
46  createCallback
47 };
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  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 
104  SurfaceInterface *surface;
105  InterfaceAddress address;
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  return reinterpret_cast<AppMenuInterface *>(q);
111  }
112  static AppMenuInterface *get(SurfaceInterface *s);
113  static const struct org_kde_kwin_appmenu_interface s_interface;
114 };
115 
116 #ifndef K_DOXYGEN
117 const struct org_kde_kwin_appmenu_interface AppMenuInterface::Private::s_interface = {
118  setAddressCallback,
119  resourceDestroyedCallback
120 };
121 #endif
122 
123 void AppMenuInterface::Private::setAddressCallback(wl_client *client, wl_resource *resource, const char * service_name, const char * object_path)
124 {
125  Q_UNUSED(client);
126  auto p = reinterpret_cast<Private*>(wl_resource_get_user_data(resource));
127  Q_ASSERT(p);
128 
129  if (p->address.serviceName == QLatin1String(service_name) &&
130  p->address.objectPath == QLatin1String(object_path)) {
131  return;
132  }
133  p->address.serviceName = QString::fromLatin1(service_name);
134  p->address.objectPath = QString::fromLatin1(object_path);
135  emit p->q_func()->addressChanged(p->address);
136 }
137 
138 AppMenuInterface::Private::Private(AppMenuInterface *q, AppMenuManagerInterface *c, SurfaceInterface *s, wl_resource *parentResource)
139  : Resource::Private(q, c, parentResource, &org_kde_kwin_appmenu_interface, &s_interface),
140  surface(s)
141 {
142 }
143 
144 AppMenuInterface::Private::~Private()
145 {
146  if (resource) {
147  wl_resource_destroy(resource);
148  resource = nullptr;
149  }
150 }
151 
152 AppMenuManagerInterface::AppMenuManagerInterface(Display *display, QObject *parent)
153  : Global(new Private(this, display), parent)
154 {
155 }
156 
157 AppMenuManagerInterface::~AppMenuManagerInterface()
158 {
159 }
160 
161 AppMenuManagerInterface::Private *AppMenuManagerInterface::d_func() const
162 {
163  return reinterpret_cast<AppMenuManagerInterface::Private*>(d.data());
164 }
165 
167 {
168  Q_D();
169  for (AppMenuInterface* menu: d->appmenus) {
170  if (menu->surface() == surface) {
171  return menu;
172  }
173  }
174  return nullptr;
175 }
176 
177 AppMenuInterface::AppMenuInterface(AppMenuManagerInterface *parent, SurfaceInterface *s, wl_resource *parentResource):
178  Resource(new Private(this, parent, s, parentResource))
179 {
180 }
181 
182 AppMenuInterface::Private *AppMenuInterface::d_func() const
183 {
184  return reinterpret_cast<AppMenuInterface::Private*>(d.data());
185 }
186 
187 AppMenuInterface::~AppMenuInterface()
188 {}
189 
191  Q_D();
192  return d->address;
193 }
194 
196  Q_D();
197  return d->surface;
198 }
199 
200 }//namespace
201 }
202 
unsigned int version()
ClientConnection * getConnection(wl_client *client)
Gets the ClientConnection for the given client.
Definition: display.cpp:592
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:89
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:32
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:79
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)
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Sun May 24 2020 23:07:24 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.