Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qwaylandqtshell.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3// Qt-Security score:critical reason:network-protocol
4
8
9#include <QtWaylandCompositor/QWaylandCompositor>
10#include <QtWaylandCompositor/QWaylandSurface>
12#include <QtWaylandCompositor/QWaylandResource>
13
14#if QT_CONFIG(wayland_compositor_quick)
15# include "qwaylandqtshellintegration_p.h"
16#endif
17
18#include <QtWaylandCompositor/QWaylandResource>
19#include <QDebug>
20#include "compositor_api/qwaylandseat.h"
21
22#include <QtWaylandCompositor/private/qwaylandutils_p.h>
23
24QT_BEGIN_NAMESPACE
25
26/*!
27 * \qmltype QtShell
28 * \nativetype QWaylandQtShell
29 * \inqmlmodule QtWayland.Compositor.QtShell
30 * \since 6.3
31 * \brief Provides a shell extension for Qt applications running on a Qt Wayland Compositor.
32 *
33 * The QtShell extension provides a way to associate an QtShellSurface with a regular Wayland
34 * surface. The QtShell extension is written to support the window management features which are
35 * supported by Qt. It may be suitable on a platform where both the compositor and client
36 * applications are written with Qt, and where applications are trusted not to abuse features such
37 * as manual window positioning and "bring-to-front".
38 *
39 * For other use cases, consider using IviApplication or XdgShell instead.
40 *
41 * \code
42 * import QtWayland.Compositor.QtShell
43 *
44 * WaylandCompositor {
45 * property ListModel shellSurfaces: ListModel {}
46 * QtShell {
47 * onQtShellSurfaceCreated: {
48 * shellSurfaces.append({shellSurface: qtShellSurface})
49 * }
50 * }
51 * }
52 * \endcode
53 */
54QWaylandQtShell::QWaylandQtShell()
55 : QWaylandCompositorExtensionTemplate<QWaylandQtShell>(*new QWaylandQtShellPrivate())
56{
57}
58
59QWaylandQtShell::QWaylandQtShell(QWaylandCompositor *compositor)
60 : QWaylandCompositorExtensionTemplate<QWaylandQtShell>(compositor, *new QWaylandQtShellPrivate())
61{
62}
63
64bool QWaylandQtShell::moveChromeToFront(QWaylandQtShellChrome *chrome)
65{
66 Q_D(QWaylandQtShell);
67 for (int i = 0; i < d->m_chromes.size(); ++i) {
68 if (d->m_chromes.at(i) == chrome) {
69 if (i > 0) {
70 QWaylandQtShellChrome *currentActive = d->m_chromes.first();
71 d->m_chromes.move(i, 0);
72 chrome->activate();
73 currentActive->deactivate();
74 }
75 return true;
76 }
77 }
78
79 return false;
80}
81
82void QWaylandQtShell::registerChrome(QWaylandQtShellChrome *chrome)
83{
84 Q_D(QWaylandQtShell);
85 if (moveChromeToFront(chrome))
86 return;
87
88 QWaylandQtShellChrome *currentActive = d->m_chromes.isEmpty() ? nullptr : d->m_chromes.first();
89
90 d->m_chromes.prepend(chrome);
91 chrome->activate();
92
93 if (currentActive != nullptr)
94 currentActive->deactivate();
95
96 connect(chrome, &QWaylandQtShellChrome::activated, this, &QWaylandQtShell::chromeActivated);
97 connect(chrome, &QWaylandQtShellChrome::deactivated, this, &QWaylandQtShell::chromeDeactivated);
98}
99
100void QWaylandQtShell::unregisterChrome(QWaylandQtShellChrome *chrome)
101{
102 Q_D(QWaylandQtShell);
103
104 chrome->disconnect(this);
105 int index = d->m_chromes.indexOf(chrome);
106 if (index >= 0) {
107 d->m_chromes.removeAt(index);
108 if (index == 0 && d->m_chromes.size() > 0)
109 d->m_chromes.at(0)->activate();
110 }
111}
112
113void QWaylandQtShell::chromeActivated()
114{
115 QWaylandQtShellChrome *c = qobject_cast<QWaylandQtShellChrome *>(sender());
116 if (c != nullptr) {
117 moveChromeToFront(c);
118 }
119}
120
121void QWaylandQtShell::chromeDeactivated()
122{
123 Q_D(QWaylandQtShell);
124 QWaylandQtShellChrome *c = qobject_cast<QWaylandQtShellChrome *>(sender());
125 if (d->m_chromes.size() > 1 && d->m_chromes.at(0) == c) {
126 d->m_chromes.move(0, 1);
127 d->m_chromes.at(0)->activate();
128 } else if (d->m_chromes.size() == 1) { // One window must be active
129 d->m_chromes.at(0)->activate();
130 }
131}
132
133void QWaylandQtShell::initialize()
134{
135 Q_D(QWaylandQtShell);
136 QWaylandCompositorExtensionTemplate::initialize();
137
138 QWaylandCompositor *compositor = static_cast<QWaylandCompositor *>(extensionContainer());
139 if (!compositor) {
140 qWarning() << "Failed to find QWaylandCompositor when initializing QWaylandQtShell";
141 return;
142 }
143
144 d->init(compositor->display(), 1);
145}
146
147const struct wl_interface *QWaylandQtShell::interface()
148{
149 return QWaylandQtShellPrivate::interface();
150}
151
152/*!
153 * \internal
154 */
155QByteArray QWaylandQtShell::interfaceName()
156{
157 return QWaylandQtShellPrivate::interfaceName();
158}
159
160/*!
161 * \qmlsignal void QtShell::qtShellSurfaceRequested(WaylandSurface surface, WaylandResource resource)
162 *
163 * This signal is emitted when the client has requested a QtShellSurface to be associated
164 * with \a surface. The handler for this signal is expected to create the QtShellSurface for
165 * \a resource and initialize it within the scope of the signal emission. If no QtShellSurface is
166 * created, a default one will be created instead.
167 */
168
169/*!
170 * \qmlsignal void QtShell::qtShellSurfaceCreated(QtShellSurface *qtShellSurface)
171 *
172 * This signal is emitted when an QtShellSurface has been created. The supplied \a qtShellSurface is
173 * most commonly used to instantiate a ShellSurfaceItem.
174 */
175
176QWaylandQtShellPrivate::QWaylandQtShellPrivate()
177{
178}
179
180void QWaylandQtShellPrivate::unregisterQtShellSurface(QWaylandQtShellSurface *qtShellSurface)
181{
182 Q_UNUSED(qtShellSurface)
183}
184
185void QWaylandQtShellPrivate::zqt_shell_v1_surface_create(QtWaylandServer::zqt_shell_v1::Resource *resource, wl_resource *surfaceResource, uint32_t id)
186{
187 Q_Q(QWaylandQtShell);
188 QWaylandSurface *surface = QWaylandSurface::fromResource(surfaceResource);
189
190 if (!surface->setRole(QWaylandQtShellSurface::role(), resource->handle, ZQT_SHELL_V1_ERROR_ROLE))
191 return;
192
193 QWaylandResource qtShellSurfaceResource(wl_resource_create(resource->client(), &zqt_shell_surface_v1_interface,
194 wl_resource_get_version(resource->handle), id));
195
196 emit q->qtShellSurfaceRequested(surface, qtShellSurfaceResource);
197
198 QWaylandQtShellSurface *qtShellSurface = QWaylandQtShellSurface::fromResource(qtShellSurfaceResource.resource());
199
200 if (!qtShellSurface)
201 qtShellSurface = new QWaylandQtShellSurface(q, surface, qtShellSurfaceResource);
202
203 emit q->qtShellSurfaceCreated(qtShellSurface);
204}
205
206QWaylandSurfaceRole QWaylandQtShellSurfacePrivate::s_role("qt_shell_surface");
207
208/*!
209 * \qmltype QtShellSurface
210 * \nativetype QWaylandQtShellSurface
211 * \inqmlmodule QtWayland.Compositor.QtShell
212 * \since 6.3
213 * \brief Provides a simple way to identify and resize a surface.
214 *
215 * This type is part of the \l{QtShell} extension and provides a way to extend
216 * the functionality of an existing WaylandSurface with window management functionality.
217 *
218 * The QtShellSurface type holds the core functionality needed to create a compositor that supports
219 * the QtShell extension. It can be used directly, or via the QtShellChrome type, depending on what
220 * the needs of the compositor are. The QtShellChrome type has default behaviors and convenience
221 * APIs for working with QtShellSurface objects.
222 */
223
224/*!
225 \qmlsignal void QtShellSurface::startMove()
226
227 The client has requested an interactive move operation in the compositor by calling
228 \l{QWindow::startSystemMove()}.
229
230 \sa capabilities
231*/
232
233/*!
234 \qmlsignal void QtShellSurface::startResize(enum edges)
235
236 The client has requested an interactive resize operation in the compositor by calling
237 \l{QWindow::startSystemResize()}.
238
239 The \a edges provides information about which edge of the window should be moved during the
240 resize. It is a mask of the following values:
241 \list
242 \li Qt.TopEdge
243 \li Qt.LeftEdge
244 \li Qt.RightEdge
245 \li Qt.BottomEdge
246 \endlist
247
248 \sa capabilities
249*/
250
251QWaylandQtShellSurface::QWaylandQtShellSurface()
252 : QWaylandShellSurfaceTemplate<QWaylandQtShellSurface>(*new QWaylandQtShellSurfacePrivate())
253{
254}
255
256QWaylandQtShellSurface::QWaylandQtShellSurface(QWaylandQtShell *application, QWaylandSurface *surface, const QWaylandResource &resource)
257 : QWaylandShellSurfaceTemplate<QWaylandQtShellSurface>(*new QWaylandQtShellSurfacePrivate())
258{
259 initialize(application, surface, resource);
260}
261
262/*!
263 * \qmlmethod void QtShellSurface::initialize(QtShell qtShell, WaylandSurface surface, WaylandResource resource)
264 *
265 * Initializes the QtShellSurface, associating it with the given \a qtShell, \a surface, and
266 * \a resource.
267 */
268void QWaylandQtShellSurface::initialize(QWaylandQtShell *qtShell, QWaylandSurface *surface, const QWaylandResource &resource)
269{
270 Q_D(QWaylandQtShellSurface);
271
272 d->m_qtShell = qtShell;
273 d->m_surface = surface;
274
275 connect(d->m_surface, &QWaylandSurface::damaged, this, &QWaylandQtShellSurface::surfaceCommitted);
276
277 d->init(resource.resource());
278 setExtensionContainer(surface);
279
280 emit surfaceChanged();
281
282 QWaylandCompositorExtension::initialize();
283}
284
285/*!
286 * \qmlproperty WaylandSurface QtShellSurface::surface
287 *
288 * This property holds the surface associated with this QtShellSurface.
289 */
290
291/*!
292 * \property QWaylandQtShellSurface::surface
293 *
294 * This property holds the surface associated with this QWaylandQtShellSurface.
295 */
296QWaylandSurface *QWaylandQtShellSurface::surface() const
297{
298 Q_D(const QWaylandQtShellSurface);
299 return d->m_surface;
300}
301
302QWaylandQtShell *QWaylandQtShellSurface::shell() const
303{
304 Q_D(const QWaylandQtShellSurface);
305 return d->m_qtShell;
306}
307
308/*!
309 * \qmlproperty point QtShellSurface::windowPosition
310 *
311 * This property holds the position of the shell surface relative to its output.
312 */
313
314/*!
315 * \property QWaylandQtShellSurface::windowPosition
316 *
317 * This property holds the position of the shell surface relative to its output.
318 */
319QPoint QWaylandQtShellSurface::windowPosition() const
320{
321 Q_D(const QWaylandQtShellSurface);
322 return d->m_windowGeometry.topLeft();
323}
324
325void QWaylandQtShellSurface::setWindowPosition(const QPoint &position)
326{
327 Q_D(QWaylandQtShellSurface);
328
329 // We don't care about the ack in this case, so use UINT_MAX as serial
330 d->send_set_position(UINT32_MAX, position.x(), position.y());
331 d->send_configure(UINT32_MAX);
332
333 d->m_windowGeometry.moveTopLeft(position);
334 d->m_positionSet = true;
335 emit positionAutomaticChanged();
336 emit windowGeometryChanged();
337}
338
339/*!
340 * \qmlproperty rect QtShellSurface::windowGeometry
341 *
342 * This property holds the window geometry of the shell surface.
343 */
344
345/*!
346 * \property QWaylandQtShellSurface::windowGeometry
347 *
348 * This property holds the window geometry of the shell surface.
349 */
350QRect QWaylandQtShellSurface::windowGeometry() const
351{
352 Q_D(const QWaylandQtShellSurface);
353 return d->m_windowGeometry;
354}
355
356/*!
357 * \qmlproperty size QtShellSurface::minimumSize
358 *
359 * The minimum size of the window if the client has specified one. Otherwise an invalid size.
360 */
361
362/*!
363 * \property QWaylandQtShellSurface::minimumSize
364 *
365 * The minimum size of the window if the client has specified one. Otherwise an
366 * invalid size.
367 */
368QSize QWaylandQtShellSurface::minimumSize() const
369{
370 Q_D(const QWaylandQtShellSurface);
371 return d->m_minimumSize;
372}
373
374/*!
375 * \qmlproperty size QtShellSurface::maximumSize
376 *
377 * The maximum size of the window if the client has specified one. Otherwise an invalid size.
378 */
379
380/*!
381 * \property QWaylandQtShellSurface::maximumSize
382 *
383 * The maximum size of the window if the client has specified one. Otherwise an
384 * invalid size.
385 */
386QSize QWaylandQtShellSurface::maximumSize() const
387{
388 Q_D(const QWaylandQtShellSurface);
389 return d->m_maximumSize;
390}
391
392/*!
393 * \qmlmethod void QtShellSurface::requestWindowGeometry(int windowState, rect windowGeometry)
394 *
395 * Requests a new \a windowState and \a windowGeometry for the QtShellSurface. The state and
396 * geometry is updated when the client has acknowledged the request (at which point it is safe to
397 * assume that the surface's buffer has been resized if necessary).
398 */
399void QWaylandQtShellSurface::requestWindowGeometry(uint windowState, const QRect &windowGeometry)
400{
401 Q_D(QWaylandQtShellSurface);
402 if (!windowGeometry.isValid())
403 return;
404
405 d->configure(windowState, windowGeometry);
406}
407
408void QWaylandQtShellSurfacePrivate::configure(uint windowState, const QRect &newGeometry)
409{
410 QWaylandCompositor *compositor = m_surface != nullptr ? m_surface->compositor() : nullptr;
411 if (!compositor) {
412 qWarning() << "Failed to find QWaylandCompositor when configuring QWaylandQtShell";
413 return;
414 }
415
416 uint32_t serial = compositor->nextSerial();
417 m_pendingConfigures[serial] = {windowState, newGeometry};
418
419 send_set_position(serial, newGeometry.x(), newGeometry.y());
420 send_resize(serial, newGeometry.width(), newGeometry.height());
421 send_set_window_state(serial, windowState & ~Qt::WindowActive);
422 send_configure(serial);
423}
424
425void QWaylandQtShellSurface::setFrameMargins(const QMargins &margins)
426{
427 Q_D(QWaylandQtShellSurface);
428 if (d->m_frameMargins == margins)
429 return;
430
431 d->m_frameMargins = margins;
432 d->updateFrameMargins();
433
434 emit frameMarginChanged();
435}
436
437/*!
438 * \qmlproperty int QtShellSurface::frameMarginLeft
439 *
440 * This holds the window frame margin to the left of the surface.
441 */
442
443/*!
444 * \property QWaylandQtShellSurface::frameMarginLeft
445 *
446 * This property holds the window frame margin to the left of the surface.
447 */
448void QWaylandQtShellSurface::setFrameMarginLeft(int left)
449{
450 Q_D(QWaylandQtShellSurface);
451 if (d->m_frameMargins.left() == left)
452 return;
453
454 d->m_frameMargins.setLeft(left);
455 d->updateFrameMargins();
456
457 emit frameMarginChanged();
458}
459
460int QWaylandQtShellSurface::frameMarginLeft() const
461{
462 Q_D(const QWaylandQtShellSurface);
463 return d->m_frameMargins.left();
464}
465
466/*!
467 * \qmlproperty int QtShellSurface::frameMarginRight
468 *
469 * This holds the window frame margin to the right of the surface.
470 */
471
472/*!
473 * \property QWaylandQtShellSurface::frameMarginRight
474 *
475 * This property holds the window frame margin to the right of the surface.
476 */
477void QWaylandQtShellSurface::setFrameMarginRight(int right)
478{
479 Q_D(QWaylandQtShellSurface);
480 if (d->m_frameMargins.right() == right)
481 return;
482
483 d->m_frameMargins.setRight(right);
484 d->updateFrameMargins();
485
486 emit frameMarginChanged();
487}
488
489int QWaylandQtShellSurface::frameMarginRight() const
490{
491 Q_D(const QWaylandQtShellSurface);
492 return d->m_frameMargins.right();
493}
494
495/*!
496 * \qmlproperty int QtShellSurface::frameMarginTop
497 *
498 * This holds the window frame margin above the surface.
499 */
500
501/*!
502 * \property QWaylandQtShellSurface::frameMarginTop
503 *
504 * This property holds the window frame margin above the surface.
505 */
506void QWaylandQtShellSurface::setFrameMarginTop(int top)
507{
508 Q_D(QWaylandQtShellSurface);
509 if (d->m_frameMargins.top() == top)
510 return;
511 d->m_frameMargins.setTop(top);
512 d->updateFrameMargins();
513
514 emit frameMarginChanged();
515}
516
517int QWaylandQtShellSurface::frameMarginTop() const
518{
519 Q_D(const QWaylandQtShellSurface);
520 return d->m_frameMargins.top();
521}
522
523/*!
524 * \qmlproperty int QtShellSurface::frameMarginBottom
525 *
526 * This holds the window frame margin below the surface.
527 */
528
529/*!
530 * \property QWaylandQtShellSurface::frameMarginBottom
531 *
532 * This property holds the window frame margin below the surface.
533 */
534void QWaylandQtShellSurface::setFrameMarginBottom(int bottom)
535{
536 Q_D(QWaylandQtShellSurface);
537 if (d->m_frameMargins.bottom() == bottom)
538 return;
539 d->m_frameMargins.setBottom(bottom);
540 d->updateFrameMargins();
541
542 emit frameMarginChanged();
543}
544
545/*!
546 * \property QWaylandQtShellSurface::positionAutomatic
547 *
548 * This property holds whether the window position is automatically determined
549 * by the compositor.
550 *
551 * The value is \c true if the position has not been explicitly set; otherwise
552 * \c false.
553 */
554bool QWaylandQtShellSurface::positionAutomatic() const
555{
556 Q_D(const QWaylandQtShellSurface);
557 return !d->m_positionSet;
558}
559
560int QWaylandQtShellSurface::frameMarginBottom() const
561{
562 Q_D(const QWaylandQtShellSurface);
563 return d->m_frameMargins.bottom();
564}
565
566/*!
567 * \qmlproperty int QtShellSurface::windowFlags
568 *
569 * This property holds the window flags of the QtShellSurface.
570 */
571
572/*!
573 * \property QWaylandQtShellSurface::windowFlags
574 *
575 * This property holds the window flags of the QWaylandQtShellSurface.
576 */
577uint QWaylandQtShellSurface::windowFlags() const
578{
579 Q_D(const QWaylandQtShellSurface);
580 return d->m_windowFlags;
581}
582
583/*!
584 * \qmlmethod void QtShellSurface::sendClose()
585 *
586 * Requests that the client application closes itself.
587 */
588void QWaylandQtShellSurface::sendClose()
589{
590 Q_D(QWaylandQtShellSurface);
591 d->send_close();
592}
593
594/*!
595 * \qmlproperty string QtShellSurface::windowTitle
596 *
597 * This property holds the window title of the QtShellSurface.
598 */
599
600/*!
601 * \property QWaylandQtShellSurface::windowTitle
602 *
603 * This property holds the window title of the QWaylandQtShellSurface.
604 */
605QString QWaylandQtShellSurface::windowTitle() const
606{
607 Q_D(const QWaylandQtShellSurface);
608 return d->m_windowTitle;
609}
610
611/*!
612 * \qmlproperty bool QtShellSurface::active
613 *
614 * This property holds whether the surface is currently considered active.
615 *
616 * \note There are no restrictions in QtShellSurface that prevents multiple surfaces from being
617 * active simultaneously. Such logic must either be implemented by the compositor itself, or by
618 * using the QtShellChrome type, which will automatically manage the activation state of surfaces.
619 */
620
621/*!
622 * \property QWaylandQtShellSurface::active
623 *
624 * This property holds whether the surface is currently considered active.
625 *
626 * \note There are no restrictions in QWaylandQtShellSurface that prevent
627 * multiple surfaces from being active simultaneously. Such logic must
628 * either be implemented by the compositor itself, or by using the
629 * QWaylandQtShellChrome type, which will automatically manage the
630 * activation state of surfaces.
631 */
632void QWaylandQtShellSurface::setActive(bool active)
633{
634 Q_D(QWaylandQtShellSurface);
635 if (d->m_active == active)
636 return;
637
638 d->m_active = active;
639 QWaylandCompositor *compositor = d->m_surface ? d->m_surface->compositor() : nullptr;
640 QWaylandSeat *seat = compositor ? compositor->defaultSeat() : nullptr;
641 if (seat && active)
642 seat->setKeyboardFocus(surface());
643 emit activeChanged();
644}
645
646bool QWaylandQtShellSurface::active() const
647{
648 Q_D(const QWaylandQtShellSurface);
649 return d->m_active;
650}
651
652/*!
653 * \qmlproperty enum QtShellSurface::capabilities
654 *
655 * This property holds the capabilities of the compositor. By default, no special capabilities are
656 * enabled.
657 *
658 * \list
659 * \li QtShellSurface.InteractiveMove The client can trigger a server-side interactive move
660 * operation using \l{QWindow::startSystemMove()}. The compositor will be notified of this
661 * through the \l{startMove()} signal.
662 * \li QtShellSurface.InteractiveResize The client can trigger a server-side interactive resize
663 * operation using \l{QWindow::startSystemResize()}. The compositor will be notified of this
664 * through the \l{startResize()} signal.
665 * \endlist
666 */
667
668/*!
669 * \property QWaylandQtShellSurface::capabilities
670 *
671 * This property holds the capabilities of the compositor. By default, no
672 * special capabilities are enabled.
673 *
674 * \list
675 * \li QWaylandQtShellSurface::InteractiveMove The client can trigger a
676 * server-side interactive move operation using
677 * QWindow::startSystemMove(). The compositor will be notified of this
678 * through the startMove() signal.
679 * \li QWaylandQtShellSurface::InteractiveResize The client can trigger a
680 * server-side interactive resize operation using
681 * QWindow::startSystemResize(). The compositor will be notified of this
682 * through the startResize() signal.
683 * \endlist
684 */
685void QWaylandQtShellSurface::setCapabilities(CapabilityFlags capabilities)
686{
687 Q_D(QWaylandQtShellSurface);
688 if (d->m_capabilities == capabilities)
689 return;
690
691 d->m_capabilities = capabilities;
692 d->send_set_capabilities(capabilities);
693
694 emit capabilitiesChanged();
695}
696
697QWaylandQtShellSurface::CapabilityFlags QWaylandQtShellSurface::capabilities() const
698{
699 Q_D(const QWaylandQtShellSurface);
700 return d->m_capabilities;
701}
702
703/*!
704 * \qmlproperty int QtShellSurface::windowState
705 *
706 * This property holds the window state of the QtShellSurface.
707 *
708 * \note When \l{requestWindowGeometry()} is called to update state of the surface, the
709 * \c windowState property will not be updated until the client has acknowledged the state change.
710 */
711
712/*!
713 * \property QWaylandQtShellSurface::windowState
714 *
715 * This property holds the window state of the QWaylandQtShellSurface.
716 *
717 * \note When requestWindowGeometry() is called to update state of the surface,
718 * the windowState property will not be updated until the client has
719 * acknowledged the state change.
720 */
721uint QWaylandQtShellSurface::windowState() const
722{
723 Q_D(const QWaylandQtShellSurface);
724 return d->m_windowState;
725}
726
727void QWaylandQtShellSurface::surfaceCommitted()
728{
729 Q_D(QWaylandQtShellSurface);
730 if (d->m_lastAckedConfigure < UINT32_MAX) {
731 QRect targetRect = d->m_windowGeometry;
732 uint windowState = d->m_windowState;
733 for (auto it = d->m_pendingConfigures.begin(); it != d->m_pendingConfigures.end(); ) {
734 if (it.key() == d->m_lastAckedConfigure) {
735 targetRect = it.value().second;
736 windowState = it.value().first;
737 }
738
739 if (it.key() <= d->m_lastAckedConfigure)
740 it = d->m_pendingConfigures.erase(it);
741 else
742 break;
743 }
744
745 if (d->m_windowState != windowState) {
746 d->m_windowState = windowState;
747 emit windowStateChanged();
748 }
749
750 if (d->m_windowGeometry != targetRect) {
751 d->m_windowGeometry = targetRect;
752 d->m_positionSet = true;
753 emit positionAutomaticChanged();
754 emit windowGeometryChanged();
755 }
756
757 d->m_lastAckedConfigure = UINT32_MAX;
758 d->m_pendingPosition = QPoint{};
759 d->m_pendingPositionValid = false;
760 d->m_pendingSize = QSize{};
761 } else {
762 QRect oldRect = d->m_windowGeometry;
763 if (d->m_pendingPositionValid) {
764 d->m_windowGeometry.moveTopLeft(d->m_pendingPosition);
765 d->m_pendingPosition = QPoint{};
766 d->m_pendingPositionValid = false;
767 d->m_positionSet = true;
768 emit positionAutomaticChanged();
769 }
770
771 if (d->m_pendingSize.isValid()) {
772 d->m_windowGeometry.setSize(d->m_pendingSize);
773 d->m_pendingSize = QSize{};
774 }
775
776 if (d->m_windowGeometry != oldRect)
777 emit windowGeometryChanged();
778 }
779}
780
781/*!
782 * \internal
783 * Returns the Wayland interface for the QWaylandQtShellSurface.
784 */
785const wl_interface *QWaylandQtShellSurface::interface()
786{
787 return QWaylandQtShellSurfacePrivate::interface();
788}
789
790QByteArray QWaylandQtShellSurface::interfaceName()
791{
792 return QWaylandQtShellSurfacePrivate::interfaceName();
793}
794
795/*!
796 * \internal
797 * Returns the surface role for the QWaylandQtShellSurface.
798 */
799QWaylandSurfaceRole *QWaylandQtShellSurface::role()
800{
801 return &QWaylandQtShellSurfacePrivate::s_role;
802}
803
804/*!
805 * \internal
806 * Returns the QWaylandQtShellSurface corresponding to the \a resource.
807 */
808QWaylandQtShellSurface *QWaylandQtShellSurface::fromResource(wl_resource *resource)
809{
810 if (auto p = QtWayland::fromResource<QWaylandQtShellSurfacePrivate *>(resource))
811 return p->q_func();
812 return nullptr;
813}
814
815#if QT_CONFIG(wayland_compositor_quick)
816QWaylandQuickShellIntegration *QWaylandQtShellSurface::createIntegration(QWaylandQuickShellSurfaceItem *item)
817{
818 return new QtWayland::QtShellIntegration(item);
819}
820#endif
821
822/*!
823 * \internal
824 */
825void QWaylandQtShellSurface::initialize()
826{
827 QWaylandShellSurfaceTemplate::initialize();
828}
829
830QWaylandQtShellSurfacePrivate::QWaylandQtShellSurfacePrivate()
831{
832}
833
834void QWaylandQtShellSurfacePrivate::zqt_shell_surface_v1_ack_configure(Resource *resource, uint32_t serial)
835{
836 Q_UNUSED(resource);
837 Q_Q(QWaylandQtShellSurface);
838 if (serial < UINT32_MAX)
839 m_lastAckedConfigure = serial;
840
841 // Fake a surface commit because we won't get one as long as the window is unexposed
842 if (m_windowState & Qt::WindowMinimized)
843 q->surfaceCommitted();
844}
845
846void QWaylandQtShellSurfacePrivate::zqt_shell_surface_v1_reposition(Resource *resource, int32_t x, int32_t y)
847{
848 Q_UNUSED(resource);
849
850 m_pendingPosition = QPoint(x, y);
851 m_pendingPositionValid = true;
852 m_lastAckedConfigure = UINT32_MAX;
853}
854
855void QWaylandQtShellSurfacePrivate::zqt_shell_surface_v1_set_size(Resource *resource, int32_t width, int32_t height)
856{
857 Q_UNUSED(resource);
858
859 m_pendingSize = QSize(width, height);
860 m_lastAckedConfigure = UINT32_MAX;
861}
862
863void QWaylandQtShellSurfacePrivate::zqt_shell_surface_v1_set_minimum_size(Resource *resource, int32_t width, int32_t height)
864{
865 Q_UNUSED(resource);
866 Q_Q(QWaylandQtShellSurface);
867 m_minimumSize = QSize{width, height};
868 emit q->minimumSizeChanged();
869}
870
871void QWaylandQtShellSurfacePrivate::zqt_shell_surface_v1_set_maximum_size(Resource *resource, int32_t width, int32_t height)
872{
873 Q_UNUSED(resource);
874 Q_Q(QWaylandQtShellSurface);
875 m_maximumSize = QSize{width, height};
876 emit q->maximumSizeChanged();
877}
878
879void QWaylandQtShellSurfacePrivate::zqt_shell_surface_v1_destroy_resource(QtWaylandServer::zqt_shell_surface_v1::Resource *resource)
880{
881 Q_UNUSED(resource);
882 Q_Q(QWaylandQtShellSurface);
883 QWaylandQtShellPrivate::get(m_qtShell)->unregisterQtShellSurface(q);
884 delete q;
885}
886
887void QWaylandQtShellSurfacePrivate::zqt_shell_surface_v1_destroy(QtWaylandServer::zqt_shell_surface_v1::Resource *resource)
888{
889 wl_resource_destroy(resource->handle);
890}
891
892void QWaylandQtShellSurfacePrivate::zqt_shell_surface_v1_set_window_flags(Resource *resource, uint32_t flags)
893{
894 Q_UNUSED(resource);
895 Q_Q(QWaylandQtShellSurface);
896 m_windowFlags = flags;
897 emit q->windowFlagsChanged();
898}
899
900void QWaylandQtShellSurfacePrivate::zqt_shell_surface_v1_change_window_state(Resource *resource, uint32_t state)
901{
902 Q_UNUSED(resource);
903 Q_Q(QWaylandQtShellSurface);
904 uint oldWindowState = m_windowState;
905 m_windowState = state & ~Qt::WindowActive;
906
907 if (oldWindowState != m_windowState)
908 emit q->windowStateChanged();
909}
910
911void QWaylandQtShellSurfacePrivate::zqt_shell_surface_v1_start_system_resize(Resource *resource, uint32_t serial, uint32_t edge)
912{
913 Q_UNUSED(resource);
914 Q_UNUSED(serial);
915 Q_Q(QWaylandQtShellSurface);
916 emit q->startResize(Qt::Edges(edge));
917}
918
919void QWaylandQtShellSurfacePrivate::zqt_shell_surface_v1_start_system_move(Resource *resource, uint32_t serial)
920{
921 Q_UNUSED(resource);
922 Q_UNUSED(serial);
923 Q_Q(QWaylandQtShellSurface);
924 emit q->startMove();
925}
926
927void QWaylandQtShellSurfacePrivate::zqt_shell_surface_v1_set_window_title(Resource *resource,
928 const QString &title)
929{
930 Q_UNUSED(resource);
931 Q_Q(QWaylandQtShellSurface);
932 m_windowTitle = title;
933 emit q->windowTitleChanged();
934}
935
936void QWaylandQtShellSurfacePrivate::zqt_shell_surface_v1_request_activate(Resource *resource)
937
938{
939 Q_UNUSED(resource);
940 Q_Q(QWaylandQtShellSurface);
941 q->setActive(true);
942
943 if (m_surface) {
944 auto view = m_surface->primaryView();
945 auto item = view ? qobject_cast<QWaylandQuickItem *>(view->renderObject()) : nullptr;
946 if (item)
947 item->forceActiveFocus();
948 }
949}
950
951void QWaylandQtShellSurfacePrivate::updateFrameMargins()
952{
953 send_set_frame_margins(m_frameMargins.left(), m_frameMargins.right(),
954 m_frameMargins.top(), m_frameMargins.bottom());
955}
956
957
958void QWaylandQtShellSurfacePrivate::zqt_shell_surface_v1_raise(Resource *resource)
959{
960 Q_UNUSED(resource);
961 Q_Q(QWaylandQtShellSurface);
962 emit q->raiseRequested();
963}
964
965void QWaylandQtShellSurfacePrivate::zqt_shell_surface_v1_lower(Resource *resource)
966{
967 Q_UNUSED(resource);
968 Q_Q(QWaylandQtShellSurface);
969 emit q->lowerRequested();
970}
971
972QT_END_NAMESPACE
973
974#include "moc_qwaylandqtshell_p.cpp"