1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include "qwaylandqtshell.h"
5#include "qwaylandqtshell_p.h"
6#include "qwaylandqtshellchrome.h"
7
8#include <QtWaylandCompositor/QWaylandCompositor>
9#include <QtWaylandCompositor/QWaylandSurface>
10#include "qwaylandqtshell.h"
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/compositor_api/qwaylandseat.h>
20
21#include <QtWaylandCompositor/private/qwaylandutils_p.h>
22
23QT_BEGIN_NAMESPACE
24
25/*!
26 * \qmltype QtShell
27 * \instantiates 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 * \qml
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 * \endqml
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(sender: chrome, signal: &QWaylandQtShellChrome::activated, context: this, slot: &QWaylandQtShell::chromeActivated);
96 connect(sender: chrome, signal: &QWaylandQtShellChrome::deactivated, context: this, slot: &QWaylandQtShell::chromeDeactivated);
97}
98
99void QWaylandQtShell::unregisterChrome(QWaylandQtShellChrome *chrome)
100{
101 Q_D(QWaylandQtShell);
102
103 chrome->disconnect(receiver: 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 *>(object: sender());
115 if (c != nullptr) {
116 moveChromeToFront(chrome: c);
117 }
118}
119
120void QWaylandQtShell::chromeDeactivated()
121{
122 Q_D(QWaylandQtShell);
123 QWaylandQtShellChrome *c = qobject_cast<QWaylandQtShellChrome *>(object: 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(resource: surfaceResource);
188
189 if (!surface->setRole(role: QWaylandQtShellSurface::role(), errorResource: resource->handle, errorCode: 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, resource: qtShellSurfaceResource);
196
197 QWaylandQtShellSurface *qtShellSurface = QWaylandQtShellSurface::fromResource(resource: 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 * \instantiates 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(qtShell: 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(sender: d->m_surface, signal: &QWaylandSurface::damaged, context: this, slot: &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(p: 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, newGeometry: 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(value1&: windowState, value2: 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(p: 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 * Returns the Wayland interface for the QWaylandQtShellSurface.
666 */
667const wl_interface *QWaylandQtShellSurface::interface()
668{
669 return QWaylandQtShellSurfacePrivate::interface();
670}
671
672QByteArray QWaylandQtShellSurface::interfaceName()
673{
674 return QWaylandQtShellSurfacePrivate::interfaceName();
675}
676
677/*!
678 * Returns the surface role for the QWaylandQtShellSurface.
679 */
680QWaylandSurfaceRole *QWaylandQtShellSurface::role()
681{
682 return &QWaylandQtShellSurfacePrivate::s_role;
683}
684
685/*!
686 * Returns the QWaylandQtShellSurface corresponding to the \a resource.
687 */
688QWaylandQtShellSurface *QWaylandQtShellSurface::fromResource(wl_resource *resource)
689{
690 if (auto p = QtWayland::fromResource<QWaylandQtShellSurfacePrivate *>(resource))
691 return p->q_func();
692 return nullptr;
693}
694
695#if QT_CONFIG(wayland_compositor_quick)
696QWaylandQuickShellIntegration *QWaylandQtShellSurface::createIntegration(QWaylandQuickShellSurfaceItem *item)
697{
698 return new QtWayland::QtShellIntegration(item);
699}
700#endif
701
702/*!
703 * \internal
704 */
705void QWaylandQtShellSurface::initialize()
706{
707 QWaylandShellSurfaceTemplate::initialize();
708}
709
710QWaylandQtShellSurfacePrivate::QWaylandQtShellSurfacePrivate()
711{
712}
713
714void QWaylandQtShellSurfacePrivate::zqt_shell_surface_v1_ack_configure(Resource *resource, uint32_t serial)
715{
716 Q_UNUSED(resource);
717 Q_Q(QWaylandQtShellSurface);
718 if (serial < UINT32_MAX)
719 m_lastAckedConfigure = serial;
720
721 // Fake a surface commit because we won't get one as long as the window is unexposed
722 if (m_windowState & Qt::WindowMinimized)
723 q->surfaceCommitted();
724}
725
726void QWaylandQtShellSurfacePrivate::zqt_shell_surface_v1_reposition(Resource *resource, int32_t x, int32_t y)
727{
728 Q_UNUSED(resource);
729
730 m_pendingPosition = QPoint(x, y);
731 m_pendingPositionValid = true;
732 m_lastAckedConfigure = UINT32_MAX;
733}
734
735void QWaylandQtShellSurfacePrivate::zqt_shell_surface_v1_set_size(Resource *resource, int32_t width, int32_t height)
736{
737 Q_UNUSED(resource);
738
739 m_pendingSize = QSize(width, height);
740 m_lastAckedConfigure = UINT32_MAX;
741}
742
743void QWaylandQtShellSurfacePrivate::zqt_shell_surface_v1_set_minimum_size(Resource *resource, int32_t width, int32_t height)
744{
745 Q_UNUSED(resource);
746 Q_Q(QWaylandQtShellSurface);
747 m_minimumSize = QSize{width, height};
748 emit q->minimumSizeChanged();
749}
750
751void QWaylandQtShellSurfacePrivate::zqt_shell_surface_v1_set_maximum_size(Resource *resource, int32_t width, int32_t height)
752{
753 Q_UNUSED(resource);
754 Q_Q(QWaylandQtShellSurface);
755 m_maximumSize = QSize{width, height};
756 emit q->maximumSizeChanged();
757}
758
759void QWaylandQtShellSurfacePrivate::zqt_shell_surface_v1_destroy_resource(QtWaylandServer::zqt_shell_surface_v1::Resource *resource)
760{
761 Q_UNUSED(resource);
762 Q_Q(QWaylandQtShellSurface);
763 QWaylandQtShellPrivate::get(qtShell: m_qtShell)->unregisterQtShellSurface(qtShellSurface: q);
764 delete q;
765}
766
767void QWaylandQtShellSurfacePrivate::zqt_shell_surface_v1_destroy(QtWaylandServer::zqt_shell_surface_v1::Resource *resource)
768{
769 wl_resource_destroy(resource->handle);
770}
771
772void QWaylandQtShellSurfacePrivate::zqt_shell_surface_v1_set_window_flags(Resource *resource, uint32_t flags)
773{
774 Q_UNUSED(resource);
775 Q_Q(QWaylandQtShellSurface);
776 m_windowFlags = flags;
777 emit q->windowFlagsChanged();
778}
779
780void QWaylandQtShellSurfacePrivate::zqt_shell_surface_v1_change_window_state(Resource *resource, uint32_t state)
781{
782 Q_UNUSED(resource);
783 Q_Q(QWaylandQtShellSurface);
784 uint oldWindowState = m_windowState;
785 m_windowState = state & ~Qt::WindowActive;
786
787 if (oldWindowState != m_windowState)
788 emit q->windowStateChanged();
789}
790
791void QWaylandQtShellSurfacePrivate::zqt_shell_surface_v1_start_system_resize(Resource *resource, uint32_t serial, uint32_t edge)
792{
793 Q_UNUSED(resource);
794 Q_UNUSED(serial);
795 Q_Q(QWaylandQtShellSurface);
796 emit q->startResize(edges: Qt::Edges(edge));
797}
798
799void QWaylandQtShellSurfacePrivate::zqt_shell_surface_v1_start_system_move(Resource *resource, uint32_t serial)
800{
801 Q_UNUSED(resource);
802 Q_UNUSED(serial);
803 Q_Q(QWaylandQtShellSurface);
804 emit q->startMove();
805}
806
807void QWaylandQtShellSurfacePrivate::zqt_shell_surface_v1_set_window_title(Resource *resource,
808 const QString &title)
809{
810 Q_UNUSED(resource);
811 Q_Q(QWaylandQtShellSurface);
812 m_windowTitle = title;
813 emit q->windowTitleChanged();
814}
815
816void QWaylandQtShellSurfacePrivate::zqt_shell_surface_v1_request_activate(Resource *resource)
817
818{
819 Q_UNUSED(resource);
820 Q_Q(QWaylandQtShellSurface);
821 q->setActive(true);
822}
823
824void QWaylandQtShellSurfacePrivate::updateFrameMargins()
825{
826 send_set_frame_margins(m_frameMargins.left(), m_frameMargins.right(),
827 m_frameMargins.top(), m_frameMargins.bottom());
828}
829
830
831void QWaylandQtShellSurfacePrivate::zqt_shell_surface_v1_raise(Resource *resource)
832{
833 Q_UNUSED(resource);
834 Q_Q(QWaylandQtShellSurface);
835 emit q->raiseRequested();
836}
837
838void QWaylandQtShellSurfacePrivate::zqt_shell_surface_v1_lower(Resource *resource)
839{
840 Q_UNUSED(resource);
841 Q_Q(QWaylandQtShellSurface);
842 emit q->lowerRequested();
843}
844
845QT_END_NAMESPACE
846
847#include "moc_qwaylandqtshell.cpp"
848

source code of qtwayland/src/imports/compositor-extensions/qtshell/qwaylandqtshell.cpp