8#if QT_CONFIG(wayland_compositor_quick)
9#include "qwaylandxdgshellintegration_p.h"
11#include <QtWaylandCompositor/private/qwaylandutils_p.h>
15#include <QtWaylandCompositor/QWaylandCompositor>
16#include <QtWaylandCompositor/QWaylandSeat>
17#include <QtWaylandCompositor/QWaylandSurface>
18#include <QtWaylandCompositor/QWaylandSurfaceRole>
19#include <QtWaylandCompositor/QWaylandResource>
21#include <QtCore/QObject>
27QWaylandXdgShellPrivate::QWaylandXdgShellPrivate()
31void QWaylandXdgShellPrivate::ping(QtWaylandServer::xdg_wm_base::Resource *resource, uint32_t serial)
33 m_pings.insert(serial);
34 send_ping(resource->handle, serial);
37void QWaylandXdgShellPrivate::registerXdgSurface(QWaylandXdgSurface *xdgSurface)
39 m_xdgSurfaces.insert(xdgSurface->surface()->client()->client(), xdgSurface);
42void QWaylandXdgShellPrivate::unregisterXdgSurface(QWaylandXdgSurface *xdgSurface)
44 auto xdgSurfacePrivate = QWaylandXdgSurfacePrivate::get(xdgSurface);
45 if (!m_xdgSurfaces.remove(xdgSurfacePrivate->resource()->client(), xdgSurface))
46 qWarning(
"%s Unexpected state. Can't find registered xdg surface\n", Q_FUNC_INFO);
49QWaylandXdgSurface *QWaylandXdgShellPrivate::xdgSurfaceFromSurface(QWaylandSurface *surface)
51 for (QWaylandXdgSurface *xdgSurface : std::as_const(m_xdgSurfaces)) {
52 if (surface == xdgSurface->surface())
58void QWaylandXdgShellPrivate::xdg_wm_base_destroy(Resource *resource)
60 if (!m_xdgSurfaces.values(resource->client()).empty())
61 wl_resource_post_error(resource->handle, XDG_WM_BASE_ERROR_DEFUNCT_SURFACES,
62 "xdg_shell was destroyed before children");
64 wl_resource_destroy(resource->handle);
67void QWaylandXdgShellPrivate::xdg_wm_base_create_positioner(QtWaylandServer::xdg_wm_base::Resource *resource, uint32_t id)
69 QWaylandResource positionerResource(wl_resource_create(resource->client(), &xdg_positioner_interface,
70 wl_resource_get_version(resource->handle), id));
72 new QWaylandXdgPositioner(positionerResource);
75void QWaylandXdgShellPrivate::xdg_wm_base_get_xdg_surface(Resource *resource, uint32_t id, wl_resource *surfaceResource)
77 Q_Q(QWaylandXdgShell);
78 QWaylandSurface *surface = QWaylandSurface::fromResource(surfaceResource);
80 if (surface->hasContent()) {
82 qWarning() <<
"get_xdg_surface requested on a xdg_surface with content";
85 QWaylandResource xdgSurfaceResource(wl_resource_create(resource->client(), &xdg_surface_interface,
86 wl_resource_get_version(resource->handle), id));
88 QWaylandXdgSurface *xdgSurface =
new QWaylandXdgSurface(q, surface, xdgSurfaceResource);
90 registerXdgSurface(xdgSurface);
91 emit q->xdgSurfaceCreated(xdgSurface);
94void QWaylandXdgShellPrivate::xdg_wm_base_pong(Resource *resource, uint32_t serial)
97 Q_Q(QWaylandXdgShell);
98 if (m_pings.remove(serial))
101 qWarning(
"Received an unexpected pong!");
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
130
133
134
135
136
137
138
139
140
141
142
143
146
147
148QWaylandXdgShell::QWaylandXdgShell()
149 : QWaylandShellTemplate<QWaylandXdgShell>(*
new QWaylandXdgShellPrivate())
154
155
156QWaylandXdgShell::QWaylandXdgShell(QWaylandCompositor *compositor)
157 : QWaylandShellTemplate<QWaylandXdgShell>(compositor, *
new QWaylandXdgShellPrivate())
162
163
164void QWaylandXdgShell::initialize()
166 Q_D(QWaylandXdgShell);
167 QWaylandShellTemplate::initialize();
168 QWaylandCompositor *compositor =
static_cast<QWaylandCompositor *>(extensionContainer());
170 qWarning() <<
"Failed to find QWaylandCompositor when initializing QWaylandXdgShell";
173 d->init(compositor->display(), 1);
175 handleSeatChanged(compositor->defaultSeat(),
nullptr);
177 connect(compositor, &QWaylandCompositor::defaultSeatChanged,
178 this, &QWaylandXdgShell::handleSeatChanged);
181 QObject *dialogExtension =
new QWaylandXdgDialogV1Global(compositor);
182 dialogExtension->setParent(
this);
186
187
188const struct wl_interface *QWaylandXdgShell::interface()
190 return QWaylandXdgShellPrivate::interface();
193QByteArray QWaylandXdgShell::interfaceName()
195 return QWaylandXdgShellPrivate::interfaceName();
199
200
201
202
203
206
207
208
209uint QWaylandXdgShell::ping(QWaylandClient *client)
211 Q_D(QWaylandXdgShell);
213 QWaylandCompositor *compositor =
static_cast<QWaylandCompositor *>(extensionContainer());
214 Q_ASSERT(compositor);
216 uint32_t serial = compositor->nextSerial();
218 QWaylandXdgShellPrivate::Resource *clientResource = d->resourceMap().value(client->client(),
nullptr);
219 Q_ASSERT(clientResource);
221 d->ping(clientResource, serial);
225void QWaylandXdgShell::handleSeatChanged(QWaylandSeat *newSeat, QWaylandSeat *oldSeat)
227 if (oldSeat !=
nullptr) {
228 disconnect(oldSeat, &QWaylandSeat::keyboardFocusChanged,
229 this, &QWaylandXdgShell::handleFocusChanged);
232 if (newSeat !=
nullptr) {
233 connect(newSeat, &QWaylandSeat::keyboardFocusChanged,
234 this, &QWaylandXdgShell::handleFocusChanged);
238void QWaylandXdgShell::handleFocusChanged(QWaylandSurface *newSurface, QWaylandSurface *oldSurface)
240 Q_D(QWaylandXdgShell);
242 QWaylandXdgSurface *newXdgSurface = d->xdgSurfaceFromSurface(newSurface);
243 QWaylandXdgSurface *oldXdgSurface = d->xdgSurfaceFromSurface(oldSurface);
246 QWaylandXdgSurfacePrivate::get(newXdgSurface)->handleFocusReceived();
249 QWaylandXdgSurfacePrivate::get(oldXdgSurface)->handleFocusLost();
252QWaylandXdgSurfacePrivate::QWaylandXdgSurfacePrivate()
256void QWaylandXdgSurfacePrivate::setWindowType(Qt::WindowType windowType)
258 if (m_windowType == windowType)
261 m_windowType = windowType;
263 Q_Q(QWaylandXdgSurface);
264 emit q->windowTypeChanged();
267void QWaylandXdgSurfacePrivate::handleFocusLost()
270 QWaylandXdgToplevelPrivate::get(m_toplevel)->handleFocusLost();
273void QWaylandXdgSurfacePrivate::handleFocusReceived()
276 QWaylandXdgToplevelPrivate::get(m_toplevel)->handleFocusReceived();
279QRect QWaylandXdgSurfacePrivate::calculateFallbackWindowGeometry()
const
283 return QRect(QPoint(), m_surface->destinationSize());
286void QWaylandXdgSurfacePrivate::updateFallbackWindowGeometry()
288 Q_Q(QWaylandXdgSurface);
289 if (!m_unsetWindowGeometry)
292 const QRect unsetGeometry = calculateFallbackWindowGeometry();
293 if (unsetGeometry == m_windowGeometry)
296 m_windowGeometry = unsetGeometry;
297 emit q->windowGeometryChanged();
300void QWaylandXdgSurfacePrivate::xdg_surface_destroy_resource(QtWaylandServer::xdg_surface::Resource *resource)
303 Q_Q(QWaylandXdgSurface);
304 QWaylandXdgShellPrivate::get(m_xdgShell)->unregisterXdgSurface(q);
308void QWaylandXdgSurfacePrivate::xdg_surface_destroy(QtWaylandServer::xdg_surface::Resource *resource)
310 wl_resource_destroy(resource->handle);
313void QWaylandXdgSurfacePrivate::xdg_surface_get_toplevel(QtWaylandServer::xdg_surface::Resource *resource, uint32_t id)
315 Q_Q(QWaylandXdgSurface);
317 if (m_toplevel || m_popup) {
318 wl_resource_post_error(resource->handle, XDG_SURFACE_ERROR_ALREADY_CONSTRUCTED,
319 "xdg_surface already has a role object");
323 if (!m_surface->setRole(QWaylandXdgToplevel::role(), resource->handle, XDG_WM_BASE_ERROR_ROLE))
326 QWaylandResource topLevelResource(wl_resource_create(resource->client(), &xdg_toplevel_interface,
327 wl_resource_get_version(resource->handle), id));
329 m_toplevel =
new QWaylandXdgToplevel(q, topLevelResource);
330 emit q->toplevelCreated();
331 emit m_xdgShell->toplevelCreated(m_toplevel, q);
332 q->connect(m_toplevel, &QWaylandXdgToplevel::modalChanged, q, [q,
this](){
333 q->setModal(m_toplevel->isModal());
337void QWaylandXdgSurfacePrivate::xdg_surface_get_popup(QtWaylandServer::xdg_surface::Resource *resource, uint32_t id, wl_resource *parentResource, wl_resource *positionerResource)
339 Q_Q(QWaylandXdgSurface);
341 if (m_toplevel || m_popup) {
342 wl_resource_post_error(resource->handle, XDG_SURFACE_ERROR_ALREADY_CONSTRUCTED,
343 "xdg_surface already has a role object");
347 QWaylandXdgSurface *parent = QWaylandXdgSurface::fromResource(parentResource);
349 wl_resource_post_error(resource->handle, XDG_WM_BASE_ERROR_INVALID_POPUP_PARENT,
350 "xdg_surface.get_popup with invalid popup parent");
354 QWaylandXdgPositioner *positioner = QWaylandXdgPositioner::fromResource(positionerResource);
356 wl_resource_post_error(resource->handle, XDG_WM_BASE_ERROR_INVALID_POSITIONER,
357 "xdg_surface.get_popup without positioner");
361 if (!positioner->m_data.isComplete()) {
362 QWaylandXdgPositionerData p = positioner->m_data;
363 wl_resource_post_error(resource->handle, XDG_WM_BASE_ERROR_INVALID_POSITIONER,
364 "xdg_surface.get_popup with invalid positioner (size: %dx%d, anchorRect: %dx%d)",
365 p.size.width(), p.size.height(), p.anchorRect.width(), p.anchorRect.height());
369 QRect anchorBounds(QPoint(0, 0), parent->windowGeometry().size());
370 if (!anchorBounds.contains(positioner->m_data.anchorRect)) {
376 qCWarning(qLcWaylandCompositor) <<
"Ignoring client protocol error: xdg_positioner anchor"
377 <<
"rect extends beyond its parent's window geometry";
380 if (!m_surface->setRole(QWaylandXdgPopup::role(), resource->handle, XDG_WM_BASE_ERROR_ROLE))
383 QWaylandResource popupResource(wl_resource_create(resource->client(), &xdg_popup_interface,
384 wl_resource_get_version(resource->handle), id));
386 m_popup =
new QWaylandXdgPopup(q, parent, positioner, popupResource);
387 emit q->popupCreated();
388 emit m_xdgShell->popupCreated(m_popup, q);
391void QWaylandXdgSurfacePrivate::xdg_surface_ack_configure(QtWaylandServer::xdg_surface::Resource *resource, uint32_t serial)
394 QWaylandXdgToplevelPrivate::get(m_toplevel)->handleAckConfigure(serial);
395 }
else if (m_popup) {
396 QWaylandXdgPopupPrivate::get(m_popup)->handleAckConfigure(serial);
398 wl_resource_post_error(resource->handle, XDG_SURFACE_ERROR_NOT_CONSTRUCTED,
399 "ack_configure requested on an unconstructed xdg_surface");
403void QWaylandXdgSurfacePrivate::xdg_surface_set_window_geometry(QtWaylandServer::xdg_surface::Resource *resource, int32_t x, int32_t y, int32_t width, int32_t height)
405 Q_Q(QWaylandXdgSurface);
407 if (!q->surface()->role()) {
408 wl_resource_post_error(resource->handle, XDG_SURFACE_ERROR_NOT_CONSTRUCTED,
409 "set_window_geometry requested on an unconstructed xdg_surface");
413 if (width <= 0 || height <= 0) {
417 qWarning() <<
"Invalid (non-positive) dimensions received in set_window_geometry";
421 m_unsetWindowGeometry =
false;
423 QRect geometry(x, y, width, height);
425 if (m_windowGeometry == geometry)
428 m_windowGeometry = geometry;
429 emit q->windowGeometryChanged();
433
434
435
436
437
438
439
440
441
442
443
444
445
448
449
450
451
452
453
454
455
456
457
458
459
462
463
464QWaylandXdgSurface::QWaylandXdgSurface()
465 : QWaylandShellSurfaceTemplate<QWaylandXdgSurface>(*
new QWaylandXdgSurfacePrivate)
470
471
472
473QWaylandXdgSurface::QWaylandXdgSurface(QWaylandXdgShell *xdgShell, QWaylandSurface *surface,
const QWaylandResource &res)
474 : QWaylandShellSurfaceTemplate<QWaylandXdgSurface>(*
new QWaylandXdgSurfacePrivate)
476 initialize(xdgShell, surface, res);
480
481
482
483
484
487
488
489
490void QWaylandXdgSurface::initialize(QWaylandXdgShell *xdgShell, QWaylandSurface *surface,
const QWaylandResource &resource)
492 Q_D(QWaylandXdgSurface);
493 d->m_xdgShell = xdgShell;
494 d->m_surface = surface;
495 d->init(resource.resource());
496 setExtensionContainer(surface);
497 d->m_windowGeometry = d->calculateFallbackWindowGeometry();
498 connect(surface, &QWaylandSurface::destinationSizeChanged,
this, &QWaylandXdgSurface::handleSurfaceSizeChanged);
499 connect(surface, &QWaylandSurface::bufferScaleChanged,
this, &QWaylandXdgSurface::handleBufferScaleChanged);
501 emit surfaceChanged();
502 QWaylandCompositorExtension::initialize();
506
507
508
509
510Qt::WindowType QWaylandXdgSurface::windowType()
const
512 Q_D(
const QWaylandXdgSurface);
513 return d->m_windowType;
517
518
519
520
521
522
523
524
527
528
529
530
531
532
533
534
535QRect QWaylandXdgSurface::windowGeometry()
const
537 Q_D(
const QWaylandXdgSurface);
538 return d->m_windowGeometry;
542
543
544void QWaylandXdgSurface::initialize()
546 QWaylandCompositorExtension::initialize();
549void QWaylandXdgSurface::handleSurfaceSizeChanged()
551 Q_D(QWaylandXdgSurface);
552 d->updateFallbackWindowGeometry();
555void QWaylandXdgSurface::handleBufferScaleChanged()
557 Q_D(QWaylandXdgSurface);
558 d->updateFallbackWindowGeometry();
562
563
564
565
568
569
570
571
572QWaylandXdgShell *QWaylandXdgSurface::shell()
const
574 Q_D(
const QWaylandXdgSurface);
575 return d->m_xdgShell;
579
580
581
582
585
586
587
588
589QWaylandSurface *QWaylandXdgSurface::surface()
const
591 Q_D(
const QWaylandXdgSurface);
596
597
598
599
600
601
602
605
606
607
608
609
610
611
612QWaylandXdgToplevel *QWaylandXdgSurface::toplevel()
const
614 Q_D(
const QWaylandXdgSurface);
615 return d->m_toplevel;
619
620
621
622
623
624
625
628
629
630
631
632
633
634
635QWaylandXdgPopup *QWaylandXdgSurface::popup()
const
637 Q_D(
const QWaylandXdgSurface);
642
643
644const wl_interface *QWaylandXdgSurface::interface()
646 return QWaylandXdgSurfacePrivate::interface();
650
651
652QByteArray QWaylandXdgSurface::interfaceName()
654 return QWaylandXdgSurfacePrivate::interfaceName();
658
659
660QWaylandXdgSurface *QWaylandXdgSurface::fromResource(wl_resource *resource)
662 if (
auto p = QtWayland::fromResource<QWaylandXdgSurfacePrivate *>(resource))
667#if QT_CONFIG(wayland_compositor_quick)
668QWaylandQuickShellIntegration *QWaylandXdgSurface::createIntegration(QWaylandQuickShellSurfaceItem *item)
670 Q_D(
const QWaylandXdgSurface);
673 return new QtWayland::XdgToplevelIntegration(item);
676 return new QtWayland::XdgPopupIntegration(item);
683
684
685
686
687
688
689
690
691
692
693
694
697
698
699
700
701
702
703
704
705
706
707
710
711
712QWaylandXdgToplevel::QWaylandXdgToplevel(QWaylandXdgSurface *xdgSurface, QWaylandResource &resource)
713 : QObject(*
new QWaylandXdgToplevelPrivate(xdgSurface, resource))
715 QList<QWaylandXdgToplevel::State> states;
716 sendConfigure({0, 0}, states);
719QWaylandXdgToplevel::~QWaylandXdgToplevel()
721 Q_D(QWaylandXdgToplevel);
724 if (Q_UNLIKELY(d->m_decoration))
725 wl_resource_destroy(d->m_decoration->resource()->handle);
726 Q_ASSERT(!d->m_decoration);
730
731
732
733
736
737
738
739
740QWaylandXdgSurface *QWaylandXdgToplevel::xdgSurface()
const
742 Q_D(
const QWaylandXdgToplevel);
743 return d->m_xdgSurface;
747
748
749
750
753
754
755
756
757
758QWaylandXdgToplevel *QWaylandXdgToplevel::parentToplevel()
const
760 Q_D(
const QWaylandXdgToplevel);
761 return d->m_parentToplevel;
765
766
767
768
771
772
773
774
775QString QWaylandXdgToplevel::title()
const
777 Q_D(
const QWaylandXdgToplevel);
782
783
784
785
786
789
790
791
792
793
794QString QWaylandXdgToplevel::appId()
const
796 Q_D(
const QWaylandXdgToplevel);
801
802
803
804
805
806
809
810
811
812
813
814
815QSize QWaylandXdgToplevel::maxSize()
const
817 Q_D(
const QWaylandXdgToplevel);
822
823
824
825
826
827
830
831
832
833
834
835
836QSize QWaylandXdgToplevel::minSize()
const
838 Q_D(
const QWaylandXdgToplevel);
843
844
845
846
847QList<QWaylandXdgToplevel::State> QWaylandXdgToplevel::states()
const
849 Q_D(
const QWaylandXdgToplevel);
850 return d->m_lastAckedConfigure.states;
854
855
856
857
860
861
862
863
864bool QWaylandXdgToplevel::maximized()
const
866 Q_D(
const QWaylandXdgToplevel);
867 return d->m_lastAckedConfigure.states.contains(QWaylandXdgToplevel::State::MaximizedState);
871
872
873
874
877
878
879
880
881bool QWaylandXdgToplevel::fullscreen()
const
883 Q_D(
const QWaylandXdgToplevel);
884 return d->m_lastAckedConfigure.states.contains(QWaylandXdgToplevel::State::FullscreenState);
888
889
890
891
894
895
896
897
898bool QWaylandXdgToplevel::resizing()
const
900 Q_D(
const QWaylandXdgToplevel);
901 return d->m_lastAckedConfigure.states.contains(QWaylandXdgToplevel::State::ResizingState);
905
906
907
908
911
912
913
914
915bool QWaylandXdgToplevel::activated()
const
917 Q_D(
const QWaylandXdgToplevel);
918 return d->m_lastAckedConfigure.states.contains(QWaylandXdgToplevel::State::ActivatedState);
922
923
924
925
926
929
930
931
932
933
934bool QWaylandXdgToplevel::isModal()
const
936 Q_D(
const QWaylandXdgToplevel);
940void QWaylandXdgToplevel::setModal(
bool newModal)
942 Q_D(QWaylandXdgToplevel);
943 if (d->m_modal == newModal)
945 d->m_modal = newModal;
950
951
952
953
954
955
956
959
960
961
962
963
964
965
966
967
968
971
972
973
974
975
976
977QWaylandXdgToplevel::DecorationMode QWaylandXdgToplevel::decorationMode()
const
979 Q_D(
const QWaylandXdgToplevel);
980 return d->m_decoration ? d->m_decoration->configuredMode() : DecorationMode::ClientSideDecoration;
984
985
986
987
988
991
992
993
994QSize QWaylandXdgToplevel::sizeForResize(
const QSizeF &size,
const QPointF &delta, Qt::Edges edges)
const
996 qreal width = size.width();
997 qreal height = size.height();
998 if (edges & Qt::LeftEdge)
1000 else if (edges & Qt::RightEdge)
1003 if (edges & Qt::TopEdge)
1004 height -= delta.y();
1005 else if (edges & Qt::BottomEdge)
1006 height += delta.y();
1008 QSize newSize = QSize(width, height)
1009 .expandedTo(minSize())
1010 .expandedTo({1, 1});
1012 if (maxSize().isValid())
1013 newSize = newSize.boundedTo(maxSize());
1019
1020
1021
1022
1023uint QWaylandXdgToplevel::sendConfigure(
const QSize &size,
const QList<QWaylandXdgToplevel::State> &states)
1025 if (!size.isValid()) {
1026 qWarning() <<
"Can't configure xdg_toplevel with an invalid size" << size;
1029 Q_D(QWaylandXdgToplevel);
1030 auto statesBytes = QByteArray::fromRawData(
reinterpret_cast<
const char *>(states.data()),
1031 states.size() *
static_cast<
int>(
sizeof(State)));
1032 uint32_t serial = d->m_xdgSurface->surface()->compositor()->nextSerial();
1033 d->m_pendingConfigures.append(QWaylandXdgToplevelPrivate::ConfigureEvent{states, size, serial});
1034 d->send_configure(size.width(), size.height(), statesBytes);
1035 QWaylandXdgSurfacePrivate::get(d->m_xdgSurface)->send_configure(serial);
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051uint QWaylandXdgToplevel::sendConfigure(
const QSize &size,
const QList<
int> &states)
1054 for (
auto state : states)
1056 return sendConfigure(size, s);
1060
1061
1062
1063
1066
1067
1068void QWaylandXdgToplevel::sendClose()
1070 Q_D(QWaylandXdgToplevel);
1075
1076
1077
1078
1079
1080
1081
1084
1085
1086
1087
1088
1089uint QWaylandXdgToplevel::sendMaximized(
const QSize &size)
1091 Q_D(QWaylandXdgToplevel);
1092 QWaylandXdgToplevelPrivate::ConfigureEvent conf = d->lastSentConfigure();
1094 if (!conf.states.contains(QWaylandXdgToplevel::State::MaximizedState))
1095 conf.states.append(QWaylandXdgToplevel::State::MaximizedState);
1096 conf.states.removeOne(QWaylandXdgToplevel::State::FullscreenState);
1097 conf.states.removeOne(QWaylandXdgToplevel::State::ResizingState);
1099 return sendConfigure(size, conf.states);
1103
1104
1105
1106
1107
1108
1109
1110
1113
1114
1115
1116
1117
1118
1119uint QWaylandXdgToplevel::sendUnmaximized(
const QSize &size)
1121 Q_D(QWaylandXdgToplevel);
1122 QWaylandXdgToplevelPrivate::ConfigureEvent conf = d->lastSentConfigure();
1124 conf.states.removeOne(QWaylandXdgToplevel::State::MaximizedState);
1125 conf.states.removeOne(QWaylandXdgToplevel::State::FullscreenState);
1126 conf.states.removeOne(QWaylandXdgToplevel::State::ResizingState);
1128 return sendConfigure(size, conf.states);
1133
1134
1135
1136
1137
1138
1139
1140
1141
1144
1145
1146
1147
1148
1149
1150
1151uint QWaylandXdgToplevel::sendFullscreen(
const QSize &size)
1153 Q_D(QWaylandXdgToplevel);
1154 QWaylandXdgToplevelPrivate::ConfigureEvent conf = d->lastSentConfigure();
1156 if (!conf.states.contains(QWaylandXdgToplevel::State::FullscreenState))
1157 conf.states.append(QWaylandXdgToplevel::State::FullscreenState);
1158 conf.states.removeOne(QWaylandXdgToplevel::State::MaximizedState);
1159 conf.states.removeOne(QWaylandXdgToplevel::State::ResizingState);
1161 return sendConfigure(size, conf.states);
1165
1166
1167
1168
1169
1170
1171
1174
1175
1176
1177
1178
1179uint QWaylandXdgToplevel::sendResizing(
const QSize &size)
1181 Q_D(QWaylandXdgToplevel);
1182 QWaylandXdgToplevelPrivate::ConfigureEvent conf = d->lastSentConfigure();
1184 if (!conf.states.contains(QWaylandXdgToplevel::State::ResizingState))
1185 conf.states.append(QWaylandXdgToplevel::State::ResizingState);
1186 conf.states.removeOne(QWaylandXdgToplevel::State::MaximizedState);
1187 conf.states.removeOne(QWaylandXdgToplevel::State::FullscreenState);
1189 return sendConfigure(size, conf.states);
1193
1194
1195QWaylandSurfaceRole *QWaylandXdgToplevel::role()
1197 return &QWaylandXdgToplevelPrivate::s_role;
1201
1202
1203QWaylandXdgToplevel *QWaylandXdgToplevel::fromResource(wl_resource *resource)
1205 if (
auto p = QtWayland::fromResource<QWaylandXdgToplevelPrivate *>(resource))
1211
1212
1213
1214
1215
1216
1217
1218
1221
1222
1223
1224
1225
1226
1227
1228
1231
1232
1233
1234
1235
1236
1237
1238
1241
1242
1243
1244
1245
1246
1247
1248
1251
1252
1253
1254
1255
1256
1257
1258
1261
1262
1263
1264
1265
1266
1267
1268
1271
1272
1273
1274
1275
1276
1279
1280
1281
1282
1283
1284
1286QList<
int> QWaylandXdgToplevel::statesAsInts()
const
1289 const auto s = states();
1290 list.reserve(s.size());
1291 for (
auto state : s) {
1292 list <<
static_cast<
int>(state);
1297QWaylandSurfaceRole QWaylandXdgToplevelPrivate::s_role(
"xdg_toplevel");
1299QWaylandXdgToplevelPrivate::QWaylandXdgToplevelPrivate(QWaylandXdgSurface *xdgSurface,
const QWaylandResource &resource)
1300 : m_xdgSurface(xdgSurface)
1302 init(resource.resource());
1305void QWaylandXdgToplevelPrivate::handleAckConfigure(uint serial)
1307 Q_Q(QWaylandXdgToplevel);
1308 ConfigureEvent config;
1310 if (m_pendingConfigures.empty()) {
1311 qWarning(
"Toplevel received an unexpected ack_configure!");
1316 config = m_pendingConfigures.takeFirst();
1318 if (config.serial == serial)
1322 QList<uint> changedStates;
1323 std::set_symmetric_difference(
1324 m_lastAckedConfigure.states.begin(), m_lastAckedConfigure.states.end(),
1325 config.states.begin(), config.states.end(),
1326 std::back_inserter(changedStates));
1328 m_lastAckedConfigure = config;
1330 for (uint state : std::as_const(changedStates)) {
1332 case state_maximized:
1333 emit q->maximizedChanged();
1335 case state_fullscreen:
1336 emit q->fullscreenChanged();
1338 case state_resizing:
1339 emit q->resizingChanged();
1341 case state_activated:
1342 emit q->activatedChanged();
1347 if (!changedStates.empty())
1348 emit q->statesChanged();
1351void QWaylandXdgToplevelPrivate::handleFocusLost()
1353 Q_Q(QWaylandXdgToplevel);
1354 QWaylandXdgToplevelPrivate::ConfigureEvent current = lastSentConfigure();
1355 current.states.removeOne(QWaylandXdgToplevel::State::ActivatedState);
1356 q->sendConfigure(current.size, current.states);
1359void QWaylandXdgToplevelPrivate::handleFocusReceived()
1361 Q_Q(QWaylandXdgToplevel);
1362 QWaylandXdgToplevelPrivate::ConfigureEvent current = lastSentConfigure();
1363 if (!current.states.contains(QWaylandXdgToplevel::State::ActivatedState)) {
1364 current.states.push_back(QWaylandXdgToplevel::State::ActivatedState);
1365 q->sendConfigure(current.size, current.states);
1369Qt::Edges QWaylandXdgToplevelPrivate::convertToEdges(resize_edge edge)
1371 return Qt::Edges(((edge & 0b1100) >> 1) | ((edge & 0b0010) << 2) | (edge & 0b0001));
1374void QWaylandXdgToplevelPrivate::xdg_toplevel_destroy_resource(QtWaylandServer::xdg_toplevel::Resource *resource)
1377 Q_Q(QWaylandXdgToplevel);
1381void QWaylandXdgToplevelPrivate::xdg_toplevel_destroy(QtWaylandServer::xdg_toplevel::Resource *resource)
1383 if (Q_UNLIKELY(m_decoration))
1384 qWarning() <<
"Client error: xdg_toplevel destroyed before its decoration object";
1386 wl_resource_destroy(resource->handle);
1390void QWaylandXdgToplevelPrivate::xdg_toplevel_set_parent(QtWaylandServer::xdg_toplevel::Resource *resource, wl_resource *parent)
1393 QWaylandXdgToplevel *parentToplevel = QWaylandXdgToplevel::fromResource(parent);
1395 Q_Q(QWaylandXdgToplevel);
1397 if (m_parentToplevel != parentToplevel) {
1398 m_parentToplevel = parentToplevel;
1399 emit q->parentToplevelChanged();
1402 if (m_parentToplevel && m_xdgSurface->windowType() != Qt::WindowType::SubWindow) {
1404 QWaylandXdgSurfacePrivate::get(m_xdgSurface)->setWindowType(Qt::WindowType::SubWindow);
1405 }
else if (!m_parentToplevel && m_xdgSurface->windowType() != Qt::WindowType::Window) {
1407 QWaylandXdgSurfacePrivate::get(m_xdgSurface)->setWindowType(Qt::WindowType::Window);
1411void QWaylandXdgToplevelPrivate::xdg_toplevel_set_title(QtWaylandServer::xdg_toplevel::Resource *resource,
const QString &title)
1414 if (title == m_title)
1416 Q_Q(QWaylandXdgToplevel);
1418 emit q->titleChanged();
1421void QWaylandXdgToplevelPrivate::xdg_toplevel_set_app_id(QtWaylandServer::xdg_toplevel::Resource *resource,
const QString &app_id)
1424 if (app_id == m_appId)
1426 Q_Q(QWaylandXdgToplevel);
1428 emit q->appIdChanged();
1431void QWaylandXdgToplevelPrivate::xdg_toplevel_show_window_menu(QtWaylandServer::xdg_toplevel::Resource *resource, wl_resource *seatResource, uint32_t serial, int32_t x, int32_t y)
1435 QPoint position(x, y);
1436 auto seat = QWaylandSeat::fromSeatResource(seatResource);
1437 Q_Q(QWaylandXdgToplevel);
1438 emit q->showWindowMenu(seat, position);
1441void QWaylandXdgToplevelPrivate::xdg_toplevel_move(Resource *resource, wl_resource *seatResource, uint32_t serial)
1445 Q_Q(QWaylandXdgToplevel);
1446 QWaylandSeat *seat = QWaylandSeat::fromSeatResource(seatResource);
1447 emit q->startMove(seat);
1450void QWaylandXdgToplevelPrivate::xdg_toplevel_resize(QtWaylandServer::xdg_toplevel::Resource *resource, wl_resource *seatResource, uint32_t serial, uint32_t edges)
1454 Q_Q(QWaylandXdgToplevel);
1455 QWaylandSeat *seat = QWaylandSeat::fromSeatResource(seatResource);
1456 emit q->startResize(seat, convertToEdges(resize_edge(edges)));
1459void QWaylandXdgToplevelPrivate::xdg_toplevel_set_max_size(QtWaylandServer::xdg_toplevel::Resource *resource, int32_t width, int32_t height)
1463 QSize maxSize(width, height);
1464 if (width == 0 && height == 0)
1467 if (m_maxSize == maxSize)
1470 if (width < 0 || height < 0) {
1472 qWarning() <<
"Received a xdg_toplevel.set_max_size request with a negative size";
1476 if (m_minSize.isValid() && maxSize.isValid() &&
1477 (maxSize.width() < m_minSize.width() || maxSize.height() < m_minSize.height())) {
1479 qWarning() <<
"Received a xdg_toplevel.set_max_size request with a size smaller than the minimium size";
1483 m_maxSize = maxSize;
1485 Q_Q(QWaylandXdgToplevel);
1486 emit q->maxSizeChanged();
1489void QWaylandXdgToplevelPrivate::xdg_toplevel_set_min_size(QtWaylandServer::xdg_toplevel::Resource *resource, int32_t width, int32_t height)
1493 QSize minSize(width, height);
1494 if (width == 0 && height == 0)
1497 if (m_minSize == minSize)
1500 if (width < 0 || height < 0) {
1502 qWarning() <<
"Received a xdg_toplevel.set_min_size request with a negative size";
1506 if (m_maxSize.isValid() && minSize.isValid() &&
1507 (minSize.width() > m_maxSize.width() || minSize.height() > m_maxSize.height())) {
1509 qWarning() <<
"Received a xdg_toplevel.set_min_size request with a size larger than the maximum size";
1513 m_minSize = minSize;
1515 Q_Q(QWaylandXdgToplevel);
1516 emit q->minSizeChanged();
1519void QWaylandXdgToplevelPrivate::xdg_toplevel_set_maximized(QtWaylandServer::xdg_toplevel::Resource *resource)
1522 Q_Q(QWaylandXdgToplevel);
1523 emit q->setMaximized();
1526void QWaylandXdgToplevelPrivate::xdg_toplevel_unset_maximized(QtWaylandServer::xdg_toplevel::Resource *resource)
1529 Q_Q(QWaylandXdgToplevel);
1530 emit q->unsetMaximized();
1533void QWaylandXdgToplevelPrivate::xdg_toplevel_set_fullscreen(QtWaylandServer::xdg_toplevel::Resource *resource, wl_resource *output_res)
1536 Q_Q(QWaylandXdgToplevel);
1537 QWaylandOutput *output = output_res ? QWaylandOutput::fromResource(output_res) :
nullptr;
1538 emit q->setFullscreen(output);
1541void QWaylandXdgToplevelPrivate::xdg_toplevel_unset_fullscreen(QtWaylandServer::xdg_toplevel::Resource *resource)
1544 Q_Q(QWaylandXdgToplevel);
1545 emit q->unsetFullscreen();
1548void QWaylandXdgToplevelPrivate::xdg_toplevel_set_minimized(QtWaylandServer::xdg_toplevel::Resource *resource)
1551 Q_Q(QWaylandXdgToplevel);
1552 emit q->setMinimized();
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1583
1584
1585QWaylandXdgPopup::QWaylandXdgPopup(QWaylandXdgSurface *xdgSurface, QWaylandXdgSurface *parentXdgSurface,
1586 QWaylandXdgPositioner *positioner, QWaylandResource &resource)
1587 : QObject(*
new QWaylandXdgPopupPrivate(xdgSurface, parentXdgSurface, positioner, resource))
1592
1593
1594
1595
1598
1599
1600
1601
1602QWaylandXdgSurface *QWaylandXdgPopup::xdgSurface()
const
1604 Q_D(
const QWaylandXdgPopup);
1605 return d->m_xdgSurface;
1609
1610
1611
1612
1615
1616
1617
1618
1619
1620QWaylandXdgSurface *QWaylandXdgPopup::parentXdgSurface()
const
1622 Q_D(
const QWaylandXdgPopup);
1623 return d->m_parentXdgSurface;
1627
1628
1629
1630
1631
1634
1635
1636
1637
1638
1639QRect QWaylandXdgPopup::configuredGeometry()
const
1641 Q_D(
const QWaylandXdgPopup);
1642 return d->m_geometry;
1646
1647
1648
1649
1650
1653
1654
1655
1656
1657
1658QRect QWaylandXdgPopup::anchorRect()
const
1660 Q_D(
const QWaylandXdgPopup);
1661 return d->m_positionerData.anchorRect;
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1679
1680
1681
1682
1683
1684
1685Qt::Edges QWaylandXdgPopup::anchorEdges()
const
1687 Q_D(
const QWaylandXdgPopup);
1688 return d->m_positionerData.anchorEdges;
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1705
1706
1707
1708
1709
1710Qt::Edges QWaylandXdgPopup::gravityEdges()
const
1712 Q_D(
const QWaylandXdgPopup);
1713 return d->m_positionerData.gravityEdges;
1717
1718
1719
1720
1721
1722
1723
1724
1727
1728
1729
1730
1731Qt::Orientations QWaylandXdgPopup::slideConstraints()
const
1733 Q_D(
const QWaylandXdgPopup);
1734 const uint flags = d->m_positionerData.constraintAdjustments;
1736 Qt::Orientations constraints = {};
1738 if (flags & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_X)
1739 constraints |= Qt::Horizontal;
1740 if (flags & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_Y)
1741 constraints |= Qt::Vertical;
1747
1748
1749
1750
1751
1752
1753
1754
1757
1758
1759
1760
1761Qt::Orientations QWaylandXdgPopup::flipConstraints()
const
1763 Q_D(
const QWaylandXdgPopup);
1764 const uint flags = d->m_positionerData.constraintAdjustments;
1766 Qt::Orientations constraints = {};
1768 if (flags & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_X)
1769 constraints |= Qt::Horizontal;
1770 if (flags & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_Y)
1771 constraints |= Qt::Vertical;
1777
1778
1779
1780
1781
1782
1783
1784
1787
1788
1789
1790
1791Qt::Orientations QWaylandXdgPopup::resizeConstraints()
const
1793 Q_D(
const QWaylandXdgPopup);
1794 const uint flags = d->m_positionerData.constraintAdjustments;
1796 Qt::Orientations constraints = {};
1798 if (flags & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_X)
1799 constraints |= Qt::Horizontal;
1800 if (flags & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_Y)
1801 constraints |= Qt::Vertical;
1807
1808
1809
1810
1811
1814
1815
1816
1817
1818
1819QPoint QWaylandXdgPopup::offset()
const
1821 Q_D(
const QWaylandXdgPopup);
1822 return d->m_positionerData.offset;
1826
1827
1828
1829
1832
1833
1834
1835
1836QSize QWaylandXdgPopup::positionerSize()
const
1838 Q_D(
const QWaylandXdgPopup);
1839 return d->m_positionerData.size;
1843
1844
1845
1846
1847
1850
1851
1852
1853
1854
1855QPoint QWaylandXdgPopup::unconstrainedPosition()
const
1857 Q_D(
const QWaylandXdgPopup);
1858 return d->m_positionerData.unconstrainedPosition();
1862
1863
1864
1865
1866
1867
1868
1871
1872
1873
1874
1875
1876
1877uint QWaylandXdgPopup::sendConfigure(
const QRect &geometry)
1879 Q_D(QWaylandXdgPopup);
1880 return d->sendConfigure(geometry);
1884
1885
1886
1887
1888
1889
1892
1893
1894
1895
1896
1897void QWaylandXdgPopup::sendPopupDone()
1899 Q_D(QWaylandXdgPopup);
1900 d->send_popup_done();
1904
1905
1906QWaylandSurfaceRole *QWaylandXdgPopup::role()
1908 return &QWaylandXdgPopupPrivate::s_role;
1911QWaylandXdgPopupPrivate::QWaylandXdgPopupPrivate(QWaylandXdgSurface *xdgSurface, QWaylandXdgSurface *parentXdgSurface,
1912 QWaylandXdgPositioner *positioner,
const QWaylandResource &resource)
1913 : m_xdgSurface(xdgSurface)
1914 , m_parentXdgSurface(parentXdgSurface)
1915 , m_positionerData(positioner->m_data)
1917 Q_ASSERT(m_positionerData.isComplete());
1918 init(resource.resource());
1920 QWaylandXdgSurfacePrivate::get(m_xdgSurface)->setWindowType(Qt::WindowType::Popup);
1923 sendConfigure(QRect(m_positionerData.unconstrainedPosition(), m_positionerData.size));
1926void QWaylandXdgPopupPrivate::handleAckConfigure(uint serial)
1928 Q_Q(QWaylandXdgPopup);
1929 ConfigureEvent config;
1931 if (m_pendingConfigures.empty()) {
1932 qWarning(
"Popup received an unexpected ack_configure!");
1937 config = m_pendingConfigures.takeFirst();
1939 if (config.serial == serial)
1943 if (m_geometry == config.geometry)
1946 m_geometry = config.geometry;
1947 emit q->configuredGeometryChanged();
1950uint QWaylandXdgPopupPrivate::sendConfigure(
const QRect &geometry)
1952 uint32_t serial = m_xdgSurface->surface()->compositor()->nextSerial();
1953 m_pendingConfigures.append(QWaylandXdgPopupPrivate::ConfigureEvent{geometry, serial});
1954 send_configure(geometry.x(), geometry.y(), geometry.width(), geometry.height());
1955 QWaylandXdgSurfacePrivate::get(m_xdgSurface)->send_configure(serial);
1959void QWaylandXdgPopupPrivate::xdg_popup_destroy(QtWaylandServer::xdg_popup::Resource *resource)
1962 qWarning() << Q_FUNC_INFO <<
"Not implemented";
1965void QWaylandXdgPopupPrivate::xdg_popup_grab(QtWaylandServer::xdg_popup::Resource *resource, wl_resource *seat, uint32_t serial)
1970 qWarning() << Q_FUNC_INFO <<
"Not implemented";
1975QWaylandSurfaceRole QWaylandXdgPopupPrivate::s_role(
"xdg_popup");
1977QWaylandXdgPositionerData::QWaylandXdgPositionerData()
1981bool QWaylandXdgPositionerData::isComplete()
const
1983 return size.width() > 0 && size.height() > 0 && anchorRect.size().width() > 0 && anchorRect.size().height() > 0;
1986QPoint QWaylandXdgPositionerData::anchorPoint()
const
1989 if (anchorEdges & Qt::TopEdge)
1990 yPosition = anchorRect.top();
1991 else if (anchorEdges & Qt::BottomEdge)
1992 yPosition = anchorRect.bottom() + 1;
1994 yPosition = anchorRect.top() + anchorRect.height() / 2;
1997 if (anchorEdges & Qt::LeftEdge)
1998 xPosition = anchorRect.left();
1999 else if (anchorEdges & Qt::RightEdge)
2000 xPosition = anchorRect.right() + 1;
2002 xPosition = anchorRect.left() + anchorRect.width() / 2;
2004 return QPoint(xPosition, yPosition);
2007QPoint QWaylandXdgPositionerData::unconstrainedPosition()
const
2009 int gravityOffsetY = 0;
2010 if (gravityEdges & Qt::TopEdge)
2011 gravityOffsetY = -size.height();
2012 else if (!(gravityEdges & Qt::BottomEdge))
2013 gravityOffsetY = -size.height() / 2;
2015 int gravityOffsetX = 0;
2016 if (gravityEdges & Qt::LeftEdge)
2017 gravityOffsetX = -size.width();
2018 else if (!(gravityEdges & Qt::RightEdge))
2019 gravityOffsetX = -size.width() / 2;
2021 QPoint gravityOffset(gravityOffsetX, gravityOffsetY);
2022 return anchorPoint() + gravityOffset + offset;
2025QWaylandXdgPositioner::QWaylandXdgPositioner(
const QWaylandResource &resource)
2027 init(resource.resource());
2030void QWaylandXdgPositioner::xdg_positioner_destroy_resource(QtWaylandServer::xdg_positioner::Resource *resource)
2036void QWaylandXdgPositioner::xdg_positioner_destroy(QtWaylandServer::xdg_positioner::Resource *resource)
2038 wl_resource_destroy(resource->handle);
2041void QWaylandXdgPositioner::xdg_positioner_set_size(QtWaylandServer::xdg_positioner::Resource *resource, int32_t width, int32_t height)
2043 if (width <= 0 || height <= 0) {
2044 wl_resource_post_error(resource->handle, XDG_POSITIONER_ERROR_INVALID_INPUT,
2045 "xdg_positioner.set_size requested with non-positive dimensions");
2049 QSize size(width, height);
2053void QWaylandXdgPositioner::xdg_positioner_set_anchor_rect(QtWaylandServer::xdg_positioner::Resource *resource, int32_t x, int32_t y, int32_t width, int32_t height)
2055 if (width <= 0 || height <= 0) {
2056 wl_resource_post_error(resource->handle, XDG_POSITIONER_ERROR_INVALID_INPUT,
2057 "xdg_positioner.set_anchor_rect requested with non-positive dimensions");
2061 QRect anchorRect(x, y, width, height);
2062 m_data.anchorRect = anchorRect;
2065void QWaylandXdgPositioner::xdg_positioner_set_anchor(QtWaylandServer::xdg_positioner::Resource *resource, uint32_t anchor)
2067 Qt::Edges anchorEdges = convertToEdges(xdg_positioner::anchor(anchor));
2069 if ((anchorEdges & Qt::BottomEdge && anchorEdges & Qt::TopEdge) ||
2070 (anchorEdges & Qt::LeftEdge && anchorEdges & Qt::RightEdge)) {
2071 wl_resource_post_error(resource->handle, XDG_POSITIONER_ERROR_INVALID_INPUT,
2072 "xdg_positioner.set_anchor requested with parallel edges");
2076 m_data.anchorEdges = anchorEdges;
2079void QWaylandXdgPositioner::xdg_positioner_set_gravity(QtWaylandServer::xdg_positioner::Resource *resource, uint32_t gravity)
2081 Qt::Edges gravityEdges = convertToEdges(xdg_positioner::gravity(gravity));
2083 if ((gravityEdges & Qt::BottomEdge && gravityEdges & Qt::TopEdge) ||
2084 (gravityEdges & Qt::LeftEdge && gravityEdges & Qt::RightEdge)) {
2085 wl_resource_post_error(resource->handle, XDG_POSITIONER_ERROR_INVALID_INPUT,
2086 "xdg_positioner.set_gravity requested with parallel edges");
2090 m_data.gravityEdges = gravityEdges;
2093void QWaylandXdgPositioner::xdg_positioner_set_constraint_adjustment(QtWaylandServer::xdg_positioner::Resource *resource, uint32_t constraint_adjustment)
2096 m_data.constraintAdjustments = constraint_adjustment;
2099void QWaylandXdgPositioner::xdg_positioner_set_offset(QtWaylandServer::xdg_positioner::Resource *resource, int32_t x, int32_t y)
2102 m_data.offset = QPoint(x, y);
2105QWaylandXdgPositioner *QWaylandXdgPositioner::fromResource(wl_resource *resource)
2107 return QtWayland::fromResource<QWaylandXdgPositioner *>(resource);
2110Qt::Edges QWaylandXdgPositioner::convertToEdges(anchor anchor)
2118 return Qt::BottomEdge;
2120 return Qt::LeftEdge;
2122 return Qt::RightEdge;
2123 case anchor_top_left:
2124 return Qt::TopEdge | Qt::LeftEdge;
2125 case anchor_bottom_left:
2126 return Qt::BottomEdge | Qt::LeftEdge;
2127 case anchor_top_right:
2128 return Qt::TopEdge | Qt::RightEdge;
2129 case anchor_bottom_right:
2130 return Qt::BottomEdge | Qt::RightEdge;
2132 qWarning() <<
"Unknown Wayland xdg edge" << anchor;
2137Qt::Edges QWaylandXdgPositioner::convertToEdges(QWaylandXdgPositioner::gravity gravity)
2139 return convertToEdges(anchor(gravity));
2145#include "moc_qwaylandxdgshell.cpp"