6 #include "event_queue.h"
10 #include "wayland_pointer_p.h"
11 #include "xdgshell_p.h"
12 #include <wayland-xdg-shell-client-protocol.h>
18 class XdgShellStable::Private :
public XdgShell::Private
21 void setup(xdg_wm_base *shell)
override;
25 XdgShellSurface *getXdgSurface(Surface *surface,
QObject *
parent)
override;
27 XdgShellPopup *getXdgPopup(Surface *surface, XdgShellSurface *parentSurface,
const XdgPositioner &positioner,
QObject *
parent)
override;
28 XdgShellPopup *getXdgPopup(Surface *surface, XdgShellPopup *parentSurface,
const XdgPositioner &positioner,
QObject *
parent)
override;
30 using XdgShell::Private::operator xdg_shell *;
31 using XdgShell::Private::operator zxdg_shell_v6 *;
32 operator xdg_wm_base *()
override
34 return xdg_shell_base;
36 operator xdg_wm_base *()
const override
38 return xdg_shell_base;
42 XdgShellPopup *internalGetXdgPopup(Surface *surface, xdg_surface *parentSurface,
const XdgPositioner &positioner,
QObject *
parent);
43 static void pingCallback(
void *data,
struct xdg_wm_base *shell, uint32_t serial);
45 WaylandPointer<xdg_wm_base, xdg_wm_base_destroy> xdg_shell_base;
46 static const struct xdg_wm_base_listener s_shellListener;
49 const struct xdg_wm_base_listener XdgShellStable::Private::s_shellListener = {
53 void XdgShellStable::Private::pingCallback(
void *data,
struct xdg_wm_base *shell, uint32_t serial)
56 xdg_wm_base_pong(shell, serial);
59 void XdgShellStable::Private::setup(xdg_wm_base *shell)
62 Q_ASSERT(!xdg_shell_base);
63 xdg_shell_base.setup(shell);
64 xdg_wm_base_add_listener(shell, &s_shellListener,
this);
69 xdg_shell_base.release();
72 void XdgShellStable::Private::destroy()
74 xdg_shell_base.destroy();
77 bool XdgShellStable::Private::isValid()
const
79 return xdg_shell_base.isValid();
82 XdgShellSurface *XdgShellStable::Private::getXdgSurface(Surface *surface,
QObject *parent)
85 auto ss = xdg_wm_base_get_xdg_surface(xdg_shell_base, *surface);
91 auto s =
new XdgTopLevelStable(parent);
92 auto toplevel = xdg_surface_get_toplevel(ss);
95 queue->addProxy(toplevel);
97 s->setup(ss, toplevel);
101 XdgShellPopup *XdgShellStable::Private::getXdgPopup(Surface *surface, XdgShellSurface *parentSurface,
const XdgPositioner &positioner,
QObject *parent)
103 return internalGetXdgPopup(surface, *parentSurface, positioner, parent);
106 XdgShellPopup *XdgShellStable::Private::getXdgPopup(Surface *surface, XdgShellPopup *parentSurface,
const XdgPositioner &positioner,
QObject *parent)
108 return internalGetXdgPopup(surface, *parentSurface, positioner, parent);
111 XdgShellPopup *XdgShellStable::Private::internalGetXdgPopup(Surface *surface, xdg_surface *parentSurface,
const XdgPositioner &positioner,
QObject *parent)
114 auto ss = xdg_wm_base_get_xdg_surface(xdg_shell_base, *surface);
119 auto p = xdg_wm_base_create_positioner(xdg_shell_base);
121 auto anchorRect = positioner.anchorRect();
122 xdg_positioner_set_anchor_rect(p, anchorRect.x(), anchorRect.y(), anchorRect.width(), anchorRect.height());
124 QSize initialSize = positioner.initialSize();
125 xdg_positioner_set_size(p, initialSize.
width(), initialSize.
height());
127 QPoint anchorOffset = positioner.anchorOffset();
128 if (!anchorOffset.
isNull()) {
129 xdg_positioner_set_offset(p, anchorOffset.
x(), anchorOffset.
y());
132 uint32_t anchor = XDG_POSITIONER_ANCHOR_NONE;
133 if (positioner.anchorEdge().testFlag(
Qt::TopEdge)) {
135 anchor = XDG_POSITIONER_ANCHOR_TOP_LEFT;
137 anchor = XDG_POSITIONER_ANCHOR_TOP_RIGHT;
139 anchor = XDG_POSITIONER_ANCHOR_TOP;
143 anchor = XDG_POSITIONER_ANCHOR_BOTTOM_LEFT;
145 anchor = XDG_POSITIONER_ANCHOR_BOTTOM_RIGHT;
147 anchor = XDG_POSITIONER_ANCHOR_BOTTOM;
150 anchor = XDG_POSITIONER_ANCHOR_RIGHT;
152 anchor = XDG_POSITIONER_ANCHOR_LEFT;
155 xdg_positioner_set_anchor(p, anchor);
158 uint32_t gravity = XDG_POSITIONER_GRAVITY_NONE;
161 gravity = XDG_POSITIONER_GRAVITY_TOP_LEFT;
163 gravity = XDG_POSITIONER_GRAVITY_TOP_RIGHT;
165 gravity = XDG_POSITIONER_GRAVITY_TOP;
169 gravity = XDG_POSITIONER_GRAVITY_BOTTOM_LEFT;
171 gravity = XDG_POSITIONER_GRAVITY_BOTTOM_RIGHT;
173 gravity = XDG_POSITIONER_GRAVITY_BOTTOM;
176 gravity = XDG_POSITIONER_GRAVITY_RIGHT;
178 gravity = XDG_POSITIONER_GRAVITY_LEFT;
181 xdg_positioner_set_gravity(p, gravity);
184 uint32_t constraint = XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_NONE;
185 if (positioner.constraints().testFlag(XdgPositioner::Constraint::SlideX)) {
186 constraint |= XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_X;
188 if (positioner.constraints().testFlag(XdgPositioner::Constraint::SlideY)) {
189 constraint |= XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_Y;
191 if (positioner.constraints().testFlag(XdgPositioner::Constraint::FlipX)) {
192 constraint |= XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_X;
194 if (positioner.constraints().testFlag(XdgPositioner::Constraint::FlipY)) {
195 constraint |= XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_Y;
197 if (positioner.constraints().testFlag(XdgPositioner::Constraint::ResizeX)) {
198 constraint |= XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_X;
200 if (positioner.constraints().testFlag(XdgPositioner::Constraint::ResizeY)) {
201 constraint |= XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_Y;
203 if (constraint != 0) {
204 xdg_positioner_set_constraint_adjustment(p, constraint);
207 XdgShellPopup *s =
new XdgShellPopupStable(parent);
208 auto popup = xdg_surface_get_popup(ss, parentSurface, p);
212 queue->addProxy(popup);
216 xdg_positioner_destroy(p);
221 XdgShellStable::XdgShellStable(
QObject *parent)
222 : XdgShell(new Private, parent)
226 XdgShellStable::~XdgShellStable() =
default;
229 class XdgTopLevelStable::Private :
public XdgShellSurface::Private
232 Private(XdgShellSurface *q);
233 WaylandPointer<xdg_toplevel, xdg_toplevel_destroy> xdgtoplevel;
234 WaylandPointer<xdg_surface, xdg_surface_destroy> xdgsurface;
236 void setup(xdg_surface *surface, xdg_toplevel *toplevel)
override;
238 void destroy()
override;
241 using XdgShellSurface::Private::operator zxdg_toplevel_v6 *;
242 using XdgShellSurface::Private::operator zxdg_surface_v6 *;
243 operator xdg_surface *()
override
247 operator xdg_surface *()
const override
251 operator xdg_toplevel *()
override
255 operator xdg_toplevel *()
const override
260 void setTransientFor(XdgShellSurface *parent)
override;
261 void setTitle(
const QString &title)
override;
262 void setAppId(
const QByteArray &appId)
override;
263 void showWindowMenu(Seat *seat, quint32 serial, qint32 x, qint32 y)
override;
264 void move(Seat *seat, quint32 serial)
override;
265 void resize(Seat *seat, quint32 serial,
Qt::Edges edges)
override;
266 void ackConfigure(quint32 serial)
override;
267 void setMaximized()
override;
268 void unsetMaximized()
override;
269 void setFullscreen(Output *output)
override;
270 void unsetFullscreen()
override;
271 void setMinimized()
override;
272 void setMaxSize(
const QSize &size)
override;
273 void setMinSize(
const QSize &size)
override;
274 void setWindowGeometry(
const QRect &windowGeometry)
override;
280 static void configureCallback(
void *data,
struct xdg_toplevel *xdg_toplevel, int32_t width, int32_t height,
struct wl_array *state);
281 static void closeCallback(
void *data, xdg_toplevel *xdg_toplevel);
282 static void surfaceConfigureCallback(
void *data, xdg_surface *xdg_surface, uint32_t serial);
284 static const struct xdg_toplevel_listener s_toplevelListener;
285 static const struct xdg_surface_listener s_surfaceListener;
288 const struct xdg_toplevel_listener XdgTopLevelStable::Private::s_toplevelListener = {configureCallback, closeCallback};
290 const struct xdg_surface_listener XdgTopLevelStable::Private::s_surfaceListener = {surfaceConfigureCallback};
292 void XdgTopLevelStable::Private::surfaceConfigureCallback(
void *data,
struct xdg_surface *surface, uint32_t serial)
295 auto s =
static_cast<Private *
>(data);
296 s->q->configureRequested(s->pendingSize, s->pendingState, serial);
297 if (!s->pendingSize.isNull()) {
298 s->q->setSize(s->pendingSize);
299 s->pendingSize =
QSize();
301 s->pendingState = {};
304 void XdgTopLevelStable::Private::configureCallback(
void *data,
struct xdg_toplevel *xdg_toplevel, int32_t width, int32_t height,
struct wl_array *state)
306 Q_UNUSED(xdg_toplevel)
307 auto s =
static_cast<Private *
>(data);
310 uint32_t *statePtr =
static_cast<uint32_t *
>(state->data);
311 for (
size_t i = 0; i < state->size /
sizeof(uint32_t); i++) {
312 switch (statePtr[i]) {
313 case XDG_TOPLEVEL_STATE_MAXIMIZED:
314 states = states | XdgShellSurface::State::Maximized;
316 case XDG_TOPLEVEL_STATE_FULLSCREEN:
317 states = states | XdgShellSurface::State::Fullscreen;
319 case XDG_TOPLEVEL_STATE_RESIZING:
320 states = states | XdgShellSurface::State::Resizing;
322 case XDG_TOPLEVEL_STATE_ACTIVATED:
323 states = states | XdgShellSurface::State::Activated;
327 s->pendingSize =
QSize(width, height);
328 s->pendingState = states;
331 void XdgTopLevelStable::Private::closeCallback(
void *data, xdg_toplevel *xdg_toplevel)
333 auto s =
static_cast<XdgTopLevelStable::Private *
>(data);
334 Q_ASSERT(s->xdgtoplevel == xdg_toplevel);
335 Q_EMIT s->q->closeRequested();
338 XdgTopLevelStable::Private::Private(XdgShellSurface *q)
339 : XdgShellSurface::Private(q)
343 void XdgTopLevelStable::Private::setup(xdg_surface *surface, xdg_toplevel *topLevel)
346 Q_ASSERT(!xdgtoplevel);
347 xdgsurface.setup(surface);
348 xdgtoplevel.setup(topLevel);
349 xdg_surface_add_listener(xdgsurface, &s_surfaceListener,
this);
350 xdg_toplevel_add_listener(xdgtoplevel, &s_toplevelListener,
this);
355 xdgtoplevel.release();
356 xdgsurface.release();
359 void XdgTopLevelStable::Private::destroy()
361 xdgtoplevel.destroy();
362 xdgsurface.destroy();
365 bool XdgTopLevelStable::Private::isValid()
const
367 return xdgtoplevel.isValid() && xdgsurface.isValid();
370 void XdgTopLevelStable::Private::setTransientFor(XdgShellSurface *parent)
372 xdg_toplevel *parentSurface =
nullptr;
374 parentSurface = *parent;
376 xdg_toplevel_set_parent(xdgtoplevel, parentSurface);
379 void XdgTopLevelStable::Private::setTitle(
const QString &title)
384 void XdgTopLevelStable::Private::setAppId(
const QByteArray &appId)
386 xdg_toplevel_set_app_id(xdgtoplevel, appId.
constData());
389 void XdgTopLevelStable::Private::showWindowMenu(Seat *seat, quint32 serial, qint32 x, qint32 y)
391 xdg_toplevel_show_window_menu(xdgtoplevel, *seat, serial, x, y);
394 void XdgTopLevelStable::Private::move(Seat *seat, quint32 serial)
396 xdg_toplevel_move(xdgtoplevel, *seat, serial);
399 void XdgTopLevelStable::Private::resize(Seat *seat, quint32 serial,
Qt::Edges edges)
401 uint wlEdge = XDG_TOPLEVEL_RESIZE_EDGE_NONE;
404 wlEdge = XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT;
406 wlEdge = XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT;
408 wlEdge = XDG_TOPLEVEL_RESIZE_EDGE_TOP;
412 wlEdge = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_LEFT;
414 wlEdge = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT;
416 wlEdge = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM;
419 wlEdge = XDG_TOPLEVEL_RESIZE_EDGE_RIGHT;
421 wlEdge = XDG_TOPLEVEL_RESIZE_EDGE_LEFT;
423 xdg_toplevel_resize(xdgtoplevel, *seat, serial, wlEdge);
426 void XdgTopLevelStable::Private::ackConfigure(quint32 serial)
428 xdg_surface_ack_configure(xdgsurface, serial);
431 void XdgTopLevelStable::Private::setMaximized()
433 xdg_toplevel_set_maximized(xdgtoplevel);
436 void XdgTopLevelStable::Private::unsetMaximized()
438 xdg_toplevel_unset_maximized(xdgtoplevel);
441 void XdgTopLevelStable::Private::setFullscreen(Output *output)
443 wl_output *o =
nullptr;
447 xdg_toplevel_set_fullscreen(xdgtoplevel, o);
450 void XdgTopLevelStable::Private::unsetFullscreen()
452 xdg_toplevel_unset_fullscreen(xdgtoplevel);
455 void XdgTopLevelStable::Private::setMinimized()
457 xdg_toplevel_set_minimized(xdgtoplevel);
460 void XdgTopLevelStable::Private::setMaxSize(
const QSize &size)
462 xdg_toplevel_set_max_size(xdgtoplevel, size.
width(), size.
height());
465 void XdgTopLevelStable::Private::setMinSize(
const QSize &size)
467 xdg_toplevel_set_min_size(xdgtoplevel, size.
width(), size.
height());
470 void XdgTopLevelStable::Private::setWindowGeometry(
const QRect &windowGeometry)
472 xdg_surface_set_window_geometry(xdgsurface, windowGeometry.
x(), windowGeometry.
y(), windowGeometry.
width(), windowGeometry.
height());
475 XdgTopLevelStable::XdgTopLevelStable(
QObject *parent)
476 : XdgShellSurface(new Private(this), parent)
480 XdgTopLevelStable::~XdgTopLevelStable() =
default;
482 class XdgShellPopupStable::Private :
public XdgShellPopup::Private
485 Private(XdgShellPopup *q);
487 void setup(xdg_surface *s, xdg_popup *p)
override;
489 void destroy()
override;
491 void requestGrab(Seat *seat, quint32 serial)
override;
492 void ackConfigure(quint32 serial)
override;
493 void setWindowGeometry(
const QRect &windowGeometry)
override;
495 using XdgShellPopup::Private::operator zxdg_popup_v6 *;
496 using XdgShellPopup::Private::operator zxdg_surface_v6 *;
497 operator xdg_surface *()
override
501 operator xdg_surface *()
const override
505 operator xdg_popup *()
override
509 operator xdg_popup *()
const override
513 WaylandPointer<xdg_surface, xdg_surface_destroy> xdgsurface;
514 WaylandPointer<xdg_popup, xdg_popup_destroy> xdgpopup;
519 static void configureCallback(
void *data, xdg_popup *xdg_popup, int32_t x, int32_t y, int32_t width, int32_t height);
520 static void popupDoneCallback(
void *data, xdg_popup *xdg_popup);
521 static void surfaceConfigureCallback(
void *data, xdg_surface *xdg_surface, uint32_t serial);
523 static const struct xdg_popup_listener s_popupListener;
524 static const struct xdg_surface_listener s_surfaceListener;
527 const struct xdg_popup_listener XdgShellPopupStable::Private::s_popupListener = {configureCallback, popupDoneCallback};
529 const struct xdg_surface_listener XdgShellPopupStable::Private::s_surfaceListener = {
530 surfaceConfigureCallback,
533 void XdgShellPopupStable::Private::configureCallback(
void *data, xdg_popup *xdg_popup, int32_t x, int32_t y, int32_t width, int32_t height)
536 auto s =
static_cast<Private *
>(data);
537 s->pendingRect =
QRect(x, y, width, height);
540 void XdgShellPopupStable::Private::surfaceConfigureCallback(
void *data,
struct xdg_surface *surface, uint32_t serial)
543 auto s =
static_cast<Private *
>(data);
544 s->q->configureRequested(s->pendingRect, serial);
545 s->pendingRect =
QRect();
548 void XdgShellPopupStable::Private::popupDoneCallback(
void *data, xdg_popup *xdg_popup)
550 auto s =
static_cast<XdgShellPopupStable::Private *
>(data);
551 Q_ASSERT(s->xdgpopup == xdg_popup);
552 Q_EMIT s->q->popupDone();
555 XdgShellPopupStable::Private::Private(XdgShellPopup *q)
556 : XdgShellPopup::Private(q)
560 void XdgShellPopupStable::Private::setup(xdg_surface *s, xdg_popup *p)
563 Q_ASSERT(!xdgsurface);
568 xdg_surface_add_listener(xdgsurface, &s_surfaceListener,
this);
569 xdg_popup_add_listener(xdgpopup, &s_popupListener,
this);
577 void XdgShellPopupStable::Private::destroy()
582 bool XdgShellPopupStable::Private::isValid()
const
584 return xdgpopup.isValid();
587 void XdgShellPopupStable::Private::requestGrab(Seat *seat, quint32 serial)
589 xdg_popup_grab(xdgpopup, *seat, serial);
592 void XdgShellPopupStable::Private::ackConfigure(quint32 serial)
594 xdg_surface_ack_configure(xdgsurface, serial);
597 void XdgShellPopupStable::Private::setWindowGeometry(
const QRect &windowGeometry)
599 xdg_surface_set_window_geometry(xdgsurface, windowGeometry.
x(), windowGeometry.
y(), windowGeometry.
width(), windowGeometry.
height());
602 XdgShellPopupStable::XdgShellPopupStable(
QObject *parent)
603 : XdgShellPopup(new Private(this), parent)
607 XdgShellPopupStable::~XdgShellPopupStable() =
default;