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