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