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

KDE's Doxygen guidelines are available online.