KWayland

shadow_interface.cpp
1 /*
2  SPDX-FileCopyrightText: 2015 Martin Gräßlin <[email protected]>
3 
4  SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
5 */
6 #include "shadow_interface.h"
7 #include "buffer_interface.h"
8 #include "display.h"
9 #include "global_p.h"
10 #include "resource_p.h"
11 #include "surface_interface_p.h"
12 
13 #include <wayland-server.h>
14 #include <wayland-shadow-server-protocol.h>
15 
16 namespace KWayland
17 {
18 namespace Server
19 {
20 class ShadowManagerInterface::Private : public Global::Private
21 {
22 public:
23  Private(ShadowManagerInterface *q, Display *d);
24 
25 private:
26  void bind(wl_client *client, uint32_t version, uint32_t id) override;
27  void createShadow(wl_client *client, wl_resource *resource, uint32_t id, wl_resource *surface);
28 
29  static void createCallback(wl_client *client, wl_resource *resource, uint32_t id, wl_resource *surface);
30  static void unsetCallback(wl_client *client, wl_resource *resource, wl_resource *surface);
31  static void destroyCallback(wl_client *client, wl_resource *resource);
32  static void unbind(wl_resource *resource);
33  static Private *cast(wl_resource *r)
34  {
35  return reinterpret_cast<Private *>(wl_resource_get_user_data(r));
36  }
37 
38  ShadowManagerInterface *q;
39  static const struct org_kde_kwin_shadow_manager_interface s_interface;
40  static const quint32 s_version;
41 };
42 
43 const quint32 ShadowManagerInterface::Private::s_version = 2;
44 
45 #ifndef K_DOXYGEN
46 const struct org_kde_kwin_shadow_manager_interface ShadowManagerInterface::Private::s_interface = {createCallback, unsetCallback, destroyCallback};
47 #endif
48 
49 ShadowManagerInterface::Private::Private(ShadowManagerInterface *q, Display *d)
50  : Global::Private(d, &org_kde_kwin_shadow_manager_interface, s_version)
51  , q(q)
52 {
53 }
54 
55 void ShadowManagerInterface::Private::bind(wl_client *client, uint32_t version, uint32_t id)
56 {
57  auto c = display->getConnection(client);
58  wl_resource *resource = c->createResource(&org_kde_kwin_shadow_manager_interface, qMin(version, s_version), id);
59  if (!resource) {
60  wl_client_post_no_memory(client);
61  return;
62  }
63  wl_resource_set_implementation(resource, &s_interface, this, unbind);
64  // TODO: should we track?
65 }
66 
67 void ShadowManagerInterface::Private::unbind(wl_resource *resource)
68 {
69  Q_UNUSED(resource)
70  // TODO: implement?
71 }
72 
73 void ShadowManagerInterface::Private::destroyCallback(wl_client *client, wl_resource *resource)
74 {
75  Q_UNUSED(client)
76  wl_resource_destroy(resource);
77 }
78 
79 void ShadowManagerInterface::Private::createCallback(wl_client *client, wl_resource *resource, uint32_t id, wl_resource *surface)
80 {
81  cast(resource)->createShadow(client, resource, id, surface);
82 }
83 
84 void ShadowManagerInterface::Private::createShadow(wl_client *client, wl_resource *resource, uint32_t id, wl_resource *surface)
85 {
86  SurfaceInterface *s = SurfaceInterface::get(surface);
87  if (!s) {
88  return;
89  }
90 
91  ShadowInterface *shadow = new ShadowInterface(q, resource);
92  shadow->create(display->getConnection(client), wl_resource_get_version(resource), id);
93  if (!shadow->resource()) {
94  wl_resource_post_no_memory(resource);
95  delete shadow;
96  return;
97  }
98  s->d_func()->setShadow(QPointer<ShadowInterface>(shadow));
99 }
100 
101 void ShadowManagerInterface::Private::unsetCallback(wl_client *client, wl_resource *resource, wl_resource *surface)
102 {
103  Q_UNUSED(client)
104  Q_UNUSED(resource)
105  SurfaceInterface *s = SurfaceInterface::get(surface);
106  if (!s) {
107  return;
108  }
109  s->d_func()->setShadow(QPointer<ShadowInterface>());
110 }
111 
112 ShadowManagerInterface::ShadowManagerInterface(Display *display, QObject *parent)
113  : Global(new Private(this, display), parent)
114 {
115 }
116 
117 ShadowManagerInterface::~ShadowManagerInterface() = default;
118 
119 class ShadowInterface::Private : public Resource::Private
120 {
121 public:
122  Private(ShadowInterface *q, ShadowManagerInterface *c, wl_resource *parentResource);
123  ~Private() override;
124 
125  struct State {
126  enum Flags {
127  None = 0,
128  LeftBuffer = 1 << 0,
129  TopLeftBuffer = 1 << 1,
130  TopBuffer = 1 << 2,
131  TopRightBuffer = 1 << 3,
132  RightBuffer = 1 << 4,
133  BottomRightBuffer = 1 << 5,
134  BottomBuffer = 1 << 6,
135  BottomLeftBuffer = 1 << 7,
136  Offset = 1 << 8,
137  };
138  BufferInterface *left = nullptr;
139  BufferInterface *topLeft = nullptr;
140  BufferInterface *top = nullptr;
141  BufferInterface *topRight = nullptr;
142  BufferInterface *right = nullptr;
143  BufferInterface *bottomRight = nullptr;
144  BufferInterface *bottom = nullptr;
145  BufferInterface *bottomLeft = nullptr;
146  QMarginsF offset;
147  Flags flags = Flags::None;
148  };
149  State current;
150  State pending;
151 
152 private:
153  void commit();
154  void attach(State::Flags flag, wl_resource *buffer);
155  ShadowInterface *q_func()
156  {
157  return reinterpret_cast<ShadowInterface *>(q);
158  }
159 
160  static void commitCallback(wl_client *client, wl_resource *resource);
161  static void attachLeftCallback(wl_client *client, wl_resource *resource, wl_resource *buffer);
162  static void attachTopLeftCallback(wl_client *client, wl_resource *resource, wl_resource *buffer);
163  static void attachTopCallback(wl_client *client, wl_resource *resource, wl_resource *buffer);
164  static void attachTopRightCallback(wl_client *client, wl_resource *resource, wl_resource *buffer);
165  static void attachRightCallback(wl_client *client, wl_resource *resource, wl_resource *buffer);
166  static void attachBottomRightCallback(wl_client *client, wl_resource *resource, wl_resource *buffer);
167  static void attachBottomCallback(wl_client *client, wl_resource *resource, wl_resource *buffer);
168  static void attachBottomLeftCallback(wl_client *client, wl_resource *resource, wl_resource *buffer);
169  static void offsetLeftCallback(wl_client *client, wl_resource *resource, wl_fixed_t offset);
170  static void offsetTopCallback(wl_client *client, wl_resource *resource, wl_fixed_t offset);
171  static void offsetRightCallback(wl_client *client, wl_resource *resource, wl_fixed_t offset);
172  static void offsetBottomCallback(wl_client *client, wl_resource *resource, wl_fixed_t offset);
173 
174  static const struct org_kde_kwin_shadow_interface s_interface;
175 };
176 
177 #ifndef K_DOXYGEN
178 const struct org_kde_kwin_shadow_interface ShadowInterface::Private::s_interface = {commitCallback,
179  attachLeftCallback,
180  attachTopLeftCallback,
181  attachTopCallback,
182  attachTopRightCallback,
183  attachRightCallback,
184  attachBottomRightCallback,
185  attachBottomCallback,
186  attachBottomLeftCallback,
187  offsetLeftCallback,
188  offsetTopCallback,
189  offsetRightCallback,
190  offsetBottomCallback,
191  resourceDestroyedCallback};
192 #endif
193 
194 void ShadowInterface::Private::commitCallback(wl_client *client, wl_resource *resource)
195 {
196  Q_UNUSED(client)
197  cast<Private>(resource)->commit();
198 }
199 
200 void ShadowInterface::Private::commit()
201 {
202 // clang-format off
203 #define BUFFER( __FLAG__, __PART__ ) \
204  if (pending.flags & State::Flags::__FLAG__##Buffer) { \
205  if (current.__PART__) { \
206  current.__PART__->unref(); \
207  } \
208  if (pending.__PART__) { \
209  pending.__PART__->ref(); \
210  } \
211  current.__PART__ = pending.__PART__; \
212  }
213  BUFFER(Left, left)
214  BUFFER(TopLeft, topLeft)
215  BUFFER(Top, top)
216  BUFFER(TopRight, topRight)
217  BUFFER(Right, right)
218  BUFFER(BottomRight, bottomRight)
219  BUFFER(Bottom, bottom)
220  BUFFER(BottomLeft, bottomLeft)
221 #undef BUFFER
222 
223  if (pending.flags & State::Offset) {
224  current.offset = pending.offset;
225  }
226  pending = State();
227 }
228 
229 void ShadowInterface::Private::attach(ShadowInterface::Private::State::Flags flag, wl_resource *buffer)
230 {
231  BufferInterface *b = BufferInterface::get(buffer);
232  if (b) {
233  QObject::connect(b, &BufferInterface::aboutToBeDestroyed, q,
234  [this](BufferInterface *buffer) {
235  #define PENDING( __PART__ ) \
236  if (pending.__PART__ == buffer) { \
237  pending.__PART__ = nullptr; \
238  }
239  PENDING(left)
240  PENDING(topLeft)
241  PENDING(top)
242  PENDING(topRight)
243  PENDING(right)
244  PENDING(bottomRight)
245  PENDING(bottom)
246  PENDING(bottomLeft)
247  #undef PENDING
248 
249  #define CURRENT( __PART__ ) \
250  if (current.__PART__ == buffer) { \
251  current.__PART__->unref(); \
252  current.__PART__ = nullptr; \
253  }
254  CURRENT(left)
255  CURRENT(topLeft)
256  CURRENT(top)
257  CURRENT(topRight)
258  CURRENT(right)
259  CURRENT(bottomRight)
260  CURRENT(bottom)
261  CURRENT(bottomLeft)
262  #undef CURRENT
263  }
264  );
265  }
266  switch (flag) {
267  case State::LeftBuffer:
268  pending.left = b;
269  break;
270  case State::TopLeftBuffer:
271  pending.topLeft = b;
272  break;
273  case State::TopBuffer:
274  pending.top = b;
275  break;
276  case State::TopRightBuffer:
277  pending.topRight = b;
278  break;
279  case State::RightBuffer:
280  pending.right = b;
281  break;
282  case State::BottomRightBuffer:
283  pending.bottomRight = b;
284  break;
285  case State::BottomBuffer:
286  pending.bottom = b;
287  break;
288  case State::BottomLeftBuffer:
289  pending.bottomLeft = b;
290  break;
291  default:
292  Q_UNREACHABLE();
293  break;
294  }
295  pending.flags = State::Flags(pending.flags | flag);
296 }
297 
298 #define ATTACH( __PART__ ) \
299 void ShadowInterface::Private::attach##__PART__##Callback(wl_client *client, wl_resource *resource, wl_resource *buffer) \
300 { \
301  Q_UNUSED(client) \
302  Private *p = cast<Private>(resource); \
303  p->attach(State::__PART__##Buffer, buffer); \
304 }
305 
306 ATTACH(Left)
307 ATTACH(TopLeft)
308 ATTACH(Top)
309 ATTACH(TopRight)
310 ATTACH(Right)
311 ATTACH(BottomRight)
312 ATTACH(Bottom)
313 ATTACH(BottomLeft)
314 
315 #undef ATTACH
316 
317 #define OFFSET( __PART__ ) \
318 void ShadowInterface::Private::offset##__PART__##Callback(wl_client *client, wl_resource *resource, wl_fixed_t offset) \
319 { \
320  Q_UNUSED(client) \
321  Q_UNUSED(resource) \
322  Private *p = cast<Private>(resource); \
323  p->pending.flags = State::Flags(p->pending.flags | State::Offset); \
324  p->pending.offset.set##__PART__(wl_fixed_to_double(offset)); \
325 }
326 
327 OFFSET(Left)
328 OFFSET(Top)
329 OFFSET(Right)
330 OFFSET(Bottom)
331 
332 #undef OFFSET
333 
334 ShadowInterface::Private::Private(ShadowInterface *q, ShadowManagerInterface *c, wl_resource *parentResource)
335  : Resource::Private(q, c, parentResource, &org_kde_kwin_shadow_interface, &s_interface)
336 {
337 }
338 
339 ShadowInterface::Private::~Private()
340 {
341 #define CURRENT( __PART__ ) \
342  if (current.__PART__) { \
343  current.__PART__->unref(); \
344  }
345  CURRENT(left)
346  CURRENT(topLeft)
347  CURRENT(top)
348  CURRENT(topRight)
349  CURRENT(right)
350  CURRENT(bottomRight)
351  CURRENT(bottom)
352  CURRENT(bottomLeft)
353 #undef CURRENT
354 }
355 
356 ShadowInterface::ShadowInterface(ShadowManagerInterface *parent, wl_resource *parentResource)
357  : Resource(new Private(this, parent, parentResource))
358 {
359 }
360 
361 ShadowInterface::~ShadowInterface() = default;
362 
363 QMarginsF ShadowInterface::offset() const
364 {
365  Q_D();
366  return d->current.offset;
367 }
368 
369 #define BUFFER( __PART__ ) \
370 BufferInterface *ShadowInterface::__PART__() const \
371 { \
372  Q_D(); \
373  return d->current.__PART__; \
374 }
375 // clang-format on
376 
377 BUFFER(left)
378 BUFFER(topLeft)
379 BUFFER(top)
380 BUFFER(topRight)
381 BUFFER(right)
382 BUFFER(bottomRight)
383 BUFFER(bottom)
384 BUFFER(bottomLeft)
385 
386 ShadowInterface::Private *ShadowInterface::d_func() const
387 {
388  return reinterpret_cast<Private *>(d.data());
389 }
390 
391 }
392 }
QTextStream & right(QTextStream &stream)
QTextStream & left(QTextStream &stream)
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
Q_D(Todo)
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 Sun Jan 29 2023 03:54:08 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.