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 "output.h"
8 #include "region.h"
9 #include "surface_p.h"
10 #include "wayland_pointer_p.h"
11 
12 #include <QGuiApplication>
13 #include <QRegion>
14 #include <QVector>
15 // Wayland
16 #include <wayland-client-protocol.h>
17 
18 namespace KWayland
19 {
20 namespace Client
21 {
22 
23 QList<Surface *> Surface::Private::s_surfaces = QList<Surface *>();
24 
25 Surface::Private::Private(Surface *q)
26  : q(q)
27 {
28 }
29 
30 Surface::Surface(QObject *parent)
31  : QObject(parent)
32  , d(new Private(this))
33 {
34  Private::s_surfaces << this;
35 }
36 
37 Surface::~Surface()
38 {
39  Private::s_surfaces.removeAll(this);
40  release();
41 }
42 
43 
45 {
46  d->surface.release();
47 }
48 
50 {
51  d->surface.destroy();
52 }
53 
54 void Surface::setup(wl_surface *surface)
55 {
56  d->setup(surface);
57 }
58 
59 void Surface::Private::setup(wl_surface *s)
60 {
61  Q_ASSERT(s);
62  Q_ASSERT(!surface);
63  surface.setup(s);
64  wl_surface_add_listener(s, &s_surfaceListener, this);
65 }
66 
67 void Surface::Private::frameCallback(void *data, wl_callback *callback, uint32_t time)
68 {
69  Q_UNUSED(time)
70  auto s = reinterpret_cast<Surface::Private *>(data);
71  if (callback) {
72  wl_callback_destroy(callback);
73  }
74  s->handleFrameCallback();
75 }
76 
77 void Surface::Private::handleFrameCallback()
78 {
79  frameCallbackInstalled = false;
80  Q_EMIT q->frameRendered();
81 }
82 
83 #ifndef K_DOXYGEN
84 const struct wl_callback_listener Surface::Private::s_listener = {frameCallback};
85 
86 const struct wl_surface_listener Surface::Private::s_surfaceListener = {enterCallback, leaveCallback};
87 #endif
88 
89 void Surface::Private::removeOutput(Output *o)
90 {
91  if (o && outputs.removeOne(o)) {
92  Q_EMIT q->outputLeft(o);
93  }
94 }
95 
96 void Surface::Private::enterCallback(void *data, wl_surface *surface, wl_output *output)
97 {
98  Q_UNUSED(surface);
99  auto s = reinterpret_cast<Surface::Private *>(data);
100  Output *o = Output::get(output);
101  if (!o) {
102  return;
103  }
104  s->outputs << o;
105  QObject::connect(o, &Output::removed, s->q, [s, o]() {
106  s->removeOutput(o);
107  });
108  Q_EMIT s->q->outputEntered(o);
109 }
110 
111 void Surface::Private::leaveCallback(void *data, wl_surface *surface, wl_output *output)
112 {
113  Q_UNUSED(surface);
114  auto s = reinterpret_cast<Surface::Private *>(data);
115  s->removeOutput(Output::get(output));
116 }
117 
118 void Surface::Private::setupFrameCallback()
119 {
120  Q_ASSERT(!frameCallbackInstalled);
121  wl_callback *callback = wl_surface_frame(surface);
122  wl_callback_add_listener(callback, &s_listener, this);
123  frameCallbackInstalled = true;
124 }
125 
127 {
128  Q_ASSERT(isValid());
129  d->setupFrameCallback();
130 }
131 
132 void Surface::commit(Surface::CommitFlag flag)
133 {
134  Q_ASSERT(isValid());
135  if (flag == CommitFlag::FrameCallback) {
137  }
138  wl_surface_commit(d->surface);
139 }
140 
141 void Surface::damage(const QRegion &region)
142 {
143  for (const QRect &rect : region) {
144  damage(rect);
145  }
146 }
147 
148 void Surface::damage(const QRect &rect)
149 {
150  Q_ASSERT(isValid());
151  wl_surface_damage(d->surface, rect.x(), rect.y(), rect.width(), rect.height());
152 }
153 
154 void Surface::damageBuffer(const QRegion &region)
155 {
156  for (const QRect &r : region) {
157  damageBuffer(r);
158  }
159 }
160 
161 void Surface::damageBuffer(const QRect &rect)
162 {
163  Q_ASSERT(isValid());
164  wl_surface_damage_buffer(d->surface, rect.x(), rect.y(), rect.width(), rect.height());
165 }
166 
167 void Surface::attachBuffer(wl_buffer *buffer, const QPoint &offset)
168 {
169  Q_ASSERT(isValid());
170  wl_surface_attach(d->surface, buffer, offset.x(), offset.y());
171 }
172 
173 void Surface::attachBuffer(Buffer *buffer, const QPoint &offset)
174 {
175  attachBuffer(buffer ? buffer->buffer() : nullptr, offset);
176 }
177 
178 void Surface::attachBuffer(Buffer::Ptr buffer, const QPoint &offset)
179 {
180  attachBuffer(buffer.toStrongRef().data(), offset);
181 }
182 
183 void Surface::setInputRegion(const Region *region)
184 {
185  Q_ASSERT(isValid());
186  if (region) {
187  wl_surface_set_input_region(d->surface, *region);
188  } else {
189  wl_surface_set_input_region(d->surface, nullptr);
190  }
191 }
192 
193 void Surface::setOpaqueRegion(const Region *region)
194 {
195  Q_ASSERT(isValid());
196  if (region) {
197  wl_surface_set_opaque_region(d->surface, *region);
198  } else {
199  wl_surface_set_opaque_region(d->surface, nullptr);
200  }
201 }
202 
203 void Surface::setSize(const QSize &size)
204 {
205  if (d->size == size) {
206  return;
207  }
208  d->size = size;
209  Q_EMIT sizeChanged(d->size);
210 }
211 
212 Surface *Surface::get(wl_surface *native)
213 {
214  auto it = std::find_if(Private::s_surfaces.constBegin(), Private::s_surfaces.constEnd(), [native](Surface *s) {
215  return s->d->surface == native;
216  });
217  if (it != Private::s_surfaces.constEnd()) {
218  return *(it);
219  }
220  return nullptr;
221 }
222 
224 {
225  return Private::s_surfaces;
226 }
227 
228 bool Surface::isValid() const
229 {
230  return d->surface.isValid();
231 }
232 
233 QSize Surface::size() const
234 {
235  return d->size;
236 }
237 
238 Surface::operator wl_surface *()
239 {
240  return d->surface;
241 }
242 
243 Surface::operator wl_surface *() const
244 {
245  return d->surface;
246 }
247 
248 quint32 Surface::id() const
249 {
250  wl_surface *s = *this;
251  return wl_proxy_get_id(reinterpret_cast<wl_proxy *>(s));
252 }
253 
254 qint32 Surface::scale() const
255 {
256  return d->scale;
257 }
258 
259 void Surface::setScale(qint32 scale)
260 {
261  d->scale = scale;
262  wl_surface_set_buffer_scale(d->surface, scale);
263 }
264 
266 {
267  return d->outputs;
268 }
269 
270 }
271 }
Q_EMITQ_EMIT
Wrapper for the wl_surface interface.
Definition: surface.h:43
static Output * get(wl_output *native)
Definition: output.cpp:414
static Surface * get(wl_surface *native)
Definition: surface.cpp:212
int width() const const
int x() const const
int y() const const
void setInputRegion(const Region *region=nullptr)
Sets the input region to region.
Definition: surface.cpp:183
quint32 id() const
Definition: surface.cpp:248
int x() const const
int y() const const
QVector< Output * > outputs() const
Definition: surface.cpp:265
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
Wrapper class for wl_buffer interface.
Definition: buffer.h:30
qint32 scale() const
Definition: surface.cpp:254
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:259
static const QList< Surface * > & all()
All Surfaces which are currently created.
Definition: surface.cpp:223
void destroy()
Destroys the data held by this Surface.
Definition: surface.cpp:49
void setup(wl_surface *surface)
Setup this Surface to manage the surface.
Definition: surface.cpp:54
int height() const const
void release()
Releases the wl_surface interface.
Definition: surface.cpp:44
CommitFlag
Flags to be added to commit.
Definition: surface.h:133
void setOpaqueRegion(const Region *region=nullptr)
Sets the opaque region to region.
Definition: surface.cpp:193
void removed()
The corresponding global for this interface on the Registry got removed.
void damageBuffer(const QRect &rect)
Mark rect in buffer coordinates as damaged for the next frame.
Definition: surface.cpp:161
void damage(const QRect &rect)
Mark rect as damaged for the next frame.
Definition: surface.cpp:148
QSharedPointer< T > toStrongRef() const const
void attachBuffer(wl_buffer *buffer, const QPoint &offset=QPoint())
Attaches the buffer to this Surface for the next frame.
Definition: surface.cpp:167
void setupFrameCallback()
Registers a frame rendered callback.
Definition: surface.cpp:126
Wrapper for the wl_region interface.
Definition: region.h:31
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Wed Feb 8 2023 03:59:22 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.