7#if QT_CONFIG(wayland_compositor_quick)
8#include "qwaylandxdgshellintegration_p.h"
10#include <QtWaylandCompositor/private/qwaylandutils_p.h>
14#include <QtWaylandCompositor/QWaylandCompositor>
15#include <QtWaylandCompositor/QWaylandSeat>
16#include <QtWaylandCompositor/QWaylandSurface>
17#include <QtWaylandCompositor/QWaylandSurfaceRole>
18#include <QtWaylandCompositor/QWaylandResource>
20#include <QtCore/QObject>
26QWaylandXdgShellPrivate::QWaylandXdgShellPrivate()
30void QWaylandXdgShellPrivate::ping(QtWaylandServer::xdg_wm_base::Resource *resource, uint32_t serial)
32 m_pings.insert(serial);
33 send_ping(resource->handle, serial);
36void QWaylandXdgShellPrivate::registerXdgSurface(QWaylandXdgSurface *xdgSurface)
38 m_xdgSurfaces.insert(xdgSurface->surface()->client()->client(), xdgSurface);
41void QWaylandXdgShellPrivate::unregisterXdgSurface(QWaylandXdgSurface *xdgSurface)
43 auto xdgSurfacePrivate = QWaylandXdgSurfacePrivate::get(xdgSurface);
44 if (!m_xdgSurfaces.remove(xdgSurfacePrivate->resource()->client(), xdgSurface))
45 qWarning(
"%s Unexpected state. Can't find registered xdg surface\n", Q_FUNC_INFO);
48QWaylandXdgSurface *QWaylandXdgShellPrivate::xdgSurfaceFromSurface(QWaylandSurface *surface)
50 for (QWaylandXdgSurface *xdgSurface : std::as_const(m_xdgSurfaces)) {
51 if (surface == xdgSurface->surface())
57void QWaylandXdgShellPrivate::xdg_wm_base_destroy(Resource *resource)
59 if (!m_xdgSurfaces.values(resource->client()).empty())
60 wl_resource_post_error(resource->handle, XDG_WM_BASE_ERROR_DEFUNCT_SURFACES,
61 "xdg_shell was destroyed before children");
63 wl_resource_destroy(resource->handle);
66void QWaylandXdgShellPrivate::xdg_wm_base_create_positioner(QtWaylandServer::xdg_wm_base::Resource *resource, uint32_t id)
68 QWaylandResource positionerResource(wl_resource_create(resource->client(), &xdg_positioner_interface,
69 wl_resource_get_version(resource->handle), id));
71 new QWaylandXdgPositioner(positionerResource);
74void QWaylandXdgShellPrivate::xdg_wm_base_get_xdg_surface(Resource *resource, uint32_t id, wl_resource *surfaceResource)
76 Q_Q(QWaylandXdgShell);
77 QWaylandSurface *surface = QWaylandSurface::fromResource(surfaceResource);
79 if (surface->hasContent()) {
81 qWarning() <<
"get_xdg_surface requested on a xdg_surface with content";
84 QWaylandResource xdgSurfaceResource(wl_resource_create(resource->client(), &xdg_surface_interface,
85 wl_resource_get_version(resource->handle), id));
87 QWaylandXdgSurface *xdgSurface =
new QWaylandXdgSurface(q, surface, xdgSurfaceResource);
89 registerXdgSurface(xdgSurface);
90 emit q->xdgSurfaceCreated(xdgSurface);
93void QWaylandXdgShellPrivate::xdg_wm_base_pong(Resource *resource, uint32_t serial)
96 Q_Q(QWaylandXdgShell);
97 if (m_pings.remove(serial))
100 qWarning(
"Received an unexpected pong!");
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
132
133
134
135
136
137
138
139
140
141
142
145
146
147QWaylandXdgShell::QWaylandXdgShell()
148 : QWaylandShellTemplate<QWaylandXdgShell>(*
new QWaylandXdgShellPrivate())
153
154
155QWaylandXdgShell::QWaylandXdgShell(QWaylandCompositor *compositor)
156 : QWaylandShellTemplate<QWaylandXdgShell>(compositor, *
new QWaylandXdgShellPrivate())
161
162
163void QWaylandXdgShell::initialize()
165 Q_D(QWaylandXdgShell);
166 QWaylandShellTemplate::initialize();
167 QWaylandCompositor *compositor =
static_cast<QWaylandCompositor *>(extensionContainer());
169 qWarning() <<
"Failed to find QWaylandCompositor when initializing QWaylandXdgShell";
172 d->init(compositor->display(), 1);
174 handleSeatChanged(compositor->defaultSeat(),
nullptr);
176 connect(compositor, &QWaylandCompositor::defaultSeatChanged,
177 this, &QWaylandXdgShell::handleSeatChanged);
180 QObject *dialogExtension =
new QWaylandXdgDialogV1Global(compositor);
181 dialogExtension->setParent(
this);
185
186
187const struct wl_interface *QWaylandXdgShell::interface()
189 return QWaylandXdgShellPrivate::interface();
192QByteArray QWaylandXdgShell::interfaceName()
194 return QWaylandXdgShellPrivate::interfaceName();
198
199
200
201
202
205
206
207
208uint QWaylandXdgShell::ping(QWaylandClient *client)
210 Q_D(QWaylandXdgShell);
212 QWaylandCompositor *compositor =
static_cast<QWaylandCompositor *>(extensionContainer());
213 Q_ASSERT(compositor);
215 uint32_t serial = compositor->nextSerial();
217 QWaylandXdgShellPrivate::Resource *clientResource = d->resourceMap().value(client->client(),
nullptr);
218 Q_ASSERT(clientResource);
220 d->ping(clientResource, serial);
224void QWaylandXdgShell::handleSeatChanged(QWaylandSeat *newSeat, QWaylandSeat *oldSeat)
226 if (oldSeat !=
nullptr) {
227 disconnect(oldSeat, &QWaylandSeat::keyboardFocusChanged,
228 this, &QWaylandXdgShell::handleFocusChanged);
231 if (newSeat !=
nullptr) {
232 connect(newSeat, &QWaylandSeat::keyboardFocusChanged,
233 this, &QWaylandXdgShell::handleFocusChanged);
237void QWaylandXdgShell::handleFocusChanged(QWaylandSurface *newSurface, QWaylandSurface *oldSurface)
239 Q_D(QWaylandXdgShell);
241 QWaylandXdgSurface *newXdgSurface = d->xdgSurfaceFromSurface(newSurface);
242 QWaylandXdgSurface *oldXdgSurface = d->xdgSurfaceFromSurface(oldSurface);
245 QWaylandXdgSurfacePrivate::get(newXdgSurface)->handleFocusReceived();
248 QWaylandXdgSurfacePrivate::get(oldXdgSurface)->handleFocusLost();
251QWaylandXdgSurfacePrivate::QWaylandXdgSurfacePrivate()
255void QWaylandXdgSurfacePrivate::setWindowType(Qt::WindowType windowType)
257 if (m_windowType == windowType)
260 m_windowType = windowType;
262 Q_Q(QWaylandXdgSurface);
263 emit q->windowTypeChanged();
266void QWaylandXdgSurfacePrivate::handleFocusLost()
269 QWaylandXdgToplevelPrivate::get(m_toplevel)->handleFocusLost();
272void QWaylandXdgSurfacePrivate::handleFocusReceived()
275 QWaylandXdgToplevelPrivate::get(m_toplevel)->handleFocusReceived();
278QRect QWaylandXdgSurfacePrivate::calculateFallbackWindowGeometry()
const
282 return QRect(QPoint(), m_surface->destinationSize());
285void QWaylandXdgSurfacePrivate::updateFallbackWindowGeometry()
287 Q_Q(QWaylandXdgSurface);
288 if (!m_unsetWindowGeometry)
291 const QRect unsetGeometry = calculateFallbackWindowGeometry();
292 if (unsetGeometry == m_windowGeometry)
295 m_windowGeometry = unsetGeometry;
296 emit q->windowGeometryChanged();
299void QWaylandXdgSurfacePrivate::xdg_surface_destroy_resource(QtWaylandServer::xdg_surface::Resource *resource)
302 Q_Q(QWaylandXdgSurface);
303 QWaylandXdgShellPrivate::get(m_xdgShell)->unregisterXdgSurface(q);
307void QWaylandXdgSurfacePrivate::xdg_surface_destroy(QtWaylandServer::xdg_surface::Resource *resource)
309 wl_resource_destroy(resource->handle);
312void QWaylandXdgSurfacePrivate::xdg_surface_get_toplevel(QtWaylandServer::xdg_surface::Resource *resource, uint32_t id)
314 Q_Q(QWaylandXdgSurface);
316 if (m_toplevel || m_popup) {
317 wl_resource_post_error(resource->handle, XDG_SURFACE_ERROR_ALREADY_CONSTRUCTED,
318 "xdg_surface already has a role object");
322 if (!m_surface->setRole(QWaylandXdgToplevel::role(), resource->handle, XDG_WM_BASE_ERROR_ROLE))
325 QWaylandResource topLevelResource(wl_resource_create(resource->client(), &xdg_toplevel_interface,
326 wl_resource_get_version(resource->handle), id));
328 m_toplevel =
new QWaylandXdgToplevel(q, topLevelResource);
329 emit q->toplevelCreated();
330 emit m_xdgShell->toplevelCreated(m_toplevel, q);
331 q->connect(m_toplevel, &QWaylandXdgToplevel::modalChanged, q, [q,
this](){
332 q->setModal(m_toplevel->isModal());
336void QWaylandXdgSurfacePrivate::xdg_surface_get_popup(QtWaylandServer::xdg_surface::Resource *resource, uint32_t id, wl_resource *parentResource, wl_resource *positionerResource)
338 Q_Q(QWaylandXdgSurface);
340 if (m_toplevel || m_popup) {
341 wl_resource_post_error(resource->handle, XDG_SURFACE_ERROR_ALREADY_CONSTRUCTED,
342 "xdg_surface already has a role object");
346 QWaylandXdgSurface *parent = QWaylandXdgSurface::fromResource(parentResource);
348 wl_resource_post_error(resource->handle, XDG_WM_BASE_ERROR_INVALID_POPUP_PARENT,
349 "xdg_surface.get_popup with invalid popup parent");
353 QWaylandXdgPositioner *positioner = QWaylandXdgPositioner::fromResource(positionerResource);
355 wl_resource_post_error(resource->handle, XDG_WM_BASE_ERROR_INVALID_POSITIONER,
356 "xdg_surface.get_popup without positioner");
360 if (!positioner->m_data.isComplete()) {
361 QWaylandXdgPositionerData p = positioner->m_data;
362 wl_resource_post_error(resource->handle, XDG_WM_BASE_ERROR_INVALID_POSITIONER,
363 "xdg_surface.get_popup with invalid positioner (size: %dx%d, anchorRect: %dx%d)",
364 p.size.width(), p.size.height(), p.anchorRect.width(), p.anchorRect.height());
368 QRect anchorBounds(QPoint(0, 0), parent->windowGeometry().size());
369 if (!anchorBounds.contains(positioner->m_data.anchorRect)) {
375 qCWarning(qLcWaylandCompositor) <<
"Ignoring client protocol error: xdg_positioner anchor"
376 <<
"rect extends beyond its parent's window geometry";
379 if (!m_surface->setRole(QWaylandXdgPopup::role(), resource->handle, XDG_WM_BASE_ERROR_ROLE))
382 QWaylandResource popupResource(wl_resource_create(resource->client(), &xdg_popup_interface,
383 wl_resource_get_version(resource->handle), id));
385 m_popup =
new QWaylandXdgPopup(q, parent, positioner, popupResource);
386 emit q->popupCreated();
387 emit m_xdgShell->popupCreated(m_popup, q);
390void QWaylandXdgSurfacePrivate::xdg_surface_ack_configure(QtWaylandServer::xdg_surface::Resource *resource, uint32_t serial)
393 QWaylandXdgToplevelPrivate::get(m_toplevel)->handleAckConfigure(serial);
394 }
else if (m_popup) {
395 QWaylandXdgPopupPrivate::get(m_popup)->handleAckConfigure(serial);
397 wl_resource_post_error(resource->handle, XDG_SURFACE_ERROR_NOT_CONSTRUCTED,
398 "ack_configure requested on an unconstructed xdg_surface");
402void QWaylandXdgSurfacePrivate::xdg_surface_set_window_geometry(QtWaylandServer::xdg_surface::Resource *resource, int32_t x, int32_t y, int32_t width, int32_t height)
404 Q_Q(QWaylandXdgSurface);
406 if (!q->surface()->role()) {
407 wl_resource_post_error(resource->handle, XDG_SURFACE_ERROR_NOT_CONSTRUCTED,
408 "set_window_geometry requested on an unconstructed xdg_surface");
412 if (width <= 0 || height <= 0) {
416 qWarning() <<
"Invalid (non-positive) dimensions received in set_window_geometry";
420 m_unsetWindowGeometry =
false;
422 QRect geometry(x, y, width, height);
424 if (m_windowGeometry == geometry)
427 m_windowGeometry = geometry;
428 emit q->windowGeometryChanged();
432
433
434
435
436
437
438
439
440
441
442
443
444
447
448
449
450
451
452
453
454
455
456
457
458
461
462
463QWaylandXdgSurface::QWaylandXdgSurface()
464 : QWaylandShellSurfaceTemplate<QWaylandXdgSurface>(*
new QWaylandXdgSurfacePrivate)
469
470
471
472QWaylandXdgSurface::QWaylandXdgSurface(QWaylandXdgShell *xdgShell, QWaylandSurface *surface,
const QWaylandResource &res)
473 : QWaylandShellSurfaceTemplate<QWaylandXdgSurface>(*
new QWaylandXdgSurfacePrivate)
475 initialize(xdgShell, surface, res);
479
480
481
482
483
486
487
488
489void QWaylandXdgSurface::initialize(QWaylandXdgShell *xdgShell, QWaylandSurface *surface,
const QWaylandResource &resource)
491 Q_D(QWaylandXdgSurface);
492 d->m_xdgShell = xdgShell;
493 d->m_surface = surface;
494 d->init(resource.resource());
495 setExtensionContainer(surface);
496 d->m_windowGeometry = d->calculateFallbackWindowGeometry();
497 connect(surface, &QWaylandSurface::destinationSizeChanged,
this, &QWaylandXdgSurface::handleSurfaceSizeChanged);
498 connect(surface, &QWaylandSurface::bufferScaleChanged,
this, &QWaylandXdgSurface::handleBufferScaleChanged);
500 emit surfaceChanged();
501 QWaylandCompositorExtension::initialize();
505
506
507
508
509Qt::WindowType QWaylandXdgSurface::windowType()
const
511 Q_D(
const QWaylandXdgSurface);
512 return d->m_windowType;
516
517
518
519
520
521
522
523
526
527
528
529
530
531
532
533
534QRect QWaylandXdgSurface::windowGeometry()
const
536 Q_D(
const QWaylandXdgSurface);
537 return d->m_windowGeometry;
541
542
543void QWaylandXdgSurface::initialize()
545 QWaylandCompositorExtension::initialize();
548void QWaylandXdgSurface::handleSurfaceSizeChanged()
550 Q_D(QWaylandXdgSurface);
551 d->updateFallbackWindowGeometry();
554void QWaylandXdgSurface::handleBufferScaleChanged()
556 Q_D(QWaylandXdgSurface);
557 d->updateFallbackWindowGeometry();
561
562
563
564
567
568
569
570
571QWaylandXdgShell *QWaylandXdgSurface::shell()
const
573 Q_D(
const QWaylandXdgSurface);
574 return d->m_xdgShell;
578
579
580
581
584
585
586
587
588QWaylandSurface *QWaylandXdgSurface::surface()
const
590 Q_D(
const QWaylandXdgSurface);
595
596
597
598
599
600
601
604
605
606
607
608
609
610
611QWaylandXdgToplevel *QWaylandXdgSurface::toplevel()
const
613 Q_D(
const QWaylandXdgSurface);
614 return d->m_toplevel;
618
619
620
621
622
623
624
627
628
629
630
631
632
633
634QWaylandXdgPopup *QWaylandXdgSurface::popup()
const
636 Q_D(
const QWaylandXdgSurface);
641
642
643const wl_interface *QWaylandXdgSurface::interface()
645 return QWaylandXdgSurfacePrivate::interface();
649
650
651QByteArray QWaylandXdgSurface::interfaceName()
653 return QWaylandXdgSurfacePrivate::interfaceName();
657
658
659QWaylandXdgSurface *QWaylandXdgSurface::fromResource(wl_resource *resource)
661 if (
auto p = QtWayland::fromResource<QWaylandXdgSurfacePrivate *>(resource))
666#if QT_CONFIG(wayland_compositor_quick)
667QWaylandQuickShellIntegration *QWaylandXdgSurface::createIntegration(QWaylandQuickShellSurfaceItem *item)
669 Q_D(
const QWaylandXdgSurface);
672 return new QtWayland::XdgToplevelIntegration(item);
675 return new QtWayland::XdgPopupIntegration(item);
682
683
684
685
686
687
688
689
690
691
692
693
696
697
698
699
700
701
702
703
704
705
706
709
710
711QWaylandXdgToplevel::QWaylandXdgToplevel(QWaylandXdgSurface *xdgSurface, QWaylandResource &resource)
712 : QObject(*
new QWaylandXdgToplevelPrivate(xdgSurface, resource))
714 QList<QWaylandXdgToplevel::State> states;
715 sendConfigure({0, 0}, states);
718QWaylandXdgToplevel::~QWaylandXdgToplevel()
720 Q_D(QWaylandXdgToplevel);
723 if (Q_UNLIKELY(d->m_decoration))
724 wl_resource_destroy(d->m_decoration->resource()->handle);
725 Q_ASSERT(!d->m_decoration);
729
730
731
732
735
736
737
738
739QWaylandXdgSurface *QWaylandXdgToplevel::xdgSurface()
const
741 Q_D(
const QWaylandXdgToplevel);
742 return d->m_xdgSurface;
746
747
748
749
752
753
754
755
756
757QWaylandXdgToplevel *QWaylandXdgToplevel::parentToplevel()
const
759 Q_D(
const QWaylandXdgToplevel);
760 return d->m_parentToplevel;
764
765
766
767
770
771
772
773
774QString QWaylandXdgToplevel::title()
const
776 Q_D(
const QWaylandXdgToplevel);
781
782
783
784
787
788
789
790
791QString QWaylandXdgToplevel::appId()
const
793 Q_D(
const QWaylandXdgToplevel);
798
799
800
801
802
803
806
807
808
809
810
811
812QSize QWaylandXdgToplevel::maxSize()
const
814 Q_D(
const QWaylandXdgToplevel);
819
820
821
822
823
824
827
828
829
830
831
832
833QSize QWaylandXdgToplevel::minSize()
const
835 Q_D(
const QWaylandXdgToplevel);
840
841
842
843
844QList<QWaylandXdgToplevel::State> QWaylandXdgToplevel::states()
const
846 Q_D(
const QWaylandXdgToplevel);
847 return d->m_lastAckedConfigure.states;
851
852
853
854
857
858
859
860
861bool QWaylandXdgToplevel::maximized()
const
863 Q_D(
const QWaylandXdgToplevel);
864 return d->m_lastAckedConfigure.states.contains(QWaylandXdgToplevel::State::MaximizedState);
868
869
870
871
874
875
876
877
878bool QWaylandXdgToplevel::fullscreen()
const
880 Q_D(
const QWaylandXdgToplevel);
881 return d->m_lastAckedConfigure.states.contains(QWaylandXdgToplevel::State::FullscreenState);
885
886
887
888
891
892
893
894
895bool QWaylandXdgToplevel::resizing()
const
897 Q_D(
const QWaylandXdgToplevel);
898 return d->m_lastAckedConfigure.states.contains(QWaylandXdgToplevel::State::ResizingState);
902
903
904
905
908
909
910
911
912bool QWaylandXdgToplevel::activated()
const
914 Q_D(
const QWaylandXdgToplevel);
915 return d->m_lastAckedConfigure.states.contains(QWaylandXdgToplevel::State::ActivatedState);
919
920
921
922
923
926
927
928
929
930
931bool QWaylandXdgToplevel::isModal()
const
933 Q_D(
const QWaylandXdgToplevel);
937void QWaylandXdgToplevel::setModal(
bool newModal)
939 Q_D(QWaylandXdgToplevel);
940 if (d->m_modal == newModal)
942 d->m_modal = newModal;
947
948
949
950
951
952
953
956
957
958
959
960
961
962
963
964
965
968
969
970
971
972
973
974QWaylandXdgToplevel::DecorationMode QWaylandXdgToplevel::decorationMode()
const
976 Q_D(
const QWaylandXdgToplevel);
977 return d->m_decoration ? d->m_decoration->configuredMode() : DecorationMode::ClientSideDecoration;
981
982
983
984
985
988
989
990
991QSize QWaylandXdgToplevel::sizeForResize(
const QSizeF &size,
const QPointF &delta, Qt::Edges edges)
const
993 qreal width = size.width();
994 qreal height = size.height();
995 if (edges & Qt::LeftEdge)
997 else if (edges & Qt::RightEdge)
1000 if (edges & Qt::TopEdge)
1001 height -= delta.y();
1002 else if (edges & Qt::BottomEdge)
1003 height += delta.y();
1005 QSize newSize = QSize(width, height)
1006 .expandedTo(minSize())
1007 .expandedTo({1, 1});
1009 if (maxSize().isValid())
1010 newSize = newSize.boundedTo(maxSize());
1016
1017
1018
1019
1020uint QWaylandXdgToplevel::sendConfigure(
const QSize &size,
const QList<QWaylandXdgToplevel::State> &states)
1022 if (!size.isValid()) {
1023 qWarning() <<
"Can't configure xdg_toplevel with an invalid size" << size;
1026 Q_D(QWaylandXdgToplevel);
1027 auto statesBytes = QByteArray::fromRawData(
reinterpret_cast<
const char *>(states.data()),
1028 states.size() *
static_cast<
int>(
sizeof(State)));
1029 uint32_t serial = d->m_xdgSurface->surface()->compositor()->nextSerial();
1030 d->m_pendingConfigures.append(QWaylandXdgToplevelPrivate::ConfigureEvent{states, size, serial});
1031 d->send_configure(size.width(), size.height(), statesBytes);
1032 QWaylandXdgSurfacePrivate::get(d->m_xdgSurface)->send_configure(serial);
1037
1038
1039
1040
1041
1042
1043uint QWaylandXdgToplevel::sendConfigure(
const QSize &size,
const QList<
int> &states)
1046 for (
auto state : states)
1048 return sendConfigure(size, s);
1052
1053
1054
1055
1058
1059
1060void QWaylandXdgToplevel::sendClose()
1062 Q_D(QWaylandXdgToplevel);
1067
1068
1069
1070
1071
1072
1073
1076
1077
1078
1079
1080
1081uint QWaylandXdgToplevel::sendMaximized(
const QSize &size)
1083 Q_D(QWaylandXdgToplevel);
1084 QWaylandXdgToplevelPrivate::ConfigureEvent conf = d->lastSentConfigure();
1086 if (!conf.states.contains(QWaylandXdgToplevel::State::MaximizedState))
1087 conf.states.append(QWaylandXdgToplevel::State::MaximizedState);
1088 conf.states.removeOne(QWaylandXdgToplevel::State::FullscreenState);
1089 conf.states.removeOne(QWaylandXdgToplevel::State::ResizingState);
1091 return sendConfigure(size, conf.states);
1095
1096
1097
1098
1099
1100
1101
1102
1105
1106
1107
1108
1109
1110
1111uint QWaylandXdgToplevel::sendUnmaximized(
const QSize &size)
1113 Q_D(QWaylandXdgToplevel);
1114 QWaylandXdgToplevelPrivate::ConfigureEvent conf = d->lastSentConfigure();
1116 conf.states.removeOne(QWaylandXdgToplevel::State::MaximizedState);
1117 conf.states.removeOne(QWaylandXdgToplevel::State::FullscreenState);
1118 conf.states.removeOne(QWaylandXdgToplevel::State::ResizingState);
1120 return sendConfigure(size, conf.states);
1125
1126
1127
1128
1129
1130
1131
1132
1133
1136
1137
1138
1139
1140
1141
1142
1143uint QWaylandXdgToplevel::sendFullscreen(
const QSize &size)
1145 Q_D(QWaylandXdgToplevel);
1146 QWaylandXdgToplevelPrivate::ConfigureEvent conf = d->lastSentConfigure();
1148 if (!conf.states.contains(QWaylandXdgToplevel::State::FullscreenState))
1149 conf.states.append(QWaylandXdgToplevel::State::FullscreenState);
1150 conf.states.removeOne(QWaylandXdgToplevel::State::MaximizedState);
1151 conf.states.removeOne(QWaylandXdgToplevel::State::ResizingState);
1153 return sendConfigure(size, conf.states);
1157
1158
1159
1160
1161
1162
1163
1166
1167
1168
1169
1170
1171uint QWaylandXdgToplevel::sendResizing(
const QSize &maxSize)
1173 Q_D(QWaylandXdgToplevel);
1174 QWaylandXdgToplevelPrivate::ConfigureEvent conf = d->lastSentConfigure();
1176 if (!conf.states.contains(QWaylandXdgToplevel::State::ResizingState))
1177 conf.states.append(QWaylandXdgToplevel::State::ResizingState);
1178 conf.states.removeOne(QWaylandXdgToplevel::State::MaximizedState);
1179 conf.states.removeOne(QWaylandXdgToplevel::State::FullscreenState);
1181 return sendConfigure(maxSize, conf.states);
1185
1186
1187QWaylandSurfaceRole *QWaylandXdgToplevel::role()
1189 return &QWaylandXdgToplevelPrivate::s_role;
1193
1194
1195QWaylandXdgToplevel *QWaylandXdgToplevel::fromResource(wl_resource *resource)
1197 if (
auto p = QtWayland::fromResource<QWaylandXdgToplevelPrivate *>(resource))
1203
1204
1205
1206
1207
1208
1209
1210
1213
1214
1215
1216
1217
1218
1219
1220
1223
1224
1225
1226
1227
1228
1229
1230
1233
1234
1235
1236
1237
1238
1239
1240
1243
1244
1245
1246
1247
1248
1249
1250
1253
1254
1255
1256
1257
1258
1259
1260
1263
1264
1265
1266
1267
1268
1271
1272
1273
1274
1275
1276
1278QList<
int> QWaylandXdgToplevel::statesAsInts()
const
1281 const auto s = states();
1282 list.reserve(s.size());
1283 for (
auto state : s) {
1284 list <<
static_cast<
int>(state);
1289QWaylandSurfaceRole QWaylandXdgToplevelPrivate::s_role(
"xdg_toplevel");
1291QWaylandXdgToplevelPrivate::QWaylandXdgToplevelPrivate(QWaylandXdgSurface *xdgSurface,
const QWaylandResource &resource)
1292 : m_xdgSurface(xdgSurface)
1294 init(resource.resource());
1297void QWaylandXdgToplevelPrivate::handleAckConfigure(uint serial)
1299 Q_Q(QWaylandXdgToplevel);
1300 ConfigureEvent config;
1302 if (m_pendingConfigures.empty()) {
1303 qWarning(
"Toplevel received an unexpected ack_configure!");
1308 config = m_pendingConfigures.takeFirst();
1310 if (config.serial == serial)
1314 QList<uint> changedStates;
1315 std::set_symmetric_difference(
1316 m_lastAckedConfigure.states.begin(), m_lastAckedConfigure.states.end(),
1317 config.states.begin(), config.states.end(),
1318 std::back_inserter(changedStates));
1320 m_lastAckedConfigure = config;
1322 for (uint state : changedStates) {
1324 case state_maximized:
1325 emit q->maximizedChanged();
1327 case state_fullscreen:
1328 emit q->fullscreenChanged();
1330 case state_resizing:
1331 emit q->resizingChanged();
1333 case state_activated:
1334 emit q->activatedChanged();
1339 if (!changedStates.empty())
1340 emit q->statesChanged();
1343void QWaylandXdgToplevelPrivate::handleFocusLost()
1345 Q_Q(QWaylandXdgToplevel);
1346 QWaylandXdgToplevelPrivate::ConfigureEvent current = lastSentConfigure();
1347 current.states.removeOne(QWaylandXdgToplevel::State::ActivatedState);
1348 q->sendConfigure(current.size, current.states);
1351void QWaylandXdgToplevelPrivate::handleFocusReceived()
1353 Q_Q(QWaylandXdgToplevel);
1354 QWaylandXdgToplevelPrivate::ConfigureEvent current = lastSentConfigure();
1355 if (!current.states.contains(QWaylandXdgToplevel::State::ActivatedState)) {
1356 current.states.push_back(QWaylandXdgToplevel::State::ActivatedState);
1357 q->sendConfigure(current.size, current.states);
1361Qt::Edges QWaylandXdgToplevelPrivate::convertToEdges(resize_edge edge)
1363 return Qt::Edges(((edge & 0b1100) >> 1) | ((edge & 0b0010) << 2) | (edge & 0b0001));
1366void QWaylandXdgToplevelPrivate::xdg_toplevel_destroy_resource(QtWaylandServer::xdg_toplevel::Resource *resource)
1369 Q_Q(QWaylandXdgToplevel);
1373void QWaylandXdgToplevelPrivate::xdg_toplevel_destroy(QtWaylandServer::xdg_toplevel::Resource *resource)
1375 if (Q_UNLIKELY(m_decoration))
1376 qWarning() <<
"Client error: xdg_toplevel destroyed before its decoration object";
1378 wl_resource_destroy(resource->handle);
1382void QWaylandXdgToplevelPrivate::xdg_toplevel_set_parent(QtWaylandServer::xdg_toplevel::Resource *resource, wl_resource *parent)
1385 QWaylandXdgToplevel *parentToplevel = QWaylandXdgToplevel::fromResource(parent);
1387 Q_Q(QWaylandXdgToplevel);
1389 if (m_parentToplevel != parentToplevel) {
1390 m_parentToplevel = parentToplevel;
1391 emit q->parentToplevelChanged();
1394 if (m_parentToplevel && m_xdgSurface->windowType() != Qt::WindowType::SubWindow) {
1396 QWaylandXdgSurfacePrivate::get(m_xdgSurface)->setWindowType(Qt::WindowType::SubWindow);
1397 }
else if (!m_parentToplevel && m_xdgSurface->windowType() != Qt::WindowType::Window) {
1399 QWaylandXdgSurfacePrivate::get(m_xdgSurface)->setWindowType(Qt::WindowType::Window);
1403void QWaylandXdgToplevelPrivate::xdg_toplevel_set_title(QtWaylandServer::xdg_toplevel::Resource *resource,
const QString &title)
1406 if (title == m_title)
1408 Q_Q(QWaylandXdgToplevel);
1410 emit q->titleChanged();
1413void QWaylandXdgToplevelPrivate::xdg_toplevel_set_app_id(QtWaylandServer::xdg_toplevel::Resource *resource,
const QString &app_id)
1416 if (app_id == m_appId)
1418 Q_Q(QWaylandXdgToplevel);
1420 emit q->appIdChanged();
1423void QWaylandXdgToplevelPrivate::xdg_toplevel_show_window_menu(QtWaylandServer::xdg_toplevel::Resource *resource, wl_resource *seatResource, uint32_t serial, int32_t x, int32_t y)
1427 QPoint position(x, y);
1428 auto seat = QWaylandSeat::fromSeatResource(seatResource);
1429 Q_Q(QWaylandXdgToplevel);
1430 emit q->showWindowMenu(seat, position);
1433void QWaylandXdgToplevelPrivate::xdg_toplevel_move(Resource *resource, wl_resource *seatResource, uint32_t serial)
1437 Q_Q(QWaylandXdgToplevel);
1438 QWaylandSeat *seat = QWaylandSeat::fromSeatResource(seatResource);
1439 emit q->startMove(seat);
1442void QWaylandXdgToplevelPrivate::xdg_toplevel_resize(QtWaylandServer::xdg_toplevel::Resource *resource, wl_resource *seatResource, uint32_t serial, uint32_t edges)
1446 Q_Q(QWaylandXdgToplevel);
1447 QWaylandSeat *seat = QWaylandSeat::fromSeatResource(seatResource);
1448 emit q->startResize(seat, convertToEdges(resize_edge(edges)));
1451void QWaylandXdgToplevelPrivate::xdg_toplevel_set_max_size(QtWaylandServer::xdg_toplevel::Resource *resource, int32_t width, int32_t height)
1455 QSize maxSize(width, height);
1456 if (width == 0 && height == 0)
1459 if (m_maxSize == maxSize)
1462 if (width < 0 || height < 0) {
1464 qWarning() <<
"Received a xdg_toplevel.set_max_size request with a negative size";
1468 if (m_minSize.isValid() && maxSize.isValid() &&
1469 (maxSize.width() < m_minSize.width() || maxSize.height() < m_minSize.height())) {
1471 qWarning() <<
"Received a xdg_toplevel.set_max_size request with a size smaller than the minimium size";
1475 m_maxSize = maxSize;
1477 Q_Q(QWaylandXdgToplevel);
1478 emit q->maxSizeChanged();
1481void QWaylandXdgToplevelPrivate::xdg_toplevel_set_min_size(QtWaylandServer::xdg_toplevel::Resource *resource, int32_t width, int32_t height)
1485 QSize minSize(width, height);
1486 if (width == 0 && height == 0)
1489 if (m_minSize == minSize)
1492 if (width < 0 || height < 0) {
1494 qWarning() <<
"Received a xdg_toplevel.set_min_size request with a negative size";
1498 if (m_maxSize.isValid() && minSize.isValid() &&
1499 (minSize.width() > m_maxSize.width() || minSize.height() > m_maxSize.height())) {
1501 qWarning() <<
"Received a xdg_toplevel.set_min_size request with a size larger than the maximum size";
1505 m_minSize = minSize;
1507 Q_Q(QWaylandXdgToplevel);
1508 emit q->minSizeChanged();
1511void QWaylandXdgToplevelPrivate::xdg_toplevel_set_maximized(QtWaylandServer::xdg_toplevel::Resource *resource)
1514 Q_Q(QWaylandXdgToplevel);
1515 emit q->setMaximized();
1518void QWaylandXdgToplevelPrivate::xdg_toplevel_unset_maximized(QtWaylandServer::xdg_toplevel::Resource *resource)
1521 Q_Q(QWaylandXdgToplevel);
1522 emit q->unsetMaximized();
1525void QWaylandXdgToplevelPrivate::xdg_toplevel_set_fullscreen(QtWaylandServer::xdg_toplevel::Resource *resource, wl_resource *output_res)
1528 Q_Q(QWaylandXdgToplevel);
1529 QWaylandOutput *output = output_res ? QWaylandOutput::fromResource(output_res) :
nullptr;
1530 emit q->setFullscreen(output);
1533void QWaylandXdgToplevelPrivate::xdg_toplevel_unset_fullscreen(QtWaylandServer::xdg_toplevel::Resource *resource)
1536 Q_Q(QWaylandXdgToplevel);
1537 emit q->unsetFullscreen();
1540void QWaylandXdgToplevelPrivate::xdg_toplevel_set_minimized(QtWaylandServer::xdg_toplevel::Resource *resource)
1543 Q_Q(QWaylandXdgToplevel);
1544 emit q->setMinimized();
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1575
1576
1577QWaylandXdgPopup::QWaylandXdgPopup(QWaylandXdgSurface *xdgSurface, QWaylandXdgSurface *parentXdgSurface,
1578 QWaylandXdgPositioner *positioner, QWaylandResource &resource)
1579 : QObject(*
new QWaylandXdgPopupPrivate(xdgSurface, parentXdgSurface, positioner, resource))
1584
1585
1586
1587
1590
1591
1592
1593
1594QWaylandXdgSurface *QWaylandXdgPopup::xdgSurface()
const
1596 Q_D(
const QWaylandXdgPopup);
1597 return d->m_xdgSurface;
1601
1602
1603
1604
1607
1608
1609
1610
1611
1612QWaylandXdgSurface *QWaylandXdgPopup::parentXdgSurface()
const
1614 Q_D(
const QWaylandXdgPopup);
1615 return d->m_parentXdgSurface;
1619
1620
1621
1622
1623
1626
1627
1628
1629
1630
1631QRect QWaylandXdgPopup::configuredGeometry()
const
1633 Q_D(
const QWaylandXdgPopup);
1634 return d->m_geometry;
1638
1639
1640
1641
1642
1645
1646
1647
1648
1649
1650QRect QWaylandXdgPopup::anchorRect()
const
1652 Q_D(
const QWaylandXdgPopup);
1653 return d->m_positionerData.anchorRect;
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1671
1672
1673
1674
1675
1676
1677Qt::Edges QWaylandXdgPopup::anchorEdges()
const
1679 Q_D(
const QWaylandXdgPopup);
1680 return d->m_positionerData.anchorEdges;
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1697
1698
1699
1700
1701
1702Qt::Edges QWaylandXdgPopup::gravityEdges()
const
1704 Q_D(
const QWaylandXdgPopup);
1705 return d->m_positionerData.gravityEdges;
1709
1710
1711
1712
1713
1714
1715
1716
1719
1720
1721
1722
1723Qt::Orientations QWaylandXdgPopup::slideConstraints()
const
1725 Q_D(
const QWaylandXdgPopup);
1726 const uint flags = d->m_positionerData.constraintAdjustments;
1728 Qt::Orientations constraints = {};
1730 if (flags & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_X)
1731 constraints |= Qt::Horizontal;
1732 if (flags & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_Y)
1733 constraints |= Qt::Vertical;
1739
1740
1741
1742
1743
1744
1745
1746
1749
1750
1751
1752
1753Qt::Orientations QWaylandXdgPopup::flipConstraints()
const
1755 Q_D(
const QWaylandXdgPopup);
1756 const uint flags = d->m_positionerData.constraintAdjustments;
1758 Qt::Orientations constraints = {};
1760 if (flags & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_X)
1761 constraints |= Qt::Horizontal;
1762 if (flags & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_Y)
1763 constraints |= Qt::Vertical;
1769
1770
1771
1772
1773
1774
1775
1776
1779
1780
1781
1782
1783Qt::Orientations QWaylandXdgPopup::resizeConstraints()
const
1785 Q_D(
const QWaylandXdgPopup);
1786 const uint flags = d->m_positionerData.constraintAdjustments;
1788 Qt::Orientations constraints = {};
1790 if (flags & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_X)
1791 constraints |= Qt::Horizontal;
1792 if (flags & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_Y)
1793 constraints |= Qt::Vertical;
1799
1800
1801
1802
1803
1806
1807
1808
1809
1810
1811QPoint QWaylandXdgPopup::offset()
const
1813 Q_D(
const QWaylandXdgPopup);
1814 return d->m_positionerData.offset;
1818
1819
1820
1821
1824
1825
1826
1827
1828QSize QWaylandXdgPopup::positionerSize()
const
1830 Q_D(
const QWaylandXdgPopup);
1831 return d->m_positionerData.size;
1835
1836
1837
1838
1839
1842
1843
1844
1845
1846
1847QPoint QWaylandXdgPopup::unconstrainedPosition()
const
1849 Q_D(
const QWaylandXdgPopup);
1850 return d->m_positionerData.unconstrainedPosition();
1854
1855
1856
1857
1858
1859
1860
1863
1864
1865
1866
1867
1868
1869uint QWaylandXdgPopup::sendConfigure(
const QRect &geometry)
1871 Q_D(QWaylandXdgPopup);
1872 return d->sendConfigure(geometry);
1876
1877
1878
1879
1880
1881
1884
1885
1886
1887
1888
1889void QWaylandXdgPopup::sendPopupDone()
1891 Q_D(QWaylandXdgPopup);
1892 d->send_popup_done();
1896
1897
1898QWaylandSurfaceRole *QWaylandXdgPopup::role()
1900 return &QWaylandXdgPopupPrivate::s_role;
1903QWaylandXdgPopupPrivate::QWaylandXdgPopupPrivate(QWaylandXdgSurface *xdgSurface, QWaylandXdgSurface *parentXdgSurface,
1904 QWaylandXdgPositioner *positioner,
const QWaylandResource &resource)
1905 : m_xdgSurface(xdgSurface)
1906 , m_parentXdgSurface(parentXdgSurface)
1907 , m_positionerData(positioner->m_data)
1909 Q_ASSERT(m_positionerData.isComplete());
1910 init(resource.resource());
1912 QWaylandXdgSurfacePrivate::get(m_xdgSurface)->setWindowType(Qt::WindowType::Popup);
1915 sendConfigure(QRect(m_positionerData.unconstrainedPosition(), m_positionerData.size));
1918void QWaylandXdgPopupPrivate::handleAckConfigure(uint serial)
1920 Q_Q(QWaylandXdgPopup);
1921 ConfigureEvent config;
1923 if (m_pendingConfigures.empty()) {
1924 qWarning(
"Popup received an unexpected ack_configure!");
1929 config = m_pendingConfigures.takeFirst();
1931 if (config.serial == serial)
1935 if (m_geometry == config.geometry)
1938 m_geometry = config.geometry;
1939 emit q->configuredGeometryChanged();
1942uint QWaylandXdgPopupPrivate::sendConfigure(
const QRect &geometry)
1944 uint32_t serial = m_xdgSurface->surface()->compositor()->nextSerial();
1945 m_pendingConfigures.append(QWaylandXdgPopupPrivate::ConfigureEvent{geometry, serial});
1946 send_configure(geometry.x(), geometry.y(), geometry.width(), geometry.height());
1947 QWaylandXdgSurfacePrivate::get(m_xdgSurface)->send_configure(serial);
1951void QWaylandXdgPopupPrivate::xdg_popup_destroy(QtWaylandServer::xdg_popup::Resource *resource)
1954 qWarning() << Q_FUNC_INFO <<
"Not implemented";
1957void QWaylandXdgPopupPrivate::xdg_popup_grab(QtWaylandServer::xdg_popup::Resource *resource, wl_resource *seat, uint32_t serial)
1962 qWarning() << Q_FUNC_INFO <<
"Not implemented";
1967QWaylandSurfaceRole QWaylandXdgPopupPrivate::s_role(
"xdg_popup");
1969QWaylandXdgPositionerData::QWaylandXdgPositionerData()
1973bool QWaylandXdgPositionerData::isComplete()
const
1975 return size.width() > 0 && size.height() > 0 && anchorRect.size().width() > 0 && anchorRect.size().height() > 0;
1978QPoint QWaylandXdgPositionerData::anchorPoint()
const
1981 if (anchorEdges & Qt::TopEdge)
1982 yPosition = anchorRect.top();
1983 else if (anchorEdges & Qt::BottomEdge)
1984 yPosition = anchorRect.bottom() + 1;
1986 yPosition = anchorRect.top() + anchorRect.height() / 2;
1989 if (anchorEdges & Qt::LeftEdge)
1990 xPosition = anchorRect.left();
1991 else if (anchorEdges & Qt::RightEdge)
1992 xPosition = anchorRect.right() + 1;
1994 xPosition = anchorRect.left() + anchorRect.width() / 2;
1996 return QPoint(xPosition, yPosition);
1999QPoint QWaylandXdgPositionerData::unconstrainedPosition()
const
2001 int gravityOffsetY = 0;
2002 if (gravityEdges & Qt::TopEdge)
2003 gravityOffsetY = -size.height();
2004 else if (!(gravityEdges & Qt::BottomEdge))
2005 gravityOffsetY = -size.height() / 2;
2007 int gravityOffsetX = 0;
2008 if (gravityEdges & Qt::LeftEdge)
2009 gravityOffsetX = -size.width();
2010 else if (!(gravityEdges & Qt::RightEdge))
2011 gravityOffsetX = -size.width() / 2;
2013 QPoint gravityOffset(gravityOffsetX, gravityOffsetY);
2014 return anchorPoint() + gravityOffset + offset;
2017QWaylandXdgPositioner::QWaylandXdgPositioner(
const QWaylandResource &resource)
2019 init(resource.resource());
2022void QWaylandXdgPositioner::xdg_positioner_destroy_resource(QtWaylandServer::xdg_positioner::Resource *resource)
2028void QWaylandXdgPositioner::xdg_positioner_destroy(QtWaylandServer::xdg_positioner::Resource *resource)
2030 wl_resource_destroy(resource->handle);
2033void QWaylandXdgPositioner::xdg_positioner_set_size(QtWaylandServer::xdg_positioner::Resource *resource, int32_t width, int32_t height)
2035 if (width <= 0 || height <= 0) {
2036 wl_resource_post_error(resource->handle, XDG_POSITIONER_ERROR_INVALID_INPUT,
2037 "xdg_positioner.set_size requested with non-positive dimensions");
2041 QSize size(width, height);
2045void QWaylandXdgPositioner::xdg_positioner_set_anchor_rect(QtWaylandServer::xdg_positioner::Resource *resource, int32_t x, int32_t y, int32_t width, int32_t height)
2047 if (width <= 0 || height <= 0) {
2048 wl_resource_post_error(resource->handle, XDG_POSITIONER_ERROR_INVALID_INPUT,
2049 "xdg_positioner.set_anchor_rect requested with non-positive dimensions");
2053 QRect anchorRect(x, y, width, height);
2054 m_data.anchorRect = anchorRect;
2057void QWaylandXdgPositioner::xdg_positioner_set_anchor(QtWaylandServer::xdg_positioner::Resource *resource, uint32_t anchor)
2059 Qt::Edges anchorEdges = convertToEdges(xdg_positioner::anchor(anchor));
2061 if ((anchorEdges & Qt::BottomEdge && anchorEdges & Qt::TopEdge) ||
2062 (anchorEdges & Qt::LeftEdge && anchorEdges & Qt::RightEdge)) {
2063 wl_resource_post_error(resource->handle, XDG_POSITIONER_ERROR_INVALID_INPUT,
2064 "xdg_positioner.set_anchor requested with parallel edges");
2068 m_data.anchorEdges = anchorEdges;
2071void QWaylandXdgPositioner::xdg_positioner_set_gravity(QtWaylandServer::xdg_positioner::Resource *resource, uint32_t gravity)
2073 Qt::Edges gravityEdges = convertToEdges(xdg_positioner::gravity(gravity));
2075 if ((gravityEdges & Qt::BottomEdge && gravityEdges & Qt::TopEdge) ||
2076 (gravityEdges & Qt::LeftEdge && gravityEdges & Qt::RightEdge)) {
2077 wl_resource_post_error(resource->handle, XDG_POSITIONER_ERROR_INVALID_INPUT,
2078 "xdg_positioner.set_gravity requested with parallel edges");
2082 m_data.gravityEdges = gravityEdges;
2085void QWaylandXdgPositioner::xdg_positioner_set_constraint_adjustment(QtWaylandServer::xdg_positioner::Resource *resource, uint32_t constraint_adjustment)
2088 m_data.constraintAdjustments = constraint_adjustment;
2091void QWaylandXdgPositioner::xdg_positioner_set_offset(QtWaylandServer::xdg_positioner::Resource *resource, int32_t x, int32_t y)
2094 m_data.offset = QPoint(x, y);
2097QWaylandXdgPositioner *QWaylandXdgPositioner::fromResource(wl_resource *resource)
2099 return QtWayland::fromResource<QWaylandXdgPositioner *>(resource);
2102Qt::Edges QWaylandXdgPositioner::convertToEdges(anchor anchor)
2110 return Qt::BottomEdge;
2112 return Qt::LeftEdge;
2114 return Qt::RightEdge;
2115 case anchor_top_left:
2116 return Qt::TopEdge | Qt::LeftEdge;
2117 case anchor_bottom_left:
2118 return Qt::BottomEdge | Qt::LeftEdge;
2119 case anchor_top_right:
2120 return Qt::TopEdge | Qt::RightEdge;
2121 case anchor_bottom_right:
2122 return Qt::BottomEdge | Qt::RightEdge;
2124 qWarning() <<
"Unknown Wayland xdg edge" << anchor;
2129Qt::Edges QWaylandXdgPositioner::convertToEdges(QWaylandXdgPositioner::gravity gravity)
2131 return convertToEdges(anchor(gravity));
2137#include "moc_qwaylandxdgshell.cpp"