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 | |
16 | namespace KWayland |
17 | { |
18 | namespace Client |
19 | { |
20 | class XdgShellUnstableV6::Private : public XdgShell::Private |
21 | { |
22 | public: |
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 | |
43 | private: |
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 | |
51 | const struct zxdg_shell_v6_listener XdgShellUnstableV6::Private::s_shellListener = { |
52 | .ping: pingCallback, |
53 | }; |
54 | |
55 | void 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 | |
61 | void 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 | |
69 | void XdgShellUnstableV6::Private::release() |
70 | { |
71 | xdgshellv6.release(); |
72 | } |
73 | |
74 | void XdgShellUnstableV6::Private::destroy() |
75 | { |
76 | xdgshellv6.destroy(); |
77 | } |
78 | |
79 | bool XdgShellUnstableV6::Private::isValid() const |
80 | { |
81 | return xdgshellv6.isValid(); |
82 | } |
83 | |
84 | XdgShellSurface *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 | |
103 | XdgShellPopup *XdgShellUnstableV6::Private::getXdgPopup(Surface *surface, XdgShellSurface *parentSurface, const XdgPositioner &positioner, QObject *parent) |
104 | { |
105 | return internalGetXdgPopup(surface, parentSurface: *parentSurface, positioner, parent); |
106 | } |
107 | |
108 | XdgShellPopup *XdgShellUnstableV6::Private::getXdgPopup(Surface *surface, XdgShellPopup *parentSurface, const XdgPositioner &positioner, QObject *parent) |
109 | { |
110 | return internalGetXdgPopup(surface, parentSurface: *parentSurface, positioner, parent); |
111 | } |
112 | |
113 | XdgShellPopup * |
114 | XdgShellUnstableV6::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 = 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 | |
207 | XdgShellUnstableV6::XdgShellUnstableV6(QObject *parent) |
208 | : XdgShell(new Private, parent) |
209 | { |
210 | } |
211 | |
212 | XdgShellUnstableV6::~XdgShellUnstableV6() = default; |
213 | |
214 | // A top level wraps both xdg_surface_v6 and xdg_top_level into the public API XdgShelllSurface |
215 | class XdgTopLevelUnstableV6::Private : public XdgShellSurface::Private |
216 | { |
217 | public: |
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 | |
261 | private: |
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 | |
273 | const struct zxdg_toplevel_v6_listener XdgTopLevelUnstableV6::Private::s_toplevelListener = {.configure: configureCallback, .close: closeCallback}; |
274 | |
275 | const struct zxdg_surface_v6_listener XdgTopLevelUnstableV6::Private::s_surfaceListener = {.configure: surfaceConfigureCallback}; |
276 | |
277 | void 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 | |
289 | void 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 | |
316 | void 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 | |
323 | XdgTopLevelUnstableV6::Private::Private(XdgShellSurface *q) |
324 | : XdgShellSurface::Private(q) |
325 | { |
326 | } |
327 | |
328 | void 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 | |
338 | void XdgTopLevelUnstableV6::Private::release() |
339 | { |
340 | xdgtoplevelv6.release(); |
341 | xdgsurfacev6.release(); |
342 | } |
343 | |
344 | void XdgTopLevelUnstableV6::Private::destroy() |
345 | { |
346 | xdgtoplevelv6.destroy(); |
347 | xdgsurfacev6.destroy(); |
348 | } |
349 | |
350 | bool XdgTopLevelUnstableV6::Private::isValid() const |
351 | { |
352 | return xdgtoplevelv6.isValid() && xdgsurfacev6.isValid(); |
353 | } |
354 | |
355 | void 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 | |
364 | void XdgTopLevelUnstableV6::Private::setTitle(const QString &title) |
365 | { |
366 | zxdg_toplevel_v6_set_title(zxdg_toplevel_v6: xdgtoplevelv6, title: title.toUtf8().constData()); |
367 | } |
368 | |
369 | void XdgTopLevelUnstableV6::Private::setAppId(const QByteArray &appId) |
370 | { |
371 | zxdg_toplevel_v6_set_app_id(zxdg_toplevel_v6: xdgtoplevelv6, app_id: appId.constData()); |
372 | } |
373 | |
374 | void 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 | |
379 | void XdgTopLevelUnstableV6::Private::move(Seat *seat, quint32 serial) |
380 | { |
381 | zxdg_toplevel_v6_move(zxdg_toplevel_v6: xdgtoplevelv6, seat: *seat, serial); |
382 | } |
383 | |
384 | void 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 | |
411 | void XdgTopLevelUnstableV6::Private::ackConfigure(quint32 serial) |
412 | { |
413 | zxdg_surface_v6_ack_configure(zxdg_surface_v6: xdgsurfacev6, serial); |
414 | } |
415 | |
416 | void XdgTopLevelUnstableV6::Private::setMaximized() |
417 | { |
418 | zxdg_toplevel_v6_set_maximized(zxdg_toplevel_v6: xdgtoplevelv6); |
419 | } |
420 | |
421 | void XdgTopLevelUnstableV6::Private::unsetMaximized() |
422 | { |
423 | zxdg_toplevel_v6_unset_maximized(zxdg_toplevel_v6: xdgtoplevelv6); |
424 | } |
425 | |
426 | void 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 | |
435 | void XdgTopLevelUnstableV6::Private::unsetFullscreen() |
436 | { |
437 | zxdg_toplevel_v6_unset_fullscreen(zxdg_toplevel_v6: xdgtoplevelv6); |
438 | } |
439 | |
440 | void XdgTopLevelUnstableV6::Private::setMinimized() |
441 | { |
442 | zxdg_toplevel_v6_set_minimized(zxdg_toplevel_v6: xdgtoplevelv6); |
443 | } |
444 | |
445 | void 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 | |
450 | void 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 | |
455 | XdgTopLevelUnstableV6::XdgTopLevelUnstableV6(QObject *parent) |
456 | : XdgShellSurface(new Private(this), parent) |
457 | { |
458 | } |
459 | |
460 | XdgTopLevelUnstableV6::~XdgTopLevelUnstableV6() = default; |
461 | |
462 | class XdgShellPopupUnstableV6::Private : public XdgShellPopup::Private |
463 | { |
464 | public: |
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 | |
497 | private: |
498 | static void configureCallback(void *data, zxdg_popup_v6 *, int32_t x, int32_t y, int32_t width, int32_t height); |
499 | static void popupDoneCallback(void *data, zxdg_popup_v6 *); |
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 | |
506 | const struct zxdg_popup_v6_listener XdgShellPopupUnstableV6::Private::s_popupListener = {.configure: configureCallback, .popup_done: popupDoneCallback}; |
507 | |
508 | const struct zxdg_surface_v6_listener XdgShellPopupUnstableV6::Private::s_surfaceListener = { |
509 | .configure: surfaceConfigureCallback, |
510 | }; |
511 | |
512 | void XdgShellPopupUnstableV6::Private::configureCallback(void *data, zxdg_popup_v6 *, 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 | |
519 | void 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 | |
527 | void XdgShellPopupUnstableV6::Private::popupDoneCallback(void *data, zxdg_popup_v6 *) |
528 | { |
529 | auto s = reinterpret_cast<XdgShellPopupUnstableV6::Private *>(data); |
530 | Q_ASSERT(s->xdgpopupv6 == xdg_popup); |
531 | Q_EMIT s->q->popupDone(); |
532 | } |
533 | |
534 | XdgShellPopupUnstableV6::Private::Private(XdgShellPopup *q) |
535 | : XdgShellPopup::Private(q) |
536 | { |
537 | } |
538 | |
539 | void 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 | |
551 | void XdgShellPopupUnstableV6::Private::release() |
552 | { |
553 | xdgpopupv6.release(); |
554 | } |
555 | |
556 | void XdgShellPopupUnstableV6::Private::destroy() |
557 | { |
558 | xdgpopupv6.destroy(); |
559 | } |
560 | |
561 | bool XdgShellPopupUnstableV6::Private::isValid() const |
562 | { |
563 | return xdgpopupv6.isValid(); |
564 | } |
565 | |
566 | void XdgShellPopupUnstableV6::Private::requestGrab(Seat *seat, quint32 serial) |
567 | { |
568 | zxdg_popup_v6_grab(zxdg_popup_v6: xdgpopupv6, seat: *seat, serial); |
569 | } |
570 | |
571 | void XdgShellPopupUnstableV6::Private::ackConfigure(quint32 serial) |
572 | { |
573 | zxdg_surface_v6_ack_configure(zxdg_surface_v6: xdgsurfacev6, serial); |
574 | } |
575 | |
576 | XdgShellPopupUnstableV6::XdgShellPopupUnstableV6(QObject *parent) |
577 | : XdgShellPopup(new Private(this), parent) |
578 | { |
579 | } |
580 | |
581 | XdgShellPopupUnstableV6::~XdgShellPopupUnstableV6() = default; |
582 | |
583 | } |
584 | } |
585 | |