20static const int s_version = 6;
29 return xdgSurfaces.value(surface);
34 xdgSurfaces.remove(surface);
43 QTimer *timer =
new QTimer(
q);
46 QObject::connect(timer, &QTimer::timeout,
q, [
this, serial, attempt = 0]()
mutable {
53 delete pings.take(serial);
55 pings.insert(serial, timer);
61 return shell->d.get();
66 const QList<XdgSurfaceInterface *> surfaces = xdgSurfaces.keys(resource);
72 if (xdgSurfaces.key(resource)) {
73 wl_resource_post_error(resource->handle, error_defunct_surfaces,
"xdg_wm_base was destroyed before children");
76 wl_resource_destroy(resource->handle);
81 wl_resource *positionerResource = wl_resource_create(resource->client(), &xdg_positioner_interface, resource->version(),
id);
90 wl_resource_post_error(resource->handle, XDG_SURFACE_ERROR_UNCONFIGURED_BUFFER,
"xdg_surface must not have a buffer at creation");
94 wl_resource *xdgSurfaceResource = wl_resource_create(resource->client(), &xdg_surface_interface, resource->version(),
id);
97 xdgSurfaces.insert(xdgSurface, resource);
102 if (QTimer *timer =
pings.take(serial)) {
127 XdgShellInterfacePrivate::Resource *clientResource = d->resourceForXdgSurface(surface);
131 quint32 serial = d->display->nextSerial();
132 d->send_ping(clientResource->handle, serial);
133 d->registerPing(serial);
140 return d->pingTimeout;
191 qWarning() <<
"Tried to destroy xdg_surface before its role object";
193 wl_resource_destroy(resource->handle);
200 wl_resource_post_error(resource->handle, error_already_constructed,
"the surface already has a role assigned %s", role->name().constData());
207 wl_resource *toplevelResource = wl_resource_create(resource->client(), &xdg_toplevel_interface, resource->version(),
id);
217 wl_resource_post_error(resource->handle, error_already_constructed,
"the surface already has a role assigned %s", role->name().constData());
227 wl_resource_post_error(shellPrivate->resourceForXdgSurface(
q)->handle,
228 QtWaylandServer::xdg_wm_base::error_invalid_positioner,
229 "xdg_positioner is incomplete");
235 if (parentXdgSurface) {
238 wl_resource_post_error(shellPrivate->resourceForXdgSurface(
q)->handle,
239 QtWaylandServer::xdg_wm_base::error_invalid_popup_parent,
240 "parent surface has no surface role");
243 parentSurface = parentXdgSurface->
surface();
246 wl_resource *popupResource = wl_resource_create(resource->client(), &xdg_popup_interface, resource->version(),
id);
255 wl_resource_post_error(resource->handle, error_not_constructed,
"xdg_surface must have a role");
259 if (width < 1 || height < 1) {
260 wl_resource_post_error(resource->handle, -1,
"invalid window geometry size (%dx%d)", width, height);
270 wl_resource_post_error(resource->handle, error_not_constructed,
"xdg_surface must have a role");
316 return d->isConfigured;
321 return d->windowGeometry;
326 if (
auto surfacePrivate = resource_cast<XdgSurfaceInterfacePrivate *>(resource)) {
327 return surfacePrivate->q;
335 , xdgSurface(xdgSurface)
342 if (xdgSurfacePrivate->firstBufferAttached && !xdgSurfacePrivate->surface->buffer()) {
347 xdgSurfacePrivate->apply(commit);
351 if (!minSize.isEmpty() && !maxSize.isEmpty() && (minSize.width() > maxSize.width() || minSize.height() > maxSize.height())) {
352 wl_resource_post_error(resource()->handle, error_invalid_size,
"minimum size can't be bigger than the maximum");
365 if (!xdgSurfacePrivate->isInitialized) {
367 xdgSurfacePrivate->isInitialized =
true;
374 xdgSurfacePrivate->reset();
393 wl_resource_destroy(resource->handle);
428 if (!xdgSurfacePrivate->isConfigured) {
429 wl_resource_post_error(resource->handle, QtWaylandServer::xdg_surface::error_not_constructed,
"surface has not been configured yet");
441 if (!xdgSurfacePrivate->isConfigured) {
442 wl_resource_post_error(resource->handle, QtWaylandServer::xdg_surface::error_not_constructed,
"surface has not been configured yet");
454 if (!xdgSurfacePrivate->isConfigured) {
455 wl_resource_post_error(resource->handle, QtWaylandServer::xdg_surface::error_not_constructed,
"surface has not been configured yet");
465 if (width < 0 || height < 0) {
466 wl_resource_post_error(resource->handle, error_invalid_size,
"width and height must be positive or zero");
474 if (width < 0 || height < 0) {
475 wl_resource_post_error(resource->handle, error_invalid_size,
"width and height must be positive or zero");
509 return toplevel->d.get();
514 return resource_cast<XdgToplevelInterfacePrivate *>(resource);
522 surfacePrivate->
pending = &d->pending;
533 surfacePrivate->
pending =
nullptr;
544 return d->xdgSurface->shell();
549 return d->xdgSurface;
554 return d->xdgSurface->surface();
559 return d->xdgSurface->isConfigured();
564 return d->parentXdgToplevel;
569 return d->windowTitle;
574 return d->windowClass;
579 return d->minimumSize.isEmpty() ? QSize(0, 0) : d->minimumSize;
584 return d->maximumSize.isEmpty() ? QSize(INT_MAX, INT_MAX) : d->maximumSize;
591 uint32_t statesData[9] = {0};
595 statesData[i++] = QtWaylandServer::xdg_toplevel::state_maximized;
598 statesData[i++] = QtWaylandServer::xdg_toplevel::state_fullscreen;
601 statesData[i++] = QtWaylandServer::xdg_toplevel::state_resizing;
604 statesData[i++] = QtWaylandServer::xdg_toplevel::state_activated;
607 if (d->resource()->version() >= XDG_TOPLEVEL_STATE_TILED_LEFT_SINCE_VERSION) {
609 statesData[i++] = QtWaylandServer::xdg_toplevel::state_tiled_left;
612 statesData[i++] = QtWaylandServer::xdg_toplevel::state_tiled_top;
615 statesData[i++] = QtWaylandServer::xdg_toplevel::state_tiled_right;
618 statesData[i++] = QtWaylandServer::xdg_toplevel::state_tiled_bottom;
622 if (d->resource()->version() >= XDG_TOPLEVEL_STATE_SUSPENDED_SINCE_VERSION) {
624 statesData[i++] = QtWaylandServer::xdg_toplevel::state_suspended;
628 const QByteArray xdgStates = QByteArray::fromRawData(
reinterpret_cast<char *
>(statesData),
sizeof(uint32_t) * i);
631 d->send_configure(size.width(), size.height(), xdgStates);
634 xdgSurfacePrivate->send_configure(serial);
635 xdgSurfacePrivate->isConfigured =
true;
647 if (d->resource()->version() >= XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION) {
648 d->send_configure_bounds(size.width(), size.height());
654 if (d->resource()->version() < XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION) {
659 uint32_t capabilitiesData[4] = {0};
663 capabilitiesData[i++] = QtWaylandServer::xdg_toplevel::wm_capabilities_window_menu;
666 capabilitiesData[i++] = QtWaylandServer::xdg_toplevel::wm_capabilities_maximize;
669 capabilitiesData[i++] = QtWaylandServer::xdg_toplevel::wm_capabilities_fullscreen;
672 capabilitiesData[i++] = QtWaylandServer::xdg_toplevel::wm_capabilities_minimize;
675 d->send_wm_capabilities(QByteArray::fromRawData(
reinterpret_cast<char *
>(capabilitiesData),
sizeof(uint32_t) * i));
680 if (
auto toplevelPrivate = resource_cast<XdgToplevelInterfacePrivate *>(resource)) {
681 return toplevelPrivate->q;
688 return popup->d.get();
694 , xdgSurface(xdgSurface)
702 wl_resource_post_error(shellPrivate->resourceForXdgSurface(
xdgSurface)->handle,
703 QtWaylandServer::xdg_wm_base::error_invalid_popup_parent,
704 "no xdg_popup parent surface has been specified");
709 if (xdgSurfacePrivate->firstBufferAttached && !xdgSurfacePrivate->surface->buffer()) {
714 xdgSurfacePrivate->apply(commit);
716 if (!xdgSurfacePrivate->isInitialized) {
718 xdgSurfacePrivate->isInitialized =
true;
727 xdgSurfacePrivate->reset();
740 wl_resource_destroy(resource->handle);
746 wl_resource_post_error(resource->handle, error_invalid_grab,
"xdg_surface is already mapped");
763 surfacePrivate->
popup =
this;
764 surfacePrivate->
pending = &d->pending;
776 surfacePrivate->
popup =
nullptr;
777 surfacePrivate->
pending =
nullptr;
788 return d->parentSurface;
793 return d->xdgSurface;
798 return d->xdgSurface->surface();
803 return d->xdgSurface->isConfigured();
808 return d->positioner;
815 d->send_configure(rect.x(), rect.y(), rect.width(), rect.height());
818 xdgSurfacePrivate->send_configure(serial);
819 xdgSurfacePrivate->isConfigured =
true;
826 d->send_popup_done();
831 Q_ASSERT(d->resource()->version() >= XDG_POPUP_REPOSITIONED_SINCE_VERSION);
832 d->send_repositioned(token);
837 if (
auto popupPrivate = resource_cast<XdgPopupInterfacePrivate *>(resource)) {
838 return popupPrivate->q;
851 return resource_cast<XdgPositionerPrivate *>(resource);
861 wl_resource_destroy(resource->handle);
866 if (width < 1 || height < 1) {
867 wl_resource_post_error(resource->handle, error_invalid_input,
"width and height must be positive and non-zero");
870 data->size = QSize(width, height);
875 if (width < 1 || height < 1) {
876 wl_resource_post_error(resource->handle, error_invalid_input,
"width and height must be positive and non-zero");
879 data->anchorRect = QRect(x, y, width, height);
884 if (anchor > anchor_bottom_right) {
885 wl_resource_post_error(resource->handle, error_invalid_input,
"unknown anchor point");
891 data->anchorEdges = Qt::TopEdge;
893 case anchor_top_right:
894 data->anchorEdges = Qt::TopEdge | Qt::RightEdge;
897 data->anchorEdges = Qt::RightEdge;
899 case anchor_bottom_right:
900 data->anchorEdges = Qt::BottomEdge | Qt::RightEdge;
903 data->anchorEdges = Qt::BottomEdge;
905 case anchor_bottom_left:
906 data->anchorEdges = Qt::BottomEdge | Qt::LeftEdge;
909 data->anchorEdges = Qt::LeftEdge;
911 case anchor_top_left:
912 data->anchorEdges = Qt::TopEdge | Qt::LeftEdge;
915 data->anchorEdges = Qt::Edges();
922 data->parentSize = QSize(width, height);
927 data->isReactive =
true;
932 data->parentConfigure = serial;
937 if (gravity > gravity_bottom_right) {
938 wl_resource_post_error(resource->handle, error_invalid_input,
"unknown gravity direction");
944 data->gravityEdges = Qt::TopEdge;
946 case gravity_top_right:
947 data->gravityEdges = Qt::TopEdge | Qt::RightEdge;
950 data->gravityEdges = Qt::RightEdge;
952 case gravity_bottom_right:
953 data->gravityEdges = Qt::BottomEdge | Qt::RightEdge;
956 data->gravityEdges = Qt::BottomEdge;
958 case gravity_bottom_left:
959 data->gravityEdges = Qt::BottomEdge | Qt::LeftEdge;
962 data->gravityEdges = Qt::LeftEdge;
964 case gravity_top_left:
965 data->gravityEdges = Qt::TopEdge | Qt::LeftEdge;
968 data->gravityEdges = Qt::Edges();
975 if (constraint_adjustment & constraint_adjustment_flip_x) {
976 data->flipConstraintAdjustments |= Qt::Horizontal;
981 if (constraint_adjustment & constraint_adjustment_flip_y) {
982 data->flipConstraintAdjustments |= Qt::Vertical;
987 if (constraint_adjustment & constraint_adjustment_slide_x) {
988 data->slideConstraintAdjustments |= Qt::Horizontal;
993 if (constraint_adjustment & constraint_adjustment_slide_y) {
994 data->slideConstraintAdjustments |= Qt::Vertical;
999 if (constraint_adjustment & constraint_adjustment_resize_x) {
1000 data->resizeConstraintAdjustments |= Qt::Horizontal;
1005 if (constraint_adjustment & constraint_adjustment_resize_y) {
1006 data->resizeConstraintAdjustments |= Qt::Vertical;
1014 data->offset = QPoint(x, y);
1039 return d->size.isValid() && d->anchorRect.isValid();
1049 return d->isReactive;
1055 auto inBounds = [bounds](
const QRectF &target, Qt::Edges edges = Qt::LeftEdge | Qt::RightEdge | Qt::TopEdge | Qt::BottomEdge) ->
bool {
1056 if (edges & Qt::LeftEdge && target.left() < bounds.left()) {
1059 if (edges & Qt::TopEdge && target.top() < bounds.top()) {
1062 if (edges & Qt::RightEdge && target.right() > bounds.right()) {
1066 if (edges & Qt::BottomEdge && target.bottom() > bounds.bottom()) {
1072 QRectF popupRect(
popupOffset(d->anchorRect, d->anchorEdges, d->gravityEdges, d->size) + d->offset, d->size);
1075 if (inBounds(popupRect)) {
1080 if (d->flipConstraintAdjustments & Qt::Horizontal) {
1081 if (!inBounds(popupRect, Qt::LeftEdge | Qt::RightEdge)) {
1083 auto flippedAnchorEdge = d->anchorEdges;
1084 if (flippedAnchorEdge & (Qt::LeftEdge | Qt::RightEdge)) {
1085 flippedAnchorEdge ^= (Qt::LeftEdge | Qt::RightEdge);
1087 auto flippedGravity = d->gravityEdges;
1088 if (flippedGravity & (Qt::LeftEdge | Qt::RightEdge)) {
1089 flippedGravity ^= (Qt::LeftEdge | Qt::RightEdge);
1091 auto flippedPopupRect = QRectF(
popupOffset(d->anchorRect, flippedAnchorEdge, flippedGravity, d->size) + d->offset, d->size);
1094 if (inBounds(flippedPopupRect, Qt::LeftEdge | Qt::RightEdge)) {
1095 popupRect.moveLeft(flippedPopupRect.left());
1099 if (d->slideConstraintAdjustments & Qt::Horizontal) {
1100 if (!inBounds(popupRect, Qt::LeftEdge)) {
1101 popupRect.moveLeft(bounds.left());
1103 if (!inBounds(popupRect, Qt::RightEdge)) {
1104 popupRect.moveRight(bounds.right());
1107 if (d->resizeConstraintAdjustments & Qt::Horizontal) {
1108 QRectF unconstrainedRect = popupRect;
1110 if (!inBounds(unconstrainedRect, Qt::LeftEdge)) {
1111 unconstrainedRect.setLeft(bounds.left());
1113 if (!inBounds(unconstrainedRect, Qt::RightEdge)) {
1114 unconstrainedRect.setRight(bounds.right());
1117 if (unconstrainedRect.isValid()) {
1118 popupRect = unconstrainedRect;
1122 if (d->flipConstraintAdjustments & Qt::Vertical) {
1123 if (!inBounds(popupRect, Qt::TopEdge | Qt::BottomEdge)) {
1125 auto flippedAnchorEdge = d->anchorEdges;
1126 if (flippedAnchorEdge & (Qt::TopEdge | Qt::BottomEdge)) {
1127 flippedAnchorEdge ^= (Qt::TopEdge | Qt::BottomEdge);
1129 auto flippedGravity = d->gravityEdges;
1130 if (flippedGravity & (Qt::TopEdge | Qt::BottomEdge)) {
1131 flippedGravity ^= (Qt::TopEdge | Qt::BottomEdge);
1133 auto flippedPopupRect = QRectF(
popupOffset(d->anchorRect, flippedAnchorEdge, flippedGravity, d->size) + d->offset, d->size);
1136 if (inBounds(flippedPopupRect, Qt::TopEdge | Qt::BottomEdge)) {
1137 popupRect.moveTop(flippedPopupRect.top());
1141 if (d->slideConstraintAdjustments & Qt::Vertical) {
1142 if (!inBounds(popupRect, Qt::TopEdge)) {
1143 popupRect.moveTop(bounds.top());
1145 if (!inBounds(popupRect, Qt::BottomEdge)) {
1146 popupRect.moveBottom(bounds.bottom());
1149 if (d->resizeConstraintAdjustments & Qt::Vertical) {
1150 QRectF unconstrainedRect = popupRect;
1152 if (!inBounds(unconstrainedRect, Qt::TopEdge)) {
1153 unconstrainedRect.setTop(bounds.top());
1155 if (!inBounds(unconstrainedRect, Qt::BottomEdge)) {
1156 unconstrainedRect.setBottom(bounds.bottom());
1159 if (unconstrainedRect.isValid()) {
1160 popupRect = unconstrainedRect;
1170 if (xdgPositionerPrivate)
1182#include "moc_xdgshell.cpp"
Class holding the Wayland server display loop.
static OutputInterface * get(wl_resource *native)
Represents a Seat on the Wayland Display.
static SeatInterface * get(wl_resource *native)
QMap< quint32, XdgToplevelCommit > stashed
XdgToplevelCommit pending
Resource representing a wl_surface.
static SurfaceInterface * get(wl_resource *native)
GraphicsBuffer * buffer() const
SurfaceRole * role() const
QRectF placement(const QRectF &bounds) const
static XdgPositioner get(::wl_resource *resource)
XdgPositioner & operator=(const XdgPositioner &other)
void xdg_positioner_set_reactive(Resource *resource) override
void xdg_positioner_destroy(Resource *resource) override
void xdg_positioner_set_size(Resource *resource, int32_t width, int32_t height) override
void xdg_positioner_set_offset(Resource *resource, int32_t x, int32_t y) override
void xdg_positioner_destroy_resource(Resource *resource) override
static XdgPositionerPrivate * get(::wl_resource *resource)
void xdg_positioner_set_constraint_adjustment(Resource *resource, uint32_t constraint_adjustment) override
void xdg_positioner_set_gravity(Resource *resource, uint32_t gravity) override
void xdg_positioner_set_parent_size(Resource *resource, int32_t width, int32_t height) override
void xdg_positioner_set_anchor_rect(Resource *resource, int32_t x, int32_t y, int32_t width, int32_t height) override
void xdg_positioner_set_anchor(Resource *resource, uint32_t anchor) override
QSharedDataPointer< XdgPositionerData > data
XdgPositionerPrivate(::wl_resource *resource)
void xdg_positioner_set_parent_configure(Resource *resource, uint32_t serial) override
XdgShellInterface(Display *display, QObject *parent=nullptr)
void setPingTimeoutInterval(std::chrono::milliseconds pingTimeout)
void toplevelCreated(XdgToplevelInterface *toplevel)
void popupCreated(XdgPopupInterface *popup)
quint32 ping(XdgSurfaceInterface *surface)
std::chrono::milliseconds pingTimeoutInterval() const
void pingTimeout(quint32 serial)
~XdgShellInterface() override
void pingDelayed(quint32 serial)
void pongReceived(quint32 serial)
Display * display() const
void xdg_wm_base_create_positioner(Resource *resource, uint32_t id) override
void registerPing(quint32 serial)
void xdg_wm_base_pong(Resource *resource, uint32_t serial) override
std::chrono::milliseconds pingTimeout
void xdg_wm_base_destroy(Resource *resource) override
Resource * resourceForXdgSurface(XdgSurfaceInterface *surface) const
void unregisterXdgSurface(XdgSurfaceInterface *surface)
QMap< quint32, QTimer * > pings
void xdg_wm_base_get_xdg_surface(Resource *resource, uint32_t id, ::wl_resource *surface) override
void xdg_wm_base_destroy_resource(Resource *resource) override
XdgShellInterfacePrivate(XdgShellInterface *shell)
static XdgShellInterfacePrivate * get(XdgShellInterface *shell)
~XdgSurfaceInterface() override
static XdgSurfaceInterface * get(::wl_resource *resource)
XdgPopupInterface * popup() const
bool isConfigured() const
QRect windowGeometry() const
void windowGeometryChanged(const QRect &rect)
void aboutToBeDestroyed()
XdgSurfaceInterface(XdgShellInterface *shell, SurfaceInterface *surface, ::wl_resource *resource)
SurfaceInterface * surface() const
XdgShellInterface * shell() const
void configureAcknowledged(quint32 serial)
XdgToplevelInterface * toplevel() const
QPointer< XdgPopupInterface > popup
void xdg_surface_get_popup(Resource *resource, uint32_t id, ::wl_resource *parent, ::wl_resource *positioner) override
void xdg_surface_get_toplevel(Resource *resource, uint32_t id) override
void xdg_surface_ack_configure(Resource *resource, uint32_t serial) override
void apply(XdgSurfaceCommit *commit)
XdgSurfaceInterfacePrivate(XdgSurfaceInterface *xdgSurface)
QPointer< XdgToplevelInterface > toplevel
void xdg_surface_set_window_geometry(Resource *resource, int32_t x, int32_t y, int32_t width, int32_t height) override
void xdg_surface_destroy(Resource *resource) override
void xdg_surface_destroy_resource(Resource *resource) override
XdgShellInterface * shell
QPointer< SurfaceInterface > surface
static XdgSurfaceInterfacePrivate * get(XdgSurfaceInterface *surface)
XdgSurfaceCommit * pending
void windowClassChanged(const QString &windowClass)
void windowMenuRequested(KWin::SeatInterface *seat, const QPoint &pos, quint32 serial)
XdgShellInterface * shell() const
void minimumSizeChanged(const QSize &size)
quint32 sendConfigure(const QSize &size, const States &states)
void unfullscreenRequested()
void windowTitleChanged(const QString &windowTitle)
XdgSurfaceInterface * xdgSurface() const
QSize maximumSize() const
static XdgToplevelInterface * get(::wl_resource *resource)
void fullscreenRequested(KWin::OutputInterface *output)
void maximumSizeChanged(const QSize &size)
void moveRequested(KWin::SeatInterface *seat, quint32 serial)
void aboutToBeDestroyed()
void parentXdgToplevelChanged()
QString windowTitle() const
static SurfaceRole * role()
SurfaceInterface * surface() const
void sendConfigureBounds(const QSize &size)
QSize minimumSize() const
XdgToplevelInterface(XdgSurfaceInterface *surface, ::wl_resource *resource)
void unmaximizeRequested()
QString windowClass() const
void sendWmCapabilities(Capabilities capabilities)
void initializeRequested()
XdgToplevelInterface * parentXdgToplevel() const
bool isConfigured() const
void resizeRequested(KWin::SeatInterface *seat, KWin::XdgToplevelInterface::ResizeAnchor anchor, quint32 serial)
~XdgToplevelInterface() override
void apply(XdgToplevelCommit *commit) override
void xdg_toplevel_set_max_size(Resource *resource, int32_t width, int32_t height) override
void xdg_toplevel_move(Resource *resource, ::wl_resource *seat, uint32_t serial) override
static XdgToplevelInterfacePrivate * get(XdgToplevelInterface *toplevel)
void xdg_toplevel_set_fullscreen(Resource *resource, ::wl_resource *output) override
void xdg_toplevel_destroy_resource(Resource *resource) override
void xdg_toplevel_set_min_size(Resource *resource, int32_t width, int32_t height) override
QPointer< XdgToplevelInterface > parentXdgToplevel
void xdg_toplevel_set_maximized(Resource *resource) override
void xdg_toplevel_set_title(Resource *resource, const QString &title) override
void xdg_toplevel_destroy(Resource *resource) override
void xdg_toplevel_show_window_menu(Resource *resource, ::wl_resource *seat, uint32_t serial, int32_t x, int32_t y) override
void xdg_toplevel_unset_maximized(Resource *resource) override
XdgSurfaceInterface * xdgSurface
void xdg_toplevel_set_minimized(Resource *resource) override
void xdg_toplevel_set_parent(Resource *resource, ::wl_resource *parent) override
void xdg_toplevel_unset_fullscreen(Resource *resource) override
void xdg_toplevel_resize(Resource *resource, ::wl_resource *seat, uint32_t serial, uint32_t edges) override
XdgToplevelInterfacePrivate(XdgToplevelInterface *toplevel, XdgSurfaceInterface *surface)
void xdg_toplevel_set_app_id(Resource *resource, const QString &app_id) override
QPointF popupOffset(const QRectF &anchorRect, const Qt::Edges anchorEdge, const Qt::Edges gravity, const QSizeF popupSize)
std::optional< quint32 > acknowledgedConfigure
std::optional< QRect > windowGeometry
std::optional< QSize > maximumSize
std::optional< QSize > minimumSize