1/*
2 SPDX-FileCopyrightText: 2017 David Edmundson <davidedmundson@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
5*/
6#include "event_queue.h"
7#include "output.h"
8#include "seat.h"
9#include "surface.h"
10#include "wayland_pointer_p.h"
11#include "xdgshell_p.h"
12#include <wayland-xdg-shell-v6-client-protocol.h>
13
14#include <QDebug>
15
16namespace KWayland
17{
18namespace Client
19{
20class XdgShellUnstableV6::Private : public XdgShell::Private
21{
22public:
23 void setupV6(zxdg_shell_v6 *shell) override;
24 void release() override;
25 void destroy() override;
26 bool isValid() const override;
27 XdgShellSurface *getXdgSurface(Surface *surface, QObject *parent) override;
28
29 XdgShellPopup *getXdgPopup(Surface *surface, XdgShellSurface *parentSurface, const XdgPositioner &positioner, QObject *parent) override;
30 XdgShellPopup *getXdgPopup(Surface *surface, XdgShellPopup *parentSurface, const XdgPositioner &positioner, QObject *parent) override;
31
32 using XdgShell::Private::operator xdg_wm_base *;
33 using XdgShell::Private::operator xdg_shell *;
34 operator zxdg_shell_v6 *() override
35 {
36 return xdgshellv6;
37 }
38 operator zxdg_shell_v6 *() const override
39 {
40 return xdgshellv6;
41 }
42
43private:
44 XdgShellPopup *internalGetXdgPopup(Surface *surface, zxdg_surface_v6 *parentSurface, const XdgPositioner &positioner, QObject *parent);
45 static void pingCallback(void *data, struct zxdg_shell_v6 *shell, uint32_t serial);
46
47 WaylandPointer<zxdg_shell_v6, zxdg_shell_v6_destroy> xdgshellv6;
48 static const struct zxdg_shell_v6_listener s_shellListener;
49};
50
51const struct zxdg_shell_v6_listener XdgShellUnstableV6::Private::s_shellListener = {
52 .ping: pingCallback,
53};
54
55void XdgShellUnstableV6::Private::pingCallback(void *data, struct zxdg_shell_v6 *shell, uint32_t serial)
56{
57 Q_UNUSED(data)
58 zxdg_shell_v6_pong(zxdg_shell_v6: shell, serial);
59}
60
61void XdgShellUnstableV6::Private::setupV6(zxdg_shell_v6 *shell)
62{
63 Q_ASSERT(shell);
64 Q_ASSERT(!xdgshellv6);
65 xdgshellv6.setup(pointer: shell);
66 zxdg_shell_v6_add_listener(zxdg_shell_v6: shell, listener: &s_shellListener, data: this);
67}
68
69void XdgShellUnstableV6::Private::release()
70{
71 xdgshellv6.release();
72}
73
74void XdgShellUnstableV6::Private::destroy()
75{
76 xdgshellv6.destroy();
77}
78
79bool XdgShellUnstableV6::Private::isValid() const
80{
81 return xdgshellv6.isValid();
82}
83
84XdgShellSurface *XdgShellUnstableV6::Private::getXdgSurface(Surface *surface, QObject *parent)
85{
86 Q_ASSERT(isValid());
87 auto ss = zxdg_shell_v6_get_xdg_surface(zxdg_shell_v6: xdgshellv6, surface: *surface);
88
89 if (!ss) {
90 return nullptr;
91 }
92
93 auto s = new XdgTopLevelUnstableV6(parent);
94 auto toplevel = zxdg_surface_v6_get_toplevel(zxdg_surface_v6: ss);
95 if (queue) {
96 queue->addProxy(proxy: ss);
97 queue->addProxy(proxy: toplevel);
98 }
99 s->setup(xdgsurfacev6: ss, toplevel);
100 return s;
101}
102
103XdgShellPopup *XdgShellUnstableV6::Private::getXdgPopup(Surface *surface, XdgShellSurface *parentSurface, const XdgPositioner &positioner, QObject *parent)
104{
105 return internalGetXdgPopup(surface, parentSurface: *parentSurface, positioner, parent);
106}
107
108XdgShellPopup *XdgShellUnstableV6::Private::getXdgPopup(Surface *surface, XdgShellPopup *parentSurface, const XdgPositioner &positioner, QObject *parent)
109{
110 return internalGetXdgPopup(surface, parentSurface: *parentSurface, positioner, parent);
111}
112
113XdgShellPopup *
114XdgShellUnstableV6::Private::internalGetXdgPopup(Surface *surface, zxdg_surface_v6 *parentSurface, const XdgPositioner &positioner, QObject *parent)
115{
116 Q_ASSERT(isValid());
117 auto ss = zxdg_shell_v6_get_xdg_surface(zxdg_shell_v6: xdgshellv6, surface: *surface);
118 if (!ss) {
119 return nullptr;
120 }
121
122 auto p = zxdg_shell_v6_create_positioner(zxdg_shell_v6: xdgshellv6);
123
124 auto anchorRect = positioner.anchorRect();
125 zxdg_positioner_v6_set_anchor_rect(zxdg_positioner_v6: p, x: anchorRect.x(), y: anchorRect.y(), width: anchorRect.width(), height: anchorRect.height());
126
127 QSize initialSize = positioner.initialSize();
128 zxdg_positioner_v6_set_size(zxdg_positioner_v6: p, width: initialSize.width(), height: initialSize.height());
129
130 QPoint anchorOffset = positioner.anchorOffset();
131 if (!anchorOffset.isNull()) {
132 zxdg_positioner_v6_set_offset(zxdg_positioner_v6: p, x: anchorOffset.x(), y: anchorOffset.y());
133 }
134
135 uint32_t anchor = 0;
136 if (positioner.anchorEdge().testFlag(flag: Qt::LeftEdge)) {
137 anchor |= ZXDG_POSITIONER_V6_ANCHOR_LEFT;
138 }
139 if (positioner.anchorEdge().testFlag(flag: Qt::TopEdge)) {
140 anchor |= ZXDG_POSITIONER_V6_ANCHOR_TOP;
141 }
142 if (positioner.anchorEdge().testFlag(flag: Qt::RightEdge)) {
143 anchor |= ZXDG_POSITIONER_V6_ANCHOR_RIGHT;
144 }
145 if (positioner.anchorEdge().testFlag(flag: Qt::BottomEdge)) {
146 anchor |= ZXDG_POSITIONER_V6_ANCHOR_BOTTOM;
147 }
148 if (anchor != 0) {
149 zxdg_positioner_v6_set_anchor(zxdg_positioner_v6: p, anchor);
150 }
151
152 uint32_t gravity = 0;
153 if (positioner.gravity().testFlag(flag: Qt::LeftEdge)) {
154 gravity |= ZXDG_POSITIONER_V6_GRAVITY_LEFT;
155 }
156 if (positioner.gravity().testFlag(flag: Qt::TopEdge)) {
157 gravity |= ZXDG_POSITIONER_V6_GRAVITY_TOP;
158 }
159 if (positioner.gravity().testFlag(flag: Qt::RightEdge)) {
160 gravity |= ZXDG_POSITIONER_V6_GRAVITY_RIGHT;
161 }
162 if (positioner.gravity().testFlag(flag: Qt::BottomEdge)) {
163 gravity |= ZXDG_POSITIONER_V6_GRAVITY_BOTTOM;
164 }
165 if (gravity != 0) {
166 zxdg_positioner_v6_set_gravity(zxdg_positioner_v6: p, gravity);
167 }
168
169 uint32_t constraint = 0;
170
171 if (positioner.constraints().testFlag(flag: XdgPositioner::Constraint::SlideX)) {
172 constraint |= ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_SLIDE_X;
173 }
174 if (positioner.constraints().testFlag(flag: XdgPositioner::Constraint::SlideY)) {
175 constraint |= ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_SLIDE_Y;
176 }
177 if (positioner.constraints().testFlag(flag: XdgPositioner::Constraint::FlipX)) {
178 constraint |= ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_FLIP_X;
179 }
180 if (positioner.constraints().testFlag(flag: XdgPositioner::Constraint::FlipY)) {
181 constraint |= ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_FLIP_Y;
182 }
183 if (positioner.constraints().testFlag(flag: XdgPositioner::Constraint::ResizeX)) {
184 constraint |= ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_RESIZE_X;
185 }
186 if (positioner.constraints().testFlag(flag: XdgPositioner::Constraint::ResizeY)) {
187 constraint |= ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_RESIZE_Y;
188 }
189 if (constraint != 0) {
190 zxdg_positioner_v6_set_constraint_adjustment(zxdg_positioner_v6: p, constraint_adjustment: constraint);
191 }
192
193 XdgShellPopup *s = new XdgShellPopupUnstableV6(parent);
194 auto popup = zxdg_surface_v6_get_popup(zxdg_surface_v6: ss, parent: parentSurface, positioner: p);
195 if (queue) {
196 // deliberately not adding the positioner because the positioner has no events sent to it
197 queue->addProxy(proxy: ss);
198 queue->addProxy(proxy: popup);
199 }
200 s->setup(xdgsurfacev6: ss, xdgpopup6: popup);
201
202 zxdg_positioner_v6_destroy(zxdg_positioner_v6: p);
203
204 return s;
205}
206
207XdgShellUnstableV6::XdgShellUnstableV6(QObject *parent)
208 : XdgShell(new Private, parent)
209{
210}
211
212XdgShellUnstableV6::~XdgShellUnstableV6() = default;
213
214// A top level wraps both xdg_surface_v6 and xdg_top_level into the public API XdgShelllSurface
215class XdgTopLevelUnstableV6::Private : public XdgShellSurface::Private
216{
217public:
218 Private(XdgShellSurface *q);
219 WaylandPointer<zxdg_toplevel_v6, zxdg_toplevel_v6_destroy> xdgtoplevelv6;
220 WaylandPointer<zxdg_surface_v6, zxdg_surface_v6_destroy> xdgsurfacev6;
221
222 void setupV6(zxdg_surface_v6 *surface, zxdg_toplevel_v6 *toplevel) override;
223 void release() override;
224 void destroy() override;
225 bool isValid() const override;
226
227 using XdgShellSurface::Private::operator xdg_surface *;
228 using XdgShellSurface::Private::operator xdg_toplevel *;
229 operator zxdg_surface_v6 *() override
230 {
231 return xdgsurfacev6;
232 }
233 operator zxdg_surface_v6 *() const override
234 {
235 return xdgsurfacev6;
236 }
237 operator zxdg_toplevel_v6 *() override
238 {
239 return xdgtoplevelv6;
240 }
241 operator zxdg_toplevel_v6 *() const override
242 {
243 return xdgtoplevelv6;
244 }
245
246 void setTransientFor(XdgShellSurface *parent) override;
247 void setTitle(const QString &title) override;
248 void setAppId(const QByteArray &appId) override;
249 void showWindowMenu(Seat *seat, quint32 serial, qint32 x, qint32 y) override;
250 void move(Seat *seat, quint32 serial) override;
251 void resize(Seat *seat, quint32 serial, Qt::Edges edges) override;
252 void ackConfigure(quint32 serial) override;
253 void setMaximized() override;
254 void unsetMaximized() override;
255 void setFullscreen(Output *output) override;
256 void unsetFullscreen() override;
257 void setMinimized() override;
258 void setMaxSize(const QSize &size) override;
259 void setMinSize(const QSize &size) override;
260
261private:
262 QSize pendingSize;
263 States pendingState;
264
265 static void configureCallback(void *data, struct zxdg_toplevel_v6 *xdg_toplevel, int32_t width, int32_t height, struct wl_array *state);
266 static void closeCallback(void *data, zxdg_toplevel_v6 *xdg_toplevel);
267 static void surfaceConfigureCallback(void *data, zxdg_surface_v6 *xdg_surface, uint32_t serial);
268
269 static const struct zxdg_toplevel_v6_listener s_toplevelListener;
270 static const struct zxdg_surface_v6_listener s_surfaceListener;
271};
272
273const struct zxdg_toplevel_v6_listener XdgTopLevelUnstableV6::Private::s_toplevelListener = {.configure: configureCallback, .close: closeCallback};
274
275const struct zxdg_surface_v6_listener XdgTopLevelUnstableV6::Private::s_surfaceListener = {.configure: surfaceConfigureCallback};
276
277void XdgTopLevelUnstableV6::Private::surfaceConfigureCallback(void *data, struct zxdg_surface_v6 *surface, uint32_t serial)
278{
279 Q_UNUSED(surface)
280 auto s = reinterpret_cast<Private *>(data);
281 s->q->configureRequested(size: s->pendingSize, states: s->pendingState, serial);
282 if (!s->pendingSize.isNull()) {
283 s->q->setSize(s->pendingSize);
284 s->pendingSize = QSize();
285 }
286 s->pendingState = {};
287}
288
289void XdgTopLevelUnstableV6::Private::configureCallback(void *data, struct zxdg_toplevel_v6 *xdg_toplevel, int32_t width, int32_t height, struct wl_array *state)
290{
291 Q_UNUSED(xdg_toplevel)
292 auto s = reinterpret_cast<Private *>(data);
293 States states;
294
295 uint32_t *statePtr = reinterpret_cast<uint32_t *>(state->data);
296 for (size_t i = 0; i < state->size / sizeof(uint32_t); i++) {
297 switch (statePtr[i]) {
298 case ZXDG_TOPLEVEL_V6_STATE_MAXIMIZED:
299 states = states | XdgShellSurface::State::Maximized;
300 break;
301 case ZXDG_TOPLEVEL_V6_STATE_FULLSCREEN:
302 states = states | XdgShellSurface::State::Fullscreen;
303 break;
304 case ZXDG_TOPLEVEL_V6_STATE_RESIZING:
305 states = states | XdgShellSurface::State::Resizing;
306 break;
307 case ZXDG_TOPLEVEL_V6_STATE_ACTIVATED:
308 states = states | XdgShellSurface::State::Activated;
309 break;
310 }
311 }
312 s->pendingSize = QSize(width, height);
313 s->pendingState = states;
314}
315
316void XdgTopLevelUnstableV6::Private::closeCallback(void *data, zxdg_toplevel_v6 *xdg_toplevel)
317{
318 auto s = reinterpret_cast<XdgTopLevelUnstableV6::Private *>(data);
319 Q_ASSERT(s->xdgtoplevelv6 == xdg_toplevel);
320 Q_EMIT s->q->closeRequested();
321}
322
323XdgTopLevelUnstableV6::Private::Private(XdgShellSurface *q)
324 : XdgShellSurface::Private(q)
325{
326}
327
328void XdgTopLevelUnstableV6::Private::setupV6(zxdg_surface_v6 *surface, zxdg_toplevel_v6 *topLevel)
329{
330 Q_ASSERT(surface);
331 Q_ASSERT(!xdgtoplevelv6);
332 xdgsurfacev6.setup(pointer: surface);
333 xdgtoplevelv6.setup(pointer: topLevel);
334 zxdg_surface_v6_add_listener(zxdg_surface_v6: xdgsurfacev6, listener: &s_surfaceListener, data: this);
335 zxdg_toplevel_v6_add_listener(zxdg_toplevel_v6: xdgtoplevelv6, listener: &s_toplevelListener, data: this);
336}
337
338void XdgTopLevelUnstableV6::Private::release()
339{
340 xdgtoplevelv6.release();
341 xdgsurfacev6.release();
342}
343
344void XdgTopLevelUnstableV6::Private::destroy()
345{
346 xdgtoplevelv6.destroy();
347 xdgsurfacev6.destroy();
348}
349
350bool XdgTopLevelUnstableV6::Private::isValid() const
351{
352 return xdgtoplevelv6.isValid() && xdgsurfacev6.isValid();
353}
354
355void XdgTopLevelUnstableV6::Private::setTransientFor(XdgShellSurface *parent)
356{
357 zxdg_toplevel_v6 *parentSurface = nullptr;
358 if (parent) {
359 parentSurface = *parent;
360 }
361 zxdg_toplevel_v6_set_parent(zxdg_toplevel_v6: xdgtoplevelv6, parent: parentSurface);
362}
363
364void XdgTopLevelUnstableV6::Private::setTitle(const QString &title)
365{
366 zxdg_toplevel_v6_set_title(zxdg_toplevel_v6: xdgtoplevelv6, title: title.toUtf8().constData());
367}
368
369void XdgTopLevelUnstableV6::Private::setAppId(const QByteArray &appId)
370{
371 zxdg_toplevel_v6_set_app_id(zxdg_toplevel_v6: xdgtoplevelv6, app_id: appId.constData());
372}
373
374void XdgTopLevelUnstableV6::Private::showWindowMenu(Seat *seat, quint32 serial, qint32 x, qint32 y)
375{
376 zxdg_toplevel_v6_show_window_menu(zxdg_toplevel_v6: xdgtoplevelv6, seat: *seat, serial, x, y);
377}
378
379void XdgTopLevelUnstableV6::Private::move(Seat *seat, quint32 serial)
380{
381 zxdg_toplevel_v6_move(zxdg_toplevel_v6: xdgtoplevelv6, seat: *seat, serial);
382}
383
384void XdgTopLevelUnstableV6::Private::resize(Seat *seat, quint32 serial, Qt::Edges edges)
385{
386 uint wlEdge = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_NONE;
387 if (edges.testFlag(flag: Qt::TopEdge)) {
388 if (edges.testFlag(flag: Qt::LeftEdge) && ((edges & ~Qt::LeftEdge) == Qt::TopEdge)) {
389 wlEdge = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_TOP_LEFT;
390 } else if (edges.testFlag(flag: Qt::RightEdge) && ((edges & ~Qt::RightEdge) == Qt::TopEdge)) {
391 wlEdge = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_TOP_RIGHT;
392 } else if ((edges & ~Qt::TopEdge) == Qt::Edges()) {
393 wlEdge = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_TOP;
394 }
395 } else if (edges.testFlag(flag: Qt::BottomEdge)) {
396 if (edges.testFlag(flag: Qt::LeftEdge) && ((edges & ~Qt::LeftEdge) == Qt::BottomEdge)) {
397 wlEdge = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_BOTTOM_LEFT;
398 } else if (edges.testFlag(flag: Qt::RightEdge) && ((edges & ~Qt::RightEdge) == Qt::BottomEdge)) {
399 wlEdge = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_BOTTOM_RIGHT;
400 } else if ((edges & ~Qt::BottomEdge) == Qt::Edges()) {
401 wlEdge = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_BOTTOM;
402 }
403 } else if (edges.testFlag(flag: Qt::RightEdge) && ((edges & ~Qt::RightEdge) == Qt::Edges())) {
404 wlEdge = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_RIGHT;
405 } else if (edges.testFlag(flag: Qt::LeftEdge) && ((edges & ~Qt::LeftEdge) == Qt::Edges())) {
406 wlEdge = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_LEFT;
407 }
408 zxdg_toplevel_v6_resize(zxdg_toplevel_v6: xdgtoplevelv6, seat: *seat, serial, edges: wlEdge);
409}
410
411void XdgTopLevelUnstableV6::Private::ackConfigure(quint32 serial)
412{
413 zxdg_surface_v6_ack_configure(zxdg_surface_v6: xdgsurfacev6, serial);
414}
415
416void XdgTopLevelUnstableV6::Private::setMaximized()
417{
418 zxdg_toplevel_v6_set_maximized(zxdg_toplevel_v6: xdgtoplevelv6);
419}
420
421void XdgTopLevelUnstableV6::Private::unsetMaximized()
422{
423 zxdg_toplevel_v6_unset_maximized(zxdg_toplevel_v6: xdgtoplevelv6);
424}
425
426void XdgTopLevelUnstableV6::Private::setFullscreen(Output *output)
427{
428 wl_output *o = nullptr;
429 if (output) {
430 o = *output;
431 }
432 zxdg_toplevel_v6_set_fullscreen(zxdg_toplevel_v6: xdgtoplevelv6, output: o);
433}
434
435void XdgTopLevelUnstableV6::Private::unsetFullscreen()
436{
437 zxdg_toplevel_v6_unset_fullscreen(zxdg_toplevel_v6: xdgtoplevelv6);
438}
439
440void XdgTopLevelUnstableV6::Private::setMinimized()
441{
442 zxdg_toplevel_v6_set_minimized(zxdg_toplevel_v6: xdgtoplevelv6);
443}
444
445void XdgTopLevelUnstableV6::Private::setMaxSize(const QSize &size)
446{
447 zxdg_toplevel_v6_set_max_size(zxdg_toplevel_v6: xdgtoplevelv6, width: size.width(), height: size.height());
448}
449
450void XdgTopLevelUnstableV6::Private::setMinSize(const QSize &size)
451{
452 zxdg_toplevel_v6_set_min_size(zxdg_toplevel_v6: xdgtoplevelv6, width: size.width(), height: size.height());
453}
454
455XdgTopLevelUnstableV6::XdgTopLevelUnstableV6(QObject *parent)
456 : XdgShellSurface(new Private(this), parent)
457{
458}
459
460XdgTopLevelUnstableV6::~XdgTopLevelUnstableV6() = default;
461
462class XdgShellPopupUnstableV6::Private : public XdgShellPopup::Private
463{
464public:
465 Private(XdgShellPopup *q);
466
467 void setupV6(zxdg_surface_v6 *s, zxdg_popup_v6 *p) override;
468 void release() override;
469 void destroy() override;
470 bool isValid() const override;
471 void requestGrab(Seat *seat, quint32 serial) override;
472 void ackConfigure(quint32 serial) override;
473
474 using XdgShellPopup::Private::operator xdg_popup *;
475 using XdgShellPopup::Private::operator xdg_surface *;
476 operator zxdg_surface_v6 *() override
477 {
478 return xdgsurfacev6;
479 }
480 operator zxdg_surface_v6 *() const override
481 {
482 return xdgsurfacev6;
483 }
484 operator zxdg_popup_v6 *() override
485 {
486 return xdgpopupv6;
487 }
488 operator zxdg_popup_v6 *() const override
489 {
490 return xdgpopupv6;
491 }
492 WaylandPointer<zxdg_surface_v6, zxdg_surface_v6_destroy> xdgsurfacev6;
493 WaylandPointer<zxdg_popup_v6, zxdg_popup_v6_destroy> xdgpopupv6;
494
495 QRect pendingRect;
496
497private:
498 static void configureCallback(void *data, zxdg_popup_v6 *xdg_popup, int32_t x, int32_t y, int32_t width, int32_t height);
499 static void popupDoneCallback(void *data, zxdg_popup_v6 *xdg_popup);
500 static void surfaceConfigureCallback(void *data, zxdg_surface_v6 *xdg_surface, uint32_t serial);
501
502 static const struct zxdg_popup_v6_listener s_popupListener;
503 static const struct zxdg_surface_v6_listener s_surfaceListener;
504};
505
506const struct zxdg_popup_v6_listener XdgShellPopupUnstableV6::Private::s_popupListener = {.configure: configureCallback, .popup_done: popupDoneCallback};
507
508const struct zxdg_surface_v6_listener XdgShellPopupUnstableV6::Private::s_surfaceListener = {
509 .configure: surfaceConfigureCallback,
510};
511
512void XdgShellPopupUnstableV6::Private::configureCallback(void *data, zxdg_popup_v6 *xdg_popup, int32_t x, int32_t y, int32_t width, int32_t height)
513{
514 Q_UNUSED(xdg_popup);
515 auto s = reinterpret_cast<Private *>(data);
516 s->pendingRect = QRect(x, y, width, height);
517}
518
519void XdgShellPopupUnstableV6::Private::surfaceConfigureCallback(void *data, struct zxdg_surface_v6 *surface, uint32_t serial)
520{
521 Q_UNUSED(surface);
522 auto s = reinterpret_cast<Private *>(data);
523 s->q->configureRequested(relativePosition: s->pendingRect, serial);
524 s->pendingRect = QRect();
525}
526
527void XdgShellPopupUnstableV6::Private::popupDoneCallback(void *data, zxdg_popup_v6 *xdg_popup)
528{
529 auto s = reinterpret_cast<XdgShellPopupUnstableV6::Private *>(data);
530 Q_ASSERT(s->xdgpopupv6 == xdg_popup);
531 Q_EMIT s->q->popupDone();
532}
533
534XdgShellPopupUnstableV6::Private::Private(XdgShellPopup *q)
535 : XdgShellPopup::Private(q)
536{
537}
538
539void XdgShellPopupUnstableV6::Private::setupV6(zxdg_surface_v6 *s, zxdg_popup_v6 *p)
540{
541 Q_ASSERT(p);
542 Q_ASSERT(!xdgsurfacev6);
543 Q_ASSERT(!xdgpopupv6);
544
545 xdgsurfacev6.setup(pointer: s);
546 xdgpopupv6.setup(pointer: p);
547 zxdg_surface_v6_add_listener(zxdg_surface_v6: xdgsurfacev6, listener: &s_surfaceListener, data: this);
548 zxdg_popup_v6_add_listener(zxdg_popup_v6: xdgpopupv6, listener: &s_popupListener, data: this);
549}
550
551void XdgShellPopupUnstableV6::Private::release()
552{
553 xdgpopupv6.release();
554}
555
556void XdgShellPopupUnstableV6::Private::destroy()
557{
558 xdgpopupv6.destroy();
559}
560
561bool XdgShellPopupUnstableV6::Private::isValid() const
562{
563 return xdgpopupv6.isValid();
564}
565
566void XdgShellPopupUnstableV6::Private::requestGrab(Seat *seat, quint32 serial)
567{
568 zxdg_popup_v6_grab(zxdg_popup_v6: xdgpopupv6, seat: *seat, serial);
569}
570
571void XdgShellPopupUnstableV6::Private::ackConfigure(quint32 serial)
572{
573 zxdg_surface_v6_ack_configure(zxdg_surface_v6: xdgsurfacev6, serial);
574}
575
576XdgShellPopupUnstableV6::XdgShellPopupUnstableV6(QObject *parent)
577 : XdgShellPopup(new Private(this), parent)
578{
579}
580
581XdgShellPopupUnstableV6::~XdgShellPopupUnstableV6() = default;
582
583}
584}
585

source code of kwayland/src/client/xdgshell_v6.cpp