KWayland

surface.cpp
1 /*
2  SPDX-FileCopyrightText: 2014 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 "surface.h"
7 #include "buffer.h"
8 #include "region.h"
9 #include "output.h"
10 #include "wayland_pointer_p.h"
11 
12 #include <QGuiApplication>
13 #include <QRegion>
14 #include <QVector>
15 #include <QWindow>
16 #include <qpa/qplatformnativeinterface.h>
17 // Wayland
18 #include <wayland-client-protocol.h>
19 
20 namespace KWayland
21 {
22 namespace Client
23 {
24 
25 class Q_DECL_HIDDEN Surface::Private
26 {
27 public:
28  Private(Surface *q);
29  void setupFrameCallback();
30 
31  WaylandPointer<wl_surface, wl_surface_destroy> surface;
32  bool frameCallbackInstalled = false;
33  QSize size;
34  bool foreign = false;
35  qint32 scale = 1;
36  QVector<Output *> outputs;
37 
38  void setup(wl_surface *s);
39 
40  static QList<Surface*> s_surfaces;
41 private:
42  void handleFrameCallback();
43  static void frameCallback(void *data, wl_callback *callback, uint32_t time);
44  static void enterCallback(void *data, wl_surface *wl_surface, wl_output *output);
45  static void leaveCallback(void *data, wl_surface *wl_surface, wl_output *output);
46 
47  Surface *q;
48  static const wl_callback_listener s_listener;
49  static const wl_surface_listener s_surfaceListener;
50 };
51 
52 QList<Surface*> Surface::Private::s_surfaces = QList<Surface*>();
53 
54 Surface::Private::Private(Surface *q)
55  : q(q)
56 {
57 }
58 
59 Surface::Surface(QObject *parent)
60  : QObject(parent)
61  , d(new Private(this))
62 {
63  Private::s_surfaces << this;
64 }
65 
66 Surface::~Surface()
67 {
68  Private::s_surfaces.removeAll(this);
69  release();
70 }
71 
73 {
74  if (!window) {
75  return nullptr;
76  }
77  QPlatformNativeInterface *native = qApp->platformNativeInterface();
78  if (!native) {
79  return nullptr;
80  }
81  window->create();
82  wl_surface *s = reinterpret_cast<wl_surface*>(native->nativeResourceForWindow(QByteArrayLiteral("surface"), window));
83  if (!s) {
84  return nullptr;
85  }
86  if (auto surface = get(s)) {
87  return surface;
88  }
89  Surface *surface = new Surface(window);
90  surface->d->surface.setup(s, true);
91  return surface;
92 }
93 
95 {
96  QWindow *window = nullptr;
97 
98  for (auto win : qApp->allWindows()) {
99  if (win->winId() == wid) {
100  window = win;
101  break;
102  }
103  }
104 
105  if (!window) {
106  return nullptr;
107  }
108  return fromWindow(window);
109 }
110 
112 {
113  d->surface.release();
114 }
115 
117 {
118  d->surface.destroy();
119 }
120 
121 void Surface::setup(wl_surface *surface)
122 {
123  d->setup(surface);
124 }
125 
126 void Surface::Private::setup(wl_surface *s)
127 {
128  Q_ASSERT(s);
129  Q_ASSERT(!surface);
130  surface.setup(s);
131  wl_surface_add_listener(s, &s_surfaceListener, this);
132 }
133 
134 void Surface::Private::frameCallback(void *data, wl_callback *callback, uint32_t time)
135 {
136  Q_UNUSED(time)
137  auto s = reinterpret_cast<Surface::Private*>(data);
138  if (callback) {
139  wl_callback_destroy(callback);
140  }
141  s->handleFrameCallback();
142 }
143 
144 void Surface::Private::handleFrameCallback()
145 {
146  frameCallbackInstalled = false;
147  emit q->frameRendered();
148 }
149 
150 #ifndef K_DOXYGEN
151 const struct wl_callback_listener Surface::Private::s_listener = {
152  frameCallback
153 };
154 
155 const struct wl_surface_listener Surface::Private::s_surfaceListener = {
156  enterCallback,
157  leaveCallback
158 };
159 #endif
160 
161 void Surface::Private::enterCallback(void *data, wl_surface *surface, wl_output *output)
162 {
163  Q_UNUSED(surface);
164  auto s = reinterpret_cast<Surface::Private*>(data);
165  Output *o = Output::get(output);
166  if (!o) {
167  return;
168  }
169  s->outputs << o;
170  QObject::connect(o, &Output::removed, s->q, [s, o]() {
171  if (!s->outputs.contains(o)) {
172  return;
173  }
174  s->outputs.removeOne(o);
175  s->q->outputLeft(o);
176  });
177  emit s->q->outputEntered(o);
178 }
179 
180 void Surface::Private::leaveCallback(void *data, wl_surface *surface, wl_output *output)
181 {
182  Q_UNUSED(surface);
183  auto s = reinterpret_cast<Surface::Private*>(data);
184  Output *o = Output::get(output);
185  if (!o) {
186  return;
187  }
188  s->outputs.removeOne(o);
189  emit s->q->outputLeft(o);
190 }
191 
192 void Surface::Private::setupFrameCallback()
193 {
194  Q_ASSERT(!frameCallbackInstalled);
195  wl_callback *callback = wl_surface_frame(surface);
196  wl_callback_add_listener(callback, &s_listener, this);
197  frameCallbackInstalled = true;
198 }
199 
201 {
202  Q_ASSERT(isValid());
203  d->setupFrameCallback();
204 }
205 
206 void Surface::commit(Surface::CommitFlag flag)
207 {
208  Q_ASSERT(isValid());
209  if (flag == CommitFlag::FrameCallback) {
210  setupFrameCallback();
211  }
212  wl_surface_commit(d->surface);
213 }
214 
215 void Surface::damage(const QRegion &region)
216 {
217  for (const QRect &rect : region) {
218  damage(rect);
219  }
220 }
221 
222 void Surface::damage(const QRect &rect)
223 {
224  Q_ASSERT(isValid());
225  wl_surface_damage(d->surface, rect.x(), rect.y(), rect.width(), rect.height());
226 }
227 
228 void Surface::damageBuffer(const QRegion &region)
229 {
230  for (const QRect &r : region) {
231  damageBuffer(r);
232  }
233 }
234 
235 void Surface::damageBuffer(const QRect &rect)
236 {
237  Q_ASSERT(isValid());
238  wl_surface_damage_buffer(d->surface, rect.x(), rect.y(), rect.width(), rect.height());
239 }
240 
241 void Surface::attachBuffer(wl_buffer *buffer, const QPoint &offset)
242 {
243  Q_ASSERT(isValid());
244  wl_surface_attach(d->surface, buffer, offset.x(), offset.y());
245 }
246 
247 void Surface::attachBuffer(Buffer *buffer, const QPoint &offset)
248 {
249  attachBuffer(buffer ? buffer->buffer() : nullptr, offset);
250 }
251 
252 void Surface::attachBuffer(Buffer::Ptr buffer, const QPoint &offset)
253 {
254  attachBuffer(buffer.toStrongRef().data(), offset);
255 }
256 
257 void Surface::setInputRegion(const Region *region)
258 {
259  Q_ASSERT(isValid());
260  if (region) {
261  wl_surface_set_input_region(d->surface, *region);
262  } else {
263  wl_surface_set_input_region(d->surface, nullptr);
264  }
265 }
266 
267 void Surface::setOpaqueRegion(const Region *region)
268 {
269  Q_ASSERT(isValid());
270  if (region) {
271  wl_surface_set_opaque_region(d->surface, *region);
272  } else {
273  wl_surface_set_opaque_region(d->surface, nullptr);
274  }
275 }
276 
277 void Surface::setSize(const QSize &size)
278 {
279  if (d->size == size) {
280  return;
281  }
282  d->size = size;
283  emit sizeChanged(d->size);
284 }
285 
286 Surface *Surface::get(wl_surface *native)
287 {
288  auto it = std::find_if(Private::s_surfaces.constBegin(), Private::s_surfaces.constEnd(),
289  [native](Surface *s) {
290  return s->d->surface == native;
291  }
292  );
293  if (it != Private::s_surfaces.constEnd()) {
294  return *(it);
295  }
296  return nullptr;
297 }
298 
300 {
301  return Private::s_surfaces;
302 }
303 
304 bool Surface::isValid() const
305 {
306  return d->surface.isValid();
307 }
308 
309 QSize Surface::size() const
310 {
311  return d->size;
312 }
313 
314 Surface::operator wl_surface*()
315 {
316  return d->surface;
317 }
318 
319 Surface::operator wl_surface*() const
320 {
321  return d->surface;
322 }
323 
324 quint32 Surface::id() const
325 {
326  wl_surface *s = *this;
327  return wl_proxy_get_id(reinterpret_cast<wl_proxy*>(s));
328 }
329 
330 qint32 Surface::scale() const
331 {
332  return d->scale;
333 }
334 
335 void Surface::setScale(qint32 scale)
336 {
337  d->scale = scale;
338  wl_surface_set_buffer_scale(d->surface, scale);
339 }
340 
342 {
343  return d->outputs;
344 }
345 
346 }
347 }
void damageBuffer(const QRect &rect)
Mark rect in buffer coordinates as damaged for the next frame.
Definition: surface.cpp:235
void setup(wl_surface *surface)
Setup this Surface to manage the surface.
Definition: surface.cpp:121
void setOpaqueRegion(const Region *region=nullptr)
Sets the opaque region to region.
Definition: surface.cpp:267
static Output * get(wl_output *native)
Definition: output.cpp:375
static Surface * fromWindow(QWindow *window)
Creates a Surface for the given window.
Definition: surface.cpp:72
void destroy()
Destroys the data held by this Surface.
Definition: surface.cpp:116
void setInputRegion(const Region *region=nullptr)
Sets the input region to region.
Definition: surface.cpp:257
bool isValid() const
Definition: surface.cpp:304
Wrapper class for wl_buffer interface.
Definition: buffer.h:31
int height() const const
int x() const const
int y() const const
CommitFlag
Flags to be added to commit.
Definition: surface.h:131
Wrapper for the wl_output interface.
Definition: output.h:55
QSharedPointer< T > toStrongRef() const const
void create()
int x() const const
int y() const const
void setupFrameCallback()
Registers a frame rendered callback.
Definition: surface.cpp:200
void setScale(qint32 scale)
The purpose of this method is to allow to supply higher resolution buffer data for use on high resolu...
Definition: surface.cpp:335
qint32 scale() const
Definition: surface.cpp:330
QPointer< Surface > surface() const
Definition: subsurface.cpp:86
Wrapper for the wl_surface interface.
Definition: surface.h:44
static const QList< Surface * > & all()
All Surfaces which are currently created.
Definition: surface.cpp:299
QVector< Output * > outputs() const
Definition: surface.cpp:341
static Surface * fromQtWinId(WId wid)
Creates a Surface for the given winId.
Definition: surface.cpp:94
quint32 id() const
Definition: surface.cpp:324
int width() const const
void damage(const QRect &rect)
Mark rect as damaged for the next frame.
Definition: surface.cpp:222
void removed()
The corresponding global for this interface on the Registry got removed.
static Surface * get(wl_surface *native)
Definition: surface.cpp:286
void attachBuffer(wl_buffer *buffer, const QPoint &offset=QPoint())
Attaches the buffer to this Surface for the next frame.
Definition: surface.cpp:241
void release()
Releases the wl_surface interface.
Definition: surface.cpp:111
void release()
Releases the wl_subsurface interface.
Definition: subsurface.cpp:76
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QObject * parent() const const
Wrapper for the wl_region interface.
Definition: region.h:32
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Sun Sep 20 2020 22:49:47 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.