KWayland

xdgoutput_interface.cpp
1 /*
2  SPDX-FileCopyrightText: 2018 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 "xdgoutput_interface.h"
7 #include "display.h"
8 #include "global_p.h"
9 #include "resource_p.h"
10 #include "output_interface.h"
11 
12 #include <wayland-xdg-output-server-protocol.h>
13 
14 #include <QHash>
15 
16 namespace KWayland
17 {
18 namespace Server
19 {
20 
21 class XdgOutputManagerInterface::Private : public Global::Private
22 {
23 public:
24  Private(XdgOutputManagerInterface *q, Display *d);
26 
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 destroyCallback(wl_client *client, wl_resource *resource);
36  static void getXdgOutputCallback(wl_client *client, wl_resource *resource, uint32_t id, wl_resource * output);
37 
38  XdgOutputManagerInterface *q;
39  static const struct zxdg_output_manager_v1_interface s_interface;
40  static const quint32 s_version;
41 };
42 
43 const quint32 XdgOutputManagerInterface::Private::s_version = 2;
44 
45 #ifndef K_DOXYGEN
46 const struct zxdg_output_manager_v1_interface XdgOutputManagerInterface::Private::s_interface = {
47  destroyCallback,
48  getXdgOutputCallback
49 };
50 #endif
51 
52 class XdgOutputV1Interface: public Resource
53 {
54 public:
55  XdgOutputV1Interface(XdgOutputManagerInterface *parent, wl_resource *parentResource);
56  ~XdgOutputV1Interface();
57  void setLogicalSize(const QSize &size);
58  void setLogicalPosition(const QPoint &pos);
59  void setName(const QString &name);
60  void setDescription(const QString &description);
61  void done();
62 private:
63  class Private;
64 };
65 
66 class XdgOutputInterface::Private
67 {
68 public:
69  void resourceConnected(XdgOutputV1Interface *resource);
70  void resourceDisconnected(XdgOutputV1Interface *resource);
71  QPoint pos;
72  QSize size;
73  QString name;
74  QString description;
75  bool dirty = false;
76  bool doneOnce = false;
78 };
79 
80 
81 XdgOutputManagerInterface::XdgOutputManagerInterface(Display *display, QObject *parent)
82  : Global(new XdgOutputManagerInterface::Private(this, display), parent)
83 {
84 }
85 
86 XdgOutputManagerInterface::~XdgOutputManagerInterface()
87 {}
88 
89 XdgOutputInterface* XdgOutputManagerInterface::createXdgOutput(OutputInterface *output, QObject *parent)
90 {
91  Q_D();
92  if (!d->outputs.contains(output)) {
93  auto xdgOutput = new XdgOutputInterface(parent);
94  d->outputs[output] = xdgOutput;
95  //as XdgOutput lifespan is managed by user, delete our mapping when either
96  //it or the relevant Output gets deleted
97  connect(output, &QObject::destroyed, this, [this, output]() {
98  Q_D();
99  d->outputs.remove(output);
100  });
101  connect(xdgOutput, &QObject::destroyed, this, [this, output]() {
102  Q_D();
103  d->outputs.remove(output);
104  });
105 
106  }
107  return d->outputs[output];
108 }
109 
110 XdgOutputManagerInterface::Private* XdgOutputManagerInterface::d_func() const
111 {
112  return reinterpret_cast<Private*>(d.data());
113 }
114 
115 void XdgOutputManagerInterface::Private::destroyCallback(wl_client *client, wl_resource *resource)
116 {
117  Q_UNUSED(client)
118  wl_resource_destroy(resource);
119 }
120 
121 void XdgOutputManagerInterface::Private::getXdgOutputCallback(wl_client *client, wl_resource *resource, uint32_t id, wl_resource * outputResource)
122 {
123  auto d = cast(resource);
124  auto output = OutputInterface::get(outputResource);
125  if (!output) { // output client is requesting XdgOutput for an Output that doesn't exist
126  return;
127  }
128  if (!d->outputs.contains(output)) {
129  return; //server hasn't created an XdgOutput for this output yet, give the client nothing
130  }
131  auto iface = new XdgOutputV1Interface(d->q, resource);
132  iface->create(d->display->getConnection(client), wl_resource_get_version(resource), id);
133  if (!iface->resource()) {
134  wl_resource_post_no_memory(resource);
135  delete iface;
136  return;
137  }
138 
139  auto xdgOutput = d->outputs[output];
140  xdgOutput->d->resourceConnected(iface);
141  connect(iface, &XdgOutputV1Interface::unbound, xdgOutput, [xdgOutput, iface]() {
142  xdgOutput->d->resourceDisconnected(iface);
143  });
144 }
145 
146 XdgOutputManagerInterface::Private::Private(XdgOutputManagerInterface *qptr, Display *d)
147  : Global::Private(d, &zxdg_output_manager_v1_interface, s_version)
148  , q(qptr)
149 {
150 }
151 
152 void XdgOutputManagerInterface::Private::bind(wl_client *client, uint32_t version, uint32_t id)
153 {
154  auto c = display->getConnection(client);
155  wl_resource *resource = c->createResource(&zxdg_output_manager_v1_interface, qMin(version, s_version), id);
156  if (!resource) {
157  wl_client_post_no_memory(client);
158  return;
159  }
160  wl_resource_set_implementation(resource, &s_interface, this, unbind);
161 }
162 
163 void XdgOutputManagerInterface::Private::unbind(wl_resource *resource)
164 {
165  Q_UNUSED(resource)
166 }
167 
168 XdgOutputInterface::XdgOutputInterface(QObject *parent):
169  QObject(parent),
170  d(new XdgOutputInterface::Private)
171 {
172 }
173 
174 XdgOutputInterface::~XdgOutputInterface()
175 {}
176 
177 void XdgOutputInterface::setLogicalSize(const QSize &size)
178 {
179  if (size == d->size) {
180  return;
181  }
182  d->size = size;
183  d->dirty = true;
184  for(auto resource: d->resources) {
185  resource->setLogicalSize(size);
186  }
187 }
188 
189 QSize XdgOutputInterface::logicalSize() const
190 {
191  return d->size;
192 }
193 
194 void XdgOutputInterface::setLogicalPosition(const QPoint &pos)
195 {
196  if (pos == d->pos) {
197  return;
198  }
199  d->pos = pos;
200  d->dirty = true;
201  for(auto resource: d->resources) {
202  resource->setLogicalPosition(pos);
203  }
204 }
205 
206 QPoint XdgOutputInterface::logicalPosition() const
207 {
208  return d->pos;
209 }
210 
211 void XdgOutputInterface::setName(const QString &name)
212 {
213  d->name = name;
214 }
215 
216 void XdgOutputInterface::setDescription(const QString &description)
217 {
218  d->description = description;
219 }
220 
221 void XdgOutputInterface::done()
222 {
223  d->doneOnce = true;
224  if (!d->dirty) {
225  return;
226  }
227  d->dirty = false;
228  for(auto resource: d->resources) {
229  resource->done();
230  }
231 }
232 
233 void XdgOutputInterface::Private::resourceConnected(XdgOutputV1Interface *resource)
234 {
235  resource->setLogicalPosition(pos);
236  resource->setLogicalSize(size);
237  if (!name.isEmpty()) {
238  resource->setName(name);
239  }
240  if (!description.isEmpty()) {
241  resource->setDescription(description);
242  }
243  if (doneOnce) {
244  resource->done();
245  }
246  resources << resource;
247 }
248 
249 void XdgOutputInterface::Private::resourceDisconnected(XdgOutputV1Interface *resource)
250 {
251  resources.removeOne(resource);
252 }
253 
254 
255 class XdgOutputV1Interface::Private : public Resource::Private
256 {
257 public:
258  Private(XdgOutputV1Interface *q, XdgOutputManagerInterface *c, wl_resource *parentResource);
259  ~Private();
260 
261 private:
262 
263  XdgOutputV1Interface *q_func() {
264  return reinterpret_cast<XdgOutputV1Interface *>(q);
265  }
266 
267  static const struct zxdg_output_v1_interface s_interface;
268 };
269 
270 XdgOutputV1Interface::XdgOutputV1Interface(XdgOutputManagerInterface *parent, wl_resource *parentResource)
271  :Resource(new XdgOutputV1Interface::Private(this, parent, parentResource))
272 {}
273 
274 XdgOutputV1Interface::~XdgOutputV1Interface()
275 {}
276 
277 void XdgOutputV1Interface::setLogicalSize(const QSize &size)
278 {
279  if (!d->resource) {
280  return;
281  }
282  zxdg_output_v1_send_logical_size(d->resource, size.width(), size.height());
283 }
284 
285 void XdgOutputV1Interface::setLogicalPosition(const QPoint &pos)
286 {
287  if (!d->resource) {
288  return;
289  }
290  zxdg_output_v1_send_logical_position(d->resource, pos.x(), pos.y());
291 }
292 
293 void XdgOutputV1Interface::setName(const QString &name)
294 {
295  if (!d->resource) {
296  return;
297  }
298  if (wl_resource_get_version(d->resource) < ZXDG_OUTPUT_V1_NAME_SINCE_VERSION) {
299  return;
300  }
301  zxdg_output_v1_send_name(d->resource, name.toUtf8().constData());
302 }
303 
304 void XdgOutputV1Interface::setDescription(const QString &description)
305 {
306  if (!d->resource) {
307  return;
308  }
309  if (wl_resource_get_version(d->resource) < ZXDG_OUTPUT_V1_DESCRIPTION_SINCE_VERSION) {
310  return;
311  }
312  zxdg_output_v1_send_description(d->resource, description.toUtf8().constData());
313 }
314 
315 void XdgOutputV1Interface::done()
316 {
317  if (!d->resource) {
318  return;
319  }
320  zxdg_output_v1_send_done(d->resource);
321 }
322 
323 #ifndef K_DOXYGEN
324 const struct zxdg_output_v1_interface XdgOutputV1Interface::Private::s_interface = {
325  resourceDestroyedCallback
326 };
327 #endif
328 
329 XdgOutputV1Interface::Private::Private(XdgOutputV1Interface *q, XdgOutputManagerInterface *c, wl_resource *parentResource)
330  : Resource::Private(q, c, parentResource, &zxdg_output_v1_interface, &s_interface)
331 {
332 }
333 
334 XdgOutputV1Interface::Private::~Private()
335 {
336  if (resource) {
337  wl_resource_destroy(resource);
338  resource = nullptr;
339  }
340 }
341 
342 }
343 }
344 
int width() const const
QString description() const
A longer human readable description.
Definition: xdgoutput.cpp:233
QString name() const
A consistent unique name for this monitor.
Definition: xdgoutput.cpp:228
int x() const const
int y() const const
Global for the wl_output interface.
bool isEmpty() const const
const char * constData() const const
Class holding the Wayland server display loop.
Definition: display.h:89
T * data() const const
QObject(QObject *parent)
Represents a bound Resource.
Definition: resource.h:32
Extension to Output Users should set all relevant values on creation and on future changes...
int height() const const
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)
QByteArray toUtf8() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Fri Aug 7 2020 22:48:20 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.