KWin
Loading...
Searching...
No Matches
subcompositor.cpp
Go to the documentation of this file.
1/*
2 SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
3 SPDX-FileCopyrightText: 2020 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
4
5 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
6*/
7#include "subcompositor.h"
8#include "display.h"
9#include "subsurface_p.h"
10#include "surface_p.h"
11#include "transaction.h"
12
13namespace KWin
14{
15static const int s_version = 1;
16
18 : QtWaylandServer::wl_subcompositor(*display, s_version)
19 , q(q)
20{
21}
22
24{
25 wl_resource_destroy(resource->handle);
26}
27
29 uint32_t id,
30 ::wl_resource *surface_resource,
31 ::wl_resource *parent_resource)
32{
33 SurfaceInterface *surface = SurfaceInterface::get(surface_resource);
34 SurfaceInterface *parent = SurfaceInterface::get(parent_resource);
35
36 if (!surface) {
37 wl_resource_post_error(resource->handle, error_bad_surface, "no surface");
38 return;
39 }
40 if (!parent) {
41 wl_resource_post_error(resource->handle, error_bad_surface, "no parent");
42 return;
43 }
44
45 if (const SurfaceRole *role = surface->role()) {
46 if (role != SubSurfaceInterface::role()) {
47 wl_resource_post_error(resource->handle, error_bad_surface, "the surface already has a role assigned %s", role->name().constData());
48 return;
49 }
50 } else {
52 }
53
54 if (surface == parent) {
55 wl_resource_post_error(resource->handle, error_bad_surface, "wl_surface@%d cannot be its own parent", wl_resource_get_id(surface_resource));
56 return;
57 }
58 if (parent->subSurface() && parent->subSurface()->mainSurface() == surface) {
59 wl_resource_post_error(resource->handle, error_bad_surface, "wl_surface@%d is an ancestor of parent", wl_resource_get_id(surface_resource));
60 return;
61 }
62
63 wl_resource *subsurfaceResource = wl_resource_create(resource->client(), &wl_subsurface_interface, resource->version(), id);
64 if (!subsurfaceResource) {
65 wl_resource_post_no_memory(resource->handle);
66 return;
67 }
68
69 Q_EMIT q->subSurfaceCreated(new SubSurfaceInterface(surface, parent, subsurfaceResource));
70}
71
73 : QObject(parent)
74 , d(new SubCompositorInterfacePrivate(display, this))
75
76{
77}
78
82
84{
85 return subsurface->d.get();
86}
87
89 : QtWaylandServer::wl_subsurface(resource)
90 , q(q)
91 , surface(surface)
92 , parent(parent)
93{
94}
95
97{
98 delete q;
99}
100
102{
103 wl_resource_destroy(resource->handle);
104}
105
106void SubSurfaceInterfacePrivate::subsurface_set_position(Resource *resource, int32_t x, int32_t y)
107{
108 if (!parent) {
109 wl_resource_post_error(resource->handle, error_bad_surface, "no parent");
110 return;
111 }
112
114
115 parentPrivate->pending->subsurface.position[q] = QPoint(x, y);
116 parentPrivate->pending->subsurfacePositionChanged = true;
117}
118
119void SubSurfaceInterfacePrivate::subsurface_place_above(Resource *resource, struct ::wl_resource *sibling_resource)
120{
121 SurfaceInterface *sibling = SurfaceInterface::get(sibling_resource);
122 if (!sibling) {
123 wl_resource_post_error(resource->handle, error_bad_surface, "no sibling");
124 return;
125 }
126 if (!parent) {
127 wl_resource_post_error(resource->handle, error_bad_surface, "no parent");
128 return;
129 }
130
132 if (!parentPrivate->raiseChild(q, sibling)) {
133 wl_resource_post_error(resource->handle, error_bad_surface, "incorrect sibling");
134 }
135}
136
137void SubSurfaceInterfacePrivate::subsurface_place_below(Resource *resource, struct ::wl_resource *sibling_resource)
138{
139 SurfaceInterface *sibling = SurfaceInterface::get(sibling_resource);
140 if (!sibling) {
141 wl_resource_post_error(resource->handle, error_bad_surface, "no sibling");
142 return;
143 }
144 if (!parent) {
145 wl_resource_post_error(resource->handle, error_bad_surface, "no parent");
146 return;
147 }
148
150 if (!parentPrivate->lowerChild(q, sibling)) {
151 wl_resource_post_error(resource->handle, error_bad_surface, "incorrect sibling");
152 }
153}
154
163
175
176SubSurfaceInterface::SubSurfaceInterface(SurfaceInterface *surface, SurfaceInterface *parent, wl_resource *resource)
177 : d(new SubSurfaceInterfacePrivate(this, surface, parent, resource))
178{
181 surfacePrivate->subsurface.handle = this;
182 parentPrivate->addChild(this);
183
184 connect(surface, &SurfaceInterface::destroyed, this, [this]() {
185 delete this;
186 });
187}
188
190{
191 if (d->parent) {
192 SurfaceInterfacePrivate *parentPrivate = SurfaceInterfacePrivate::get(d->parent);
193 parentPrivate->removeChild(this);
194 }
195 if (d->surface) {
196 SurfaceInterfacePrivate *surfacePrivate = SurfaceInterfacePrivate::get(d->surface);
197 surfacePrivate->subsurface.handle = nullptr;
198 surfacePrivate->subsurface.transaction.reset();
199 }
200}
201
203{
204 static SurfaceRole role(QByteArrayLiteral("wl_subsurface"));
205 return &role;
206}
207
209{
210 return d->position;
211}
212
214{
215 return d->surface;
216}
217
219{
220 return d->parent;
221}
222
224{
225 return d->mode;
226}
227
229{
230 if (d->mode == Mode::Synchronized) {
231 return true;
232 }
233 if (!d->parent) {
234 // that shouldn't happen, but let's assume false
235 return false;
236 }
237 if (d->parent->subSurface()) {
238 // follow parent's mode
239 return d->parent->subSurface()->isSynchronized();
240 }
241 // parent is no subsurface, thus parent is in desync mode and this surface is in desync mode
242 return false;
243}
244
246{
247 if (!d->parent) {
248 return nullptr;
249 }
250 SurfaceInterfacePrivate *parentPrivate = SurfaceInterfacePrivate::get(d->parent);
251 if (parentPrivate->subsurface.handle) {
252 return parentPrivate->subsurface.handle->mainSurface();
253 }
254 return d->parent;
255}
256
257void SubSurfaceInterface::parentDesynchronized()
258{
260 return;
261 }
262
263 auto surfacePrivate = SurfaceInterfacePrivate::get(d->surface);
264 if (surfacePrivate->subsurface.transaction) {
265 surfacePrivate->subsurface.transaction->commit();
266 surfacePrivate->subsurface.transaction.release();
267 }
268
269 const auto below = d->surface->below();
270 for (SubSurfaceInterface *child : below) {
271 child->parentDesynchronized();
272 }
273
274 const auto above = d->surface->above();
275 for (SubSurfaceInterface *child : above) {
276 child->parentDesynchronized();
277 }
278}
279
280void SubSurfaceInterface::parentApplyState(quint32 serial)
281{
282 auto parentPrivate = SurfaceInterfacePrivate::get(d->parent);
283 if (parentPrivate->current->subsurfacePositionChanged) {
284 const QPoint &pos = parentPrivate->current->subsurface.position[this];
285 if (d->position != pos) {
286 d->position = pos;
287 Q_EMIT positionChanged(pos);
288 }
289 }
290}
291
292} // namespace KWin
293
294#include "moc_subcompositor.cpp"
Class holding the Wayland server display loop.
Definition display.h:34
void subSurfaceCreated(KWin::SubSurfaceInterface *subsurface)
SubCompositorInterface(Display *display, QObject *parent=nullptr)
void subcompositor_get_subsurface(Resource *resource, uint32_t id, struct ::wl_resource *surface_resource, struct ::wl_resource *parent_resource) override
SubCompositorInterfacePrivate(Display *display, SubCompositorInterface *q)
void subcompositor_destroy(Resource *resource) override
SubCompositorInterface * q
static SurfaceRole * role()
SurfaceInterface * parentSurface() const
SurfaceInterface * surface() const
void positionChanged(const QPoint &position)
void modeChanged(KWin::SubSurfaceInterface::Mode mode)
SurfaceInterface * mainSurface() const
QPointer< SurfaceInterface > parent
static SubSurfaceInterfacePrivate * get(SubSurfaceInterface *subsurface)
void subsurface_set_desync(Resource *resource) override
SubSurfaceInterfacePrivate(SubSurfaceInterface *q, SurfaceInterface *surface, SurfaceInterface *parent, ::wl_resource *resource)
void subsurface_place_above(Resource *resource, struct ::wl_resource *sibling_resource) override
void subsurface_set_sync(Resource *resource) override
void subsurface_destroy(Resource *resource) override
void subsurface_destroy_resource(Resource *resource) override
void subsurface_set_position(Resource *resource, int32_t x, int32_t y) override
QPointer< SurfaceInterface > surface
SubSurfaceInterface::Mode mode
void subsurface_place_below(Resource *resource, struct ::wl_resource *sibling_resource) override
Resource representing a wl_surface.
Definition surface.h:80
static SurfaceInterface * get(wl_resource *native)
Definition surface.cpp:819
SurfaceRole * role() const
Definition surface.cpp:429
SubSurfaceInterface * subSurface() const
Definition surface.cpp:845
void setRole(SurfaceRole *role)
Definition surface.cpp:434
bool raiseChild(SubSurfaceInterface *subsurface, SurfaceInterface *anchor)
Definition surface.cpp:123
std::unique_ptr< Transaction > transaction
Definition surface_p.h:177
std::unique_ptr< SurfaceState > current
Definition surface_p.h:136
void removeChild(SubSurfaceInterface *subsurface)
Definition surface.cpp:96
std::unique_ptr< SurfaceState > pending
Definition surface_p.h:137
static SurfaceInterfacePrivate * get(SurfaceInterface *surface)
Definition surface_p.h:99
void addChild(SubSurfaceInterface *subsurface)
Definition surface.cpp:63
SubSurfaceInterface * handle
Definition surface_p.h:176
struct KWin::SurfaceInterfacePrivate::@30 subsurface
bool lowerChild(SubSurfaceInterface *subsurface, SurfaceInterface *anchor)
Definition surface.cpp:150