Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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
4#include "qwaylandqtshell.h"
5#include "qwaylandqtshell_p.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)
15#endif
16
17#include <QtWaylandCompositor/QWaylandResource>
18#include <QDebug>
20
21#include <QtWaylandCompositor/private/qwaylandutils_p.h>
22
24
57
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
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
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
133{
134 Q_D(QWaylandQtShell);
136
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
155{
156 return QWaylandQtShellPrivate::interfaceName();
157}
158
178
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
254
260
268{
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());
278
280
282}
283
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
307{
308 Q_D(const QWaylandQtShellSurface);
309 return d->m_windowGeometry.topLeft();
310}
311
313{
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;
324}
325
332{
333 Q_D(const QWaylandQtShellSurface);
334 return d->m_windowGeometry;
335}
336
343{
344 Q_D(const QWaylandQtShellSurface);
345 return d->m_minimumSize;
346}
347
354{
355 Q_D(const QWaylandQtShellSurface);
356 return d->m_maximumSize;
357}
358
366void QWaylandQtShellSurface::requestWindowGeometry(uint windowState, const QRect &windowGeometry)
367{
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
393{
395 if (d->m_frameMargins == margins)
396 return;
397
398 d->m_frameMargins = margins;
399 d->updateFrameMargins();
400
402}
403
410{
412 if (d->m_frameMargins.left() == left)
413 return;
414
415 d->m_frameMargins.setLeft(left);
416 d->updateFrameMargins();
417
419}
420
422{
423 Q_D(const QWaylandQtShellSurface);
424 return d->m_frameMargins.left();
425}
426
433{
435 if (d->m_frameMargins.right() == right)
436 return;
437
438 d->m_frameMargins.setRight(right);
439 d->updateFrameMargins();
440
442}
443
445{
446 Q_D(const QWaylandQtShellSurface);
447 return d->m_frameMargins.right();
448}
449
457{
459 if (d->m_frameMargins.top() == top)
460 return;
461 d->m_frameMargins.setTop(top);
462 d->updateFrameMargins();
463
465}
466
468{
469 Q_D(const QWaylandQtShellSurface);
470 return d->m_frameMargins.top();
471}
472
479{
481 if (d->m_frameMargins.bottom() == bottom)
482 return;
483 d->m_frameMargins.setBottom(bottom);
484 d->updateFrameMargins();
485
487}
488
490{
491 Q_D(const QWaylandQtShellSurface);
492 return !d->m_positionSet;
493}
494
496{
497 Q_D(const QWaylandQtShellSurface);
498 return d->m_frameMargins.bottom();
499}
500
507{
508 Q_D(const QWaylandQtShellSurface);
509 return d->m_windowFlags;
510}
511
518{
520 d->send_close();
521}
522
529{
530 Q_D(const QWaylandQtShellSurface);
531 return d->m_windowTitle;
532}
533
544{
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());
555}
556
558{
559 Q_D(const QWaylandQtShellSurface);
560 return d->m_active;
561}
562
578void QWaylandQtShellSurface::setCapabilities(CapabilityFlags capabilities)
579{
581 if (d->m_capabilities == capabilities)
582 return;
583
584 d->m_capabilities = capabilities;
585 d->send_set_capabilities(capabilities);
586
588}
589
590QWaylandQtShellSurface::CapabilityFlags QWaylandQtShellSurface::capabilities() const
591{
592 Q_D(const QWaylandQtShellSurface);
593 return d->m_capabilities;
594}
595
605{
606 Q_D(const QWaylandQtShellSurface);
607 return d->m_windowState;
608}
609
610void QWaylandQtShellSurface::surfaceCommitted()
611{
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;
631 }
632
633 if (d->m_windowGeometry != targetRect) {
634 d->m_windowGeometry = targetRect;
635 d->m_positionSet = true;
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;
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)
661 }
662}
663
668{
669 return QWaylandQtShellSurfacePrivate::interface();
670}
671
673{
674 return QWaylandQtShellSurfacePrivate::interfaceName();
675}
676
681{
682 return &QWaylandQtShellSurfacePrivate::s_role;
683}
684
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{
699}
700#endif
701
709
713
715{
716 Q_UNUSED(resource);
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
727{
728 Q_UNUSED(resource);
729
730 m_pendingPosition = QPoint(x, y);
731 m_pendingPositionValid = true;
732 m_lastAckedConfigure = UINT32_MAX;
733}
734
736{
737 Q_UNUSED(resource);
738
739 m_pendingSize = QSize(width, height);
740 m_lastAckedConfigure = UINT32_MAX;
741}
742
744{
745 Q_UNUSED(resource);
747 m_minimumSize = QSize{width, height};
748 emit q->minimumSizeChanged();
749}
750
752{
753 Q_UNUSED(resource);
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);
763 QWaylandQtShellPrivate::get(m_qtShell)->unregisterQtShellSurface(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
773{
774 Q_UNUSED(resource);
776 m_windowFlags = flags;
777 emit q->windowFlagsChanged();
778}
779
781{
782 Q_UNUSED(resource);
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);
796 emit q->startResize(Qt::Edges(edge));
797}
798
800{
801 Q_UNUSED(resource);
802 Q_UNUSED(serial);
804 emit q->startMove();
805}
806
808 const QString &title)
809{
810 Q_UNUSED(resource);
812 m_windowTitle = title;
813 emit q->windowTitleChanged();
814}
815
817
818{
819 Q_UNUSED(resource);
821 q->setActive(true);
822}
823
825{
826 send_set_frame_margins(m_frameMargins.left(), m_frameMargins.right(),
827 m_frameMargins.top(), m_frameMargins.bottom());
828}
829
830
832{
833 Q_UNUSED(resource);
835 emit q->raiseRequested();
836}
837
839{
840 Q_UNUSED(resource);
842 emit q->lowerRequested();
843}
844
846
847#include "moc_qwaylandqtshell.cpp"
\inmodule QtCore
Definition qbytearray.h:57
\inmodule QtCore
Definition qmargins.h:24
constexpr int bottom() const noexcept
Returns the bottom margin.
Definition qmargins.h:115
constexpr int left() const noexcept
Returns the left margin.
Definition qmargins.h:106
constexpr int right() const noexcept
Returns the right margin.
Definition qmargins.h:112
constexpr int top() const noexcept
Returns the top margin.
Definition qmargins.h:109
QObject * sender() const
Returns a pointer to the object that sent the signal, if called in a slot activated by a signal; othe...
Definition qobject.cpp:2658
\inmodule QtCore\reentrant
Definition qpoint.h:25
\inmodule QtCore\reentrant
Definition qrect.h:30
constexpr void moveTopLeft(const QPoint &p) noexcept
Moves the rectangle, leaving the top-left corner at the given position.
Definition qrect.h:304
constexpr int height() const noexcept
Returns the height of the rectangle.
Definition qrect.h:239
constexpr bool isValid() const noexcept
Returns true if the rectangle is valid, otherwise returns false.
Definition qrect.h:170
constexpr int x() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:185
constexpr int width() const noexcept
Returns the width of the rectangle.
Definition qrect.h:236
constexpr int y() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:188
iterator begin()
Definition qset.h:136
iterator end()
Definition qset.h:140
iterator erase(const_iterator i)
Definition qset.h:145
\inmodule QtCore
Definition qsize.h:25
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
void setExtensionContainer(QWaylandObject *container)
Sets the extension container for this QWaylandCompositorExtension to container.
virtual void initialize()
Initializes the QWaylandCompositorExtension.
\qmltype WaylandCompositor \instantiates QWaylandCompositor \inqmlmodule QtWayland....
void activate()
\qmlmethod void QtShellChrome::activate()
void unregisterQtShellSurface(QWaylandQtShellSurface *qtShellSurface)
QWaylandQtShellPrivate()
\qmlsignal void QtShell::qtShellSurfaceRequested(WaylandSurface surface, WaylandResource resource)
static QWaylandQtShellPrivate * get(QWaylandQtShell *qtShell)
void zqt_shell_v1_surface_create(Resource *resource, wl_resource *surface, uint32_t id) override
void zqt_shell_surface_v1_raise(Resource *resource) override
void zqt_shell_surface_v1_start_system_move(Resource *resource, uint32_t serial) override
void zqt_shell_surface_v1_request_activate(Resource *resource) override
void zqt_shell_surface_v1_start_system_resize(Resource *resource, uint32_t serial, uint32_t edge) override
void zqt_shell_surface_v1_ack_configure(Resource *resource, uint32_t serial) override
void zqt_shell_surface_v1_set_window_flags(Resource *resource, uint32_t flags) override
void zqt_shell_surface_v1_set_size(Resource *resource, int32_t width, int32_t height) override
void zqt_shell_surface_v1_reposition(Resource *resource, int32_t x, int32_t y) override
void zqt_shell_surface_v1_change_window_state(Resource *resource, uint32_t state) override
void configure(uint windowState, const QRect &newGeometry)
void zqt_shell_surface_v1_destroy(Resource *resource) override
void zqt_shell_surface_v1_set_maximum_size(Resource *resource, int32_t width, int32_t height) override
void zqt_shell_surface_v1_destroy_resource(Resource *resource) override
void zqt_shell_surface_v1_set_window_title(Resource *resource, const QString &title) override
void zqt_shell_surface_v1_lower(Resource *resource) override
void zqt_shell_surface_v1_set_minimum_size(Resource *resource, int32_t width, int32_t height) override
Q_INVOKABLE void requestWindowGeometry(uint windowState, const QRect &windowGeometry)
\qmlmethod void QtShellSurface::requestWindowGeometry(int windowState, rect windowGeometry)
QWaylandSurface * surface
static const wl_interface * interface()
Returns the Wayland interface for the QWaylandQtShellSurface.
static QByteArray interfaceName()
void setFrameMargins(const QMargins &margins)
static QWaylandSurfaceRole * role()
Returns the surface role for the QWaylandQtShellSurface.
void setCapabilities(CapabilityFlags capabilities)
\qmlproperty enum QtShellSurface::capabilities
void setActive(bool active)
\qmlproperty bool QtShellSurface::active
QWaylandQtShellSurface()
\qmltype QtShellSurface \instantiates QWaylandQtShellSurface \inqmlmodule QtWayland....
CapabilityFlags capabilities
void setFrameMarginLeft(int left)
\qmlproperty int QtShellSurface::frameMarginLeft
static QWaylandQtShellSurface * fromResource(::wl_resource *resource)
Returns the QWaylandQtShellSurface corresponding to the resource.
Q_INVOKABLE void sendClose()
\qmlmethod void QtShellSurface::sendClose()
void setFrameMarginBottom(int bottom)
\qmlproperty int QtShellSurface::frameMarginBottom
void setFrameMarginRight(int right)
\qmlproperty int QtShellSurface::frameMarginRight
void setFrameMarginTop(int top)
\qmlproperty int QtShellSurface::frameMarginTop
void setWindowPosition(const QPoint &position)
static const struct wl_interface * interface()
void initialize() override
Initializes the QWaylandCompositorExtension.
void registerChrome(QWaylandQtShellChrome *chrome)
static QByteArray interfaceName()
void unregisterChrome(QWaylandQtShellChrome *chrome)
QWaylandQtShell()
\qmltype QtShell \instantiates QWaylandQtShell \inqmlmodule QtWayland.Compositor.QtShell
\qmltype ShellSurfaceItem \instantiates QWaylandQuickShellSurfaceItem \inherits WaylandQuickItem \inq...
\inmodule QtWaylandCompositor
wl_resource * resource() const
\qmltype WaylandSeat \instantiates QWaylandSeat \inqmlmodule QtWayland.Compositor
bool setKeyboardFocus(QWaylandSurface *surface)
Sets the current keyboard focus to surface.
\inmodule QtWaylandCompositor
\inmodule QtWaylandCompositor
\qmltype WaylandSurface \instantiates QWaylandSurface \inqmlmodule QtWayland.Compositor
static QWaylandSurface * fromResource(::wl_resource *resource)
Returns the QWaylandSurface corresponding to the Wayland resource resource.
QWaylandCompositor * compositor() const
Returns the compositor for this QWaylandSurface.
bool setRole(QWaylandSurfaceRole *role, wl_resource *errorResource, uint32_t errorCode)
Sets a role on the surface.
void damaged(const QRegion &rect)
QSet< QString >::iterator it
else opt state
[0]
Combined button and popup list for selecting options.
Definition qcompare.h:63
@ WindowMinimized
Definition qnamespace.h:253
@ WindowActive
Definition qnamespace.h:256
#define qWarning
Definition qlogging.h:166
static QOpenGLCompositor * compositor
GLint GLint GLint GLint GLint x
[0]
GLint GLsizei GLsizei height
GLuint index
[2]
GLdouble GLdouble GLdouble GLdouble top
GLdouble GLdouble right
GLint GLsizei width
GLint left
GLint GLint bottom
GLbitfield flags
GLint y
const GLubyte * c
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLfloat GLfloat p
[1]
QT_BEGIN_NAMESPACE constexpr decltype(auto) qMakePair(T1 &&value1, T2 &&value2) noexcept(noexcept(std::make_pair(std::forward< T1 >(value1), std::forward< T2 >(value2))))
Definition qpair.h:19
static qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine)
#define emit
#define Q_UNUSED(x)
unsigned int uint
Definition qtypes.h:34
connect(quitButton, &QPushButton::clicked, &app, &QCoreApplication::quit, Qt::QueuedConnection)
QObject::connect nullptr
QString title
[35]
QGraphicsItem * item