diff --git a/src/client/xdgshell_stable.cpp b/src/client/xdgshell_stable.cpp index 0c37c84..146a9b6 100644 --- a/src/client/xdgshell_stable.cpp +++ b/src/client/xdgshell_stable.cpp @@ -1,624 +1,624 @@ /**************************************************************************** Copyright 2017 David Edmundson This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . ****************************************************************************/ #include "xdgshell_p.h" #include "event_queue.h" #include "output.h" #include "seat.h" #include "surface.h" #include "wayland_pointer_p.h" #include namespace KWayland { namespace Client { class XdgShellStable::Private : public XdgShell::Private { public: void setup(xdg_wm_base *shell) override; void release() override; void destroy() override; bool isValid() const override; XdgShellSurface *getXdgSurface(Surface *surface, QObject *parent) override; XdgShellPopup *getXdgPopup(Surface *surface, XdgShellSurface *parentSurface, const XdgPositioner &positioner, QObject *parent) override; XdgShellPopup *getXdgPopup(Surface *surface, XdgShellPopup *parentSurface, const XdgPositioner &positioner, QObject *parent) override; using XdgShell::Private::operator xdg_shell*; using XdgShell::Private::operator zxdg_shell_v6*; operator xdg_wm_base*() override { return xdg_shell_base; } operator xdg_wm_base*() const override { return xdg_shell_base; } private: XdgShellPopup *internalGetXdgPopup(Surface *surface, xdg_surface *parentSurface, const XdgPositioner &positioner, QObject *parent); static void pingCallback(void *data, struct xdg_wm_base *shell, uint32_t serial); WaylandPointer xdg_shell_base; static const struct xdg_wm_base_listener s_shellListener; }; const struct xdg_wm_base_listener XdgShellStable::Private::s_shellListener = { pingCallback, }; void XdgShellStable::Private::pingCallback(void *data, struct xdg_wm_base *shell, uint32_t serial) { Q_UNUSED(data) xdg_wm_base_pong(shell, serial); } void XdgShellStable::Private::setup(xdg_wm_base *shell) { Q_ASSERT(shell); Q_ASSERT(!xdg_shell_base); xdg_shell_base.setup(shell); xdg_wm_base_add_listener(shell, &s_shellListener, this); } void XdgShellStable::Private::release() { xdg_shell_base.release(); } void XdgShellStable::Private::destroy() { xdg_shell_base.destroy(); } bool XdgShellStable::Private::isValid() const { return xdg_shell_base.isValid(); } XdgShellSurface *XdgShellStable::Private::getXdgSurface(Surface *surface, QObject *parent) { Q_ASSERT(isValid()); auto ss = xdg_wm_base_get_xdg_surface(xdg_shell_base, *surface); if (!ss) { return nullptr; } auto s = new XdgTopLevelStable(parent); auto toplevel = xdg_surface_get_toplevel(ss); if (queue) { queue->addProxy(ss); queue->addProxy(toplevel); } s->setup(ss, toplevel); return s; } XdgShellPopup *XdgShellStable::Private::getXdgPopup(Surface *surface, XdgShellSurface *parentSurface, const XdgPositioner &positioner, QObject *parent) { return internalGetXdgPopup(surface, *parentSurface, positioner, parent); } XdgShellPopup *XdgShellStable::Private::getXdgPopup(Surface *surface, XdgShellPopup *parentSurface, const XdgPositioner &positioner, QObject *parent) { return internalGetXdgPopup(surface, *parentSurface, positioner, parent); } XdgShellPopup *XdgShellStable::Private::internalGetXdgPopup(Surface *surface, xdg_surface *parentSurface, const XdgPositioner &positioner, QObject *parent) { Q_ASSERT(isValid()); auto ss = xdg_wm_base_get_xdg_surface(xdg_shell_base, *surface); if (!ss) { return nullptr; } auto p = xdg_wm_base_create_positioner(xdg_shell_base); auto anchorRect = positioner.anchorRect(); xdg_positioner_set_anchor_rect(p, anchorRect.x(), anchorRect.y(), anchorRect.width(), anchorRect.height()); QSize initialSize = positioner.initialSize(); xdg_positioner_set_size(p, initialSize.width(), initialSize.height()); QPoint anchorOffset = positioner.anchorOffset(); if (!anchorOffset.isNull()) { xdg_positioner_set_offset(p, anchorOffset.x(), anchorOffset.y()); } uint32_t anchor = XDG_POSITIONER_ANCHOR_NONE; if (positioner.anchorEdge().testFlag(Qt::TopEdge)) { if (positioner.anchorEdge().testFlag(Qt::LeftEdge) && ((positioner.anchorEdge() & ~Qt::LeftEdge) == Qt::TopEdge)) { anchor = XDG_POSITIONER_ANCHOR_TOP_LEFT; } else if (positioner.anchorEdge().testFlag(Qt::RightEdge) && ((positioner.anchorEdge() & ~Qt::RightEdge) == Qt::TopEdge)) { anchor = XDG_POSITIONER_ANCHOR_TOP_RIGHT; } else if ((positioner.anchorEdge() & ~Qt::TopEdge) == Qt::Edges()) { anchor = XDG_POSITIONER_ANCHOR_TOP; } } else if (positioner.anchorEdge().testFlag(Qt::BottomEdge)) { if (positioner.anchorEdge().testFlag(Qt::LeftEdge) && ((positioner.anchorEdge() & ~Qt::LeftEdge) == Qt::BottomEdge)) { anchor = XDG_POSITIONER_ANCHOR_BOTTOM_LEFT; } else if (positioner.anchorEdge().testFlag(Qt::RightEdge) && ((positioner.anchorEdge() & ~Qt::RightEdge) == Qt::BottomEdge)) { anchor = XDG_POSITIONER_ANCHOR_BOTTOM_RIGHT; } else if ((positioner.anchorEdge() & ~Qt::BottomEdge) == Qt::Edges()) { anchor = XDG_POSITIONER_ANCHOR_BOTTOM; } } else if (positioner.anchorEdge().testFlag(Qt::RightEdge) && ((positioner.anchorEdge() & ~Qt::RightEdge) == Qt::Edges())) { anchor = XDG_POSITIONER_ANCHOR_RIGHT; } else if (positioner.anchorEdge().testFlag(Qt::LeftEdge) && ((positioner.anchorEdge() & ~Qt::LeftEdge) == Qt::Edges())) { anchor = XDG_POSITIONER_ANCHOR_LEFT; } if (anchor != 0) { xdg_positioner_set_anchor(p, anchor); } uint32_t gravity = XDG_POSITIONER_GRAVITY_NONE; if (positioner.gravity().testFlag(Qt::TopEdge)) { if (positioner.gravity().testFlag(Qt::LeftEdge) && ((positioner.gravity() & ~Qt::LeftEdge) == Qt::TopEdge)) { gravity = XDG_POSITIONER_GRAVITY_TOP_LEFT; } else if (positioner.gravity().testFlag(Qt::RightEdge) && ((positioner.gravity() & ~Qt::RightEdge) == Qt::TopEdge)) { gravity = XDG_POSITIONER_GRAVITY_TOP_RIGHT; } else if ((positioner.gravity() & ~Qt::TopEdge) == Qt::Edges()) { gravity = XDG_POSITIONER_GRAVITY_TOP; } } else if (positioner.gravity().testFlag(Qt::BottomEdge)) { if (positioner.gravity().testFlag(Qt::LeftEdge) && ((positioner.gravity() & ~Qt::LeftEdge) == Qt::BottomEdge)) { gravity = XDG_POSITIONER_GRAVITY_BOTTOM_LEFT; } else if (positioner.gravity().testFlag(Qt::RightEdge) && ((positioner.gravity() & ~Qt::RightEdge) == Qt::BottomEdge)) { gravity = XDG_POSITIONER_GRAVITY_BOTTOM_RIGHT; } else if ((positioner.gravity() & ~Qt::BottomEdge) == Qt::Edges()) { gravity = XDG_POSITIONER_GRAVITY_BOTTOM; } } else if (positioner.gravity().testFlag(Qt::RightEdge) && ((positioner.gravity() & ~Qt::RightEdge) == Qt::Edges())) { gravity = XDG_POSITIONER_GRAVITY_RIGHT; } else if (positioner.gravity().testFlag(Qt::LeftEdge) && ((positioner.gravity() & ~Qt::LeftEdge) == Qt::Edges())) { gravity = XDG_POSITIONER_GRAVITY_LEFT; } if (gravity != 0) { xdg_positioner_set_gravity(p, gravity); } uint32_t constraint = XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_NONE; if (positioner.constraints().testFlag(XdgPositioner::Constraint::SlideX)) { constraint |= XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_X; } if (positioner.constraints().testFlag(XdgPositioner::Constraint::SlideY)) { constraint |= XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_Y; } if (positioner.constraints().testFlag(XdgPositioner::Constraint::FlipX)) { constraint |= XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_X; } if (positioner.constraints().testFlag(XdgPositioner::Constraint::FlipY)) { constraint |= XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_Y; } if (positioner.constraints().testFlag(XdgPositioner::Constraint::ResizeX)) { constraint |= XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_X; } if (positioner.constraints().testFlag(XdgPositioner::Constraint::ResizeY)) { constraint |= XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_Y; } if (constraint != 0) { xdg_positioner_set_constraint_adjustment(p, constraint); } XdgShellPopup *s = new XdgShellPopupStable(parent); auto popup = xdg_surface_get_popup(ss, parentSurface, p); if (queue) { //deliberately not adding the positioner because the positioner has no events sent to it queue->addProxy(ss); queue->addProxy(popup); } s->setup(ss, popup); xdg_positioner_destroy(p); return s; } XdgShellStable::XdgShellStable(QObject *parent) : XdgShell(new Private, parent) { } XdgShellStable::~XdgShellStable() = default; //A top level wraps both xdg_surface and xdg_top_level into the public API XdgShelllSurface class XdgTopLevelStable::Private : public XdgShellSurface::Private { public: Private(XdgShellSurface *q); WaylandPointer xdgtoplevel; WaylandPointer xdgsurface; void setup(xdg_surface *surface, xdg_toplevel *toplevel) override; void release() override; void destroy() override; bool isValid() const override; using XdgShellSurface::Private::operator zxdg_toplevel_v6*; using XdgShellSurface::Private::operator zxdg_surface_v6*; operator xdg_surface*() override { return xdgsurface; } operator xdg_surface*() const override { return xdgsurface; } operator xdg_toplevel*() override { return xdgtoplevel; } operator xdg_toplevel*() const override { return xdgtoplevel; } void setTransientFor(XdgShellSurface *parent) override; void setTitle(const QString &title) override; void setAppId(const QByteArray &appId) override; void showWindowMenu(Seat *seat, quint32 serial, qint32 x, qint32 y) override; void move(Seat *seat, quint32 serial) override; void resize(Seat *seat, quint32 serial, Qt::Edges edges) override; void ackConfigure(quint32 serial) override; void setMaximized() override; void unsetMaximized() override; void setFullscreen(Output *output) override; void unsetFullscreen() override; void setMinimized() override; void setMaxSize(const QSize &size) override; void setMinSize(const QSize &size) override; void setWindowGeometry(const QRect &windowGeometry) override; private: QSize pendingSize; States pendingState; static void configureCallback(void *data, struct xdg_toplevel *xdg_toplevel, int32_t width, int32_t height, struct wl_array *state); static void closeCallback(void *data, xdg_toplevel *xdg_toplevel); static void surfaceConfigureCallback(void *data, xdg_surface *xdg_surface, uint32_t serial); static const struct xdg_toplevel_listener s_toplevelListener; static const struct xdg_surface_listener s_surfaceListener; }; const struct xdg_toplevel_listener XdgTopLevelStable::Private::s_toplevelListener = { configureCallback, closeCallback }; const struct xdg_surface_listener XdgTopLevelStable::Private::s_surfaceListener = { surfaceConfigureCallback }; void XdgTopLevelStable::Private::surfaceConfigureCallback(void *data, struct xdg_surface *surface, uint32_t serial) { Q_UNUSED(surface) auto s = static_cast(data); s->q->configureRequested(s->pendingSize, s->pendingState, serial); if (!s->pendingSize.isNull()) { s->q->setSize(s->pendingSize); s->pendingSize = QSize(); } - s->pendingState = nullptr; + s->pendingState = {}; } void XdgTopLevelStable::Private::configureCallback(void *data, struct xdg_toplevel *xdg_toplevel, int32_t width, int32_t height, struct wl_array *state) { Q_UNUSED(xdg_toplevel) auto s = static_cast(data); States states; uint32_t *statePtr = static_cast(state->data); for (size_t i = 0; i < state->size / sizeof(uint32_t); i++) { switch (statePtr[i]) { case XDG_TOPLEVEL_STATE_MAXIMIZED: states = states | XdgShellSurface::State::Maximized; break; case XDG_TOPLEVEL_STATE_FULLSCREEN: states = states | XdgShellSurface::State::Fullscreen; break; case XDG_TOPLEVEL_STATE_RESIZING: states = states | XdgShellSurface::State::Resizing; break; case XDG_TOPLEVEL_STATE_ACTIVATED: states = states | XdgShellSurface::State::Activated; break; } } s->pendingSize = QSize(width, height); s->pendingState = states; } void XdgTopLevelStable::Private::closeCallback(void *data, xdg_toplevel *xdg_toplevel) { auto s = static_cast(data); Q_ASSERT(s->xdgtoplevel == xdg_toplevel); emit s->q->closeRequested(); } XdgTopLevelStable::Private::Private(XdgShellSurface *q) : XdgShellSurface::Private(q) { } void XdgTopLevelStable::Private::setup(xdg_surface *surface, xdg_toplevel *topLevel) { Q_ASSERT(surface); Q_ASSERT(!xdgtoplevel); xdgsurface.setup(surface); xdgtoplevel.setup(topLevel); xdg_surface_add_listener(xdgsurface, &s_surfaceListener, this); xdg_toplevel_add_listener(xdgtoplevel, &s_toplevelListener, this); } void XdgTopLevelStable::Private::release() { xdgtoplevel.release(); xdgsurface.release(); } void XdgTopLevelStable::Private::destroy() { xdgtoplevel.destroy(); xdgsurface.destroy(); } bool XdgTopLevelStable::Private::isValid() const { return xdgtoplevel.isValid() && xdgsurface.isValid(); } void XdgTopLevelStable::Private::setTransientFor(XdgShellSurface *parent) { xdg_toplevel *parentSurface = nullptr; if (parent) { parentSurface = *parent; } xdg_toplevel_set_parent(xdgtoplevel, parentSurface); } void XdgTopLevelStable::Private::setTitle(const QString & title) { xdg_toplevel_set_title(xdgtoplevel, title.toUtf8().constData()); } void XdgTopLevelStable::Private::setAppId(const QByteArray & appId) { xdg_toplevel_set_app_id(xdgtoplevel, appId.constData()); } void XdgTopLevelStable::Private::showWindowMenu(Seat *seat, quint32 serial, qint32 x, qint32 y) { xdg_toplevel_show_window_menu(xdgtoplevel, *seat, serial, x, y); } void XdgTopLevelStable::Private::move(Seat *seat, quint32 serial) { xdg_toplevel_move(xdgtoplevel, *seat, serial); } void XdgTopLevelStable::Private::resize(Seat *seat, quint32 serial, Qt::Edges edges) { uint wlEdge = XDG_TOPLEVEL_RESIZE_EDGE_NONE; if (edges.testFlag(Qt::TopEdge)) { if (edges.testFlag(Qt::LeftEdge) && ((edges & ~Qt::LeftEdge) == Qt::TopEdge)) { wlEdge = XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT; } else if (edges.testFlag(Qt::RightEdge) && ((edges & ~Qt::RightEdge) == Qt::TopEdge)) { wlEdge = XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT; } else if ((edges & ~Qt::TopEdge) == Qt::Edges()) { wlEdge = XDG_TOPLEVEL_RESIZE_EDGE_TOP; } } else if (edges.testFlag(Qt::BottomEdge)) { if (edges.testFlag(Qt::LeftEdge) && ((edges & ~Qt::LeftEdge) == Qt::BottomEdge)) { wlEdge = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_LEFT; } else if (edges.testFlag(Qt::RightEdge) && ((edges & ~Qt::RightEdge) == Qt::BottomEdge)) { wlEdge = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT; } else if ((edges & ~Qt::BottomEdge) == Qt::Edges()) { wlEdge = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM; } } else if (edges.testFlag(Qt::RightEdge) && ((edges & ~Qt::RightEdge) == Qt::Edges())) { wlEdge = XDG_TOPLEVEL_RESIZE_EDGE_RIGHT; } else if (edges.testFlag(Qt::LeftEdge) && ((edges & ~Qt::LeftEdge) == Qt::Edges())) { wlEdge = XDG_TOPLEVEL_RESIZE_EDGE_LEFT; } xdg_toplevel_resize(xdgtoplevel, *seat, serial, wlEdge); } void XdgTopLevelStable::Private::ackConfigure(quint32 serial) { xdg_surface_ack_configure(xdgsurface, serial); } void XdgTopLevelStable::Private::setMaximized() { xdg_toplevel_set_maximized(xdgtoplevel); } void XdgTopLevelStable::Private::unsetMaximized() { xdg_toplevel_unset_maximized(xdgtoplevel); } void XdgTopLevelStable::Private::setFullscreen(Output *output) { wl_output *o = nullptr; if (output) { o = *output; } xdg_toplevel_set_fullscreen(xdgtoplevel, o); } void XdgTopLevelStable::Private::unsetFullscreen() { xdg_toplevel_unset_fullscreen(xdgtoplevel); } void XdgTopLevelStable::Private::setMinimized() { xdg_toplevel_set_minimized(xdgtoplevel); } void XdgTopLevelStable::Private::setMaxSize(const QSize &size) { xdg_toplevel_set_max_size(xdgtoplevel, size.width(), size.height()); } void XdgTopLevelStable::Private::setMinSize(const QSize &size) { xdg_toplevel_set_min_size(xdgtoplevel, size.width(), size.height()); } void XdgTopLevelStable::Private::setWindowGeometry(const QRect &windowGeometry) { xdg_surface_set_window_geometry(xdgsurface, windowGeometry.x(), windowGeometry.y(), windowGeometry.width(), windowGeometry.height()); } XdgTopLevelStable::XdgTopLevelStable(QObject *parent) : XdgShellSurface(new Private(this), parent) { } XdgTopLevelStable::~XdgTopLevelStable() = default; class XdgShellPopupStable::Private : public XdgShellPopup::Private { public: Private(XdgShellPopup *q); void setup(xdg_surface *s, xdg_popup *p) override; void release() override; void destroy() override; bool isValid() const override; void requestGrab(Seat *seat, quint32 serial) override; void ackConfigure(quint32 serial) override; void setWindowGeometry(const QRect &windowGeometry) override; using XdgShellPopup::Private::operator zxdg_popup_v6*; using XdgShellPopup::Private::operator zxdg_surface_v6*; operator xdg_surface*() override { return xdgsurface; } operator xdg_surface*() const override { return xdgsurface; } operator xdg_popup*() override { return xdgpopup; } operator xdg_popup*() const override { return xdgpopup; } WaylandPointer xdgsurface; WaylandPointer xdgpopup; QRect pendingRect; private: static void configureCallback(void *data, xdg_popup *xdg_popup, int32_t x, int32_t y, int32_t width, int32_t height); static void popupDoneCallback(void *data, xdg_popup *xdg_popup); static void surfaceConfigureCallback(void *data, xdg_surface *xdg_surface, uint32_t serial); static const struct xdg_popup_listener s_popupListener; static const struct xdg_surface_listener s_surfaceListener; }; const struct xdg_popup_listener XdgShellPopupStable::Private::s_popupListener = { configureCallback, popupDoneCallback }; const struct xdg_surface_listener XdgShellPopupStable::Private::s_surfaceListener = { surfaceConfigureCallback, }; void XdgShellPopupStable::Private::configureCallback(void *data, xdg_popup *xdg_popup, int32_t x, int32_t y, int32_t width, int32_t height) { Q_UNUSED(xdg_popup) auto s = static_cast(data); s->pendingRect = QRect(x, y, width, height); } void XdgShellPopupStable::Private::surfaceConfigureCallback(void *data, struct xdg_surface *surface, uint32_t serial) { Q_UNUSED(surface) auto s = static_cast(data); s->q->configureRequested(s->pendingRect, serial); s->pendingRect = QRect(); } void XdgShellPopupStable::Private::popupDoneCallback(void *data, xdg_popup *xdg_popup) { auto s = static_cast(data); Q_ASSERT(s->xdgpopup == xdg_popup); emit s->q->popupDone(); } XdgShellPopupStable::Private::Private(XdgShellPopup *q) : XdgShellPopup::Private(q) { } void XdgShellPopupStable::Private::setup(xdg_surface *s, xdg_popup *p) { Q_ASSERT(p); Q_ASSERT(!xdgsurface); Q_ASSERT(!xdgpopup); xdgsurface.setup(s); xdgpopup.setup(p); xdg_surface_add_listener(xdgsurface, &s_surfaceListener, this); xdg_popup_add_listener(xdgpopup, &s_popupListener, this); } void XdgShellPopupStable::Private::release() { xdgpopup.release(); } void XdgShellPopupStable::Private::destroy() { xdgpopup.destroy(); } bool XdgShellPopupStable::Private::isValid() const { return xdgpopup.isValid(); } void XdgShellPopupStable::Private::requestGrab(Seat *seat, quint32 serial) { xdg_popup_grab(xdgpopup, *seat, serial); } void XdgShellPopupStable::Private::ackConfigure(quint32 serial) { xdg_surface_ack_configure(xdgsurface, serial); } void XdgShellPopupStable::Private::setWindowGeometry(const QRect &windowGeometry) { xdg_surface_set_window_geometry(xdgsurface, windowGeometry.x(), windowGeometry.y(), windowGeometry.width(), windowGeometry.height()); } XdgShellPopupStable::XdgShellPopupStable(QObject *parent) : XdgShellPopup(new Private(this), parent) { } XdgShellPopupStable::~XdgShellPopupStable() = default; } } diff --git a/src/client/xdgshell_v6.cpp b/src/client/xdgshell_v6.cpp index 58cd44c..3d3aae4 100644 --- a/src/client/xdgshell_v6.cpp +++ b/src/client/xdgshell_v6.cpp @@ -1,597 +1,597 @@ /**************************************************************************** Copyright 2017 David Edmundson This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . ****************************************************************************/ #include "xdgshell_p.h" #include "event_queue.h" #include "output.h" #include "seat.h" #include "surface.h" #include "wayland_pointer_p.h" #include #include namespace KWayland { namespace Client { class XdgShellUnstableV6::Private : public XdgShell::Private { public: void setupV6(zxdg_shell_v6 *shell) override; void release() override; void destroy() override; bool isValid() const override; XdgShellSurface *getXdgSurface(Surface *surface, QObject *parent) override; XdgShellPopup *getXdgPopup(Surface *surface, XdgShellSurface *parentSurface, const XdgPositioner &positioner, QObject *parent) override; XdgShellPopup *getXdgPopup(Surface *surface, XdgShellPopup *parentSurface, const XdgPositioner &positioner, QObject *parent) override; using XdgShell::Private::operator xdg_wm_base*; using XdgShell::Private::operator xdg_shell*; operator zxdg_shell_v6*() override { return xdgshellv6; } operator zxdg_shell_v6*() const override { return xdgshellv6; } private: XdgShellPopup *internalGetXdgPopup(Surface *surface, zxdg_surface_v6 *parentSurface, const XdgPositioner &positioner, QObject *parent); static void pingCallback(void *data, struct zxdg_shell_v6 *shell, uint32_t serial); WaylandPointer xdgshellv6; static const struct zxdg_shell_v6_listener s_shellListener; }; const struct zxdg_shell_v6_listener XdgShellUnstableV6::Private::s_shellListener = { pingCallback, }; void XdgShellUnstableV6::Private::pingCallback(void *data, struct zxdg_shell_v6 *shell, uint32_t serial) { Q_UNUSED(data) zxdg_shell_v6_pong(shell, serial); } void XdgShellUnstableV6::Private::setupV6(zxdg_shell_v6 *shell) { Q_ASSERT(shell); Q_ASSERT(!xdgshellv6); xdgshellv6.setup(shell); zxdg_shell_v6_add_listener(shell, &s_shellListener, this); } void XdgShellUnstableV6::Private::release() { xdgshellv6.release(); } void XdgShellUnstableV6::Private::destroy() { xdgshellv6.destroy(); } bool XdgShellUnstableV6::Private::isValid() const { return xdgshellv6.isValid(); } XdgShellSurface *XdgShellUnstableV6::Private::getXdgSurface(Surface *surface, QObject *parent) { Q_ASSERT(isValid()); auto ss = zxdg_shell_v6_get_xdg_surface(xdgshellv6, *surface); if (!ss) { return nullptr; } auto s = new XdgTopLevelUnstableV6(parent); auto toplevel = zxdg_surface_v6_get_toplevel(ss); if (queue) { queue->addProxy(ss); queue->addProxy(toplevel); } s->setup(ss, toplevel); return s; } XdgShellPopup *XdgShellUnstableV6::Private::getXdgPopup(Surface *surface, XdgShellSurface *parentSurface, const XdgPositioner &positioner, QObject *parent) { return internalGetXdgPopup(surface, *parentSurface, positioner, parent); } XdgShellPopup *XdgShellUnstableV6::Private::getXdgPopup(Surface *surface, XdgShellPopup *parentSurface, const XdgPositioner &positioner, QObject *parent) { return internalGetXdgPopup(surface, *parentSurface, positioner, parent); } XdgShellPopup *XdgShellUnstableV6::Private::internalGetXdgPopup(Surface *surface, zxdg_surface_v6 *parentSurface, const XdgPositioner &positioner, QObject *parent) { Q_ASSERT(isValid()); auto ss = zxdg_shell_v6_get_xdg_surface(xdgshellv6, *surface); if (!ss) { return nullptr; } auto p = zxdg_shell_v6_create_positioner(xdgshellv6); auto anchorRect = positioner.anchorRect(); zxdg_positioner_v6_set_anchor_rect(p, anchorRect.x(), anchorRect.y(), anchorRect.width(), anchorRect.height()); QSize initialSize = positioner.initialSize(); zxdg_positioner_v6_set_size(p, initialSize.width(), initialSize.height()); QPoint anchorOffset = positioner.anchorOffset(); if (!anchorOffset.isNull()) { zxdg_positioner_v6_set_offset(p, anchorOffset.x(), anchorOffset.y()); } uint32_t anchor = 0; if (positioner.anchorEdge().testFlag(Qt::LeftEdge)) { anchor |= ZXDG_POSITIONER_V6_ANCHOR_LEFT; } if (positioner.anchorEdge().testFlag(Qt::TopEdge)) { anchor |= ZXDG_POSITIONER_V6_ANCHOR_TOP; } if (positioner.anchorEdge().testFlag(Qt::RightEdge)) { anchor |= ZXDG_POSITIONER_V6_ANCHOR_RIGHT; } if (positioner.anchorEdge().testFlag(Qt::BottomEdge)) { anchor |= ZXDG_POSITIONER_V6_ANCHOR_BOTTOM; } if (anchor != 0) { zxdg_positioner_v6_set_anchor(p, anchor); } uint32_t gravity = 0; if (positioner.gravity().testFlag(Qt::LeftEdge)) { gravity |= ZXDG_POSITIONER_V6_GRAVITY_LEFT; } if (positioner.gravity().testFlag(Qt::TopEdge)) { gravity |= ZXDG_POSITIONER_V6_GRAVITY_TOP; } if (positioner.gravity().testFlag(Qt::RightEdge)) { gravity |= ZXDG_POSITIONER_V6_GRAVITY_RIGHT; } if (positioner.gravity().testFlag(Qt::BottomEdge)) { gravity |= ZXDG_POSITIONER_V6_GRAVITY_BOTTOM; } if (gravity != 0) { zxdg_positioner_v6_set_gravity(p, gravity); } uint32_t constraint = 0; if (positioner.constraints().testFlag(XdgPositioner::Constraint::SlideX)) { constraint |= ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_SLIDE_X; } if (positioner.constraints().testFlag(XdgPositioner::Constraint::SlideY)) { constraint |= ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_SLIDE_Y; } if (positioner.constraints().testFlag(XdgPositioner::Constraint::FlipX)) { constraint |= ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_FLIP_X; } if (positioner.constraints().testFlag(XdgPositioner::Constraint::FlipY)) { constraint |= ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_FLIP_Y; } if (positioner.constraints().testFlag(XdgPositioner::Constraint::ResizeX)) { constraint |= ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_RESIZE_X; } if (positioner.constraints().testFlag(XdgPositioner::Constraint::ResizeY)) { constraint |= ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_RESIZE_Y; } if (constraint != 0) { zxdg_positioner_v6_set_constraint_adjustment(p, constraint); } XdgShellPopup *s = new XdgShellPopupUnstableV6(parent); auto popup = zxdg_surface_v6_get_popup(ss, parentSurface, p); if (queue) { //deliberately not adding the positioner because the positioner has no events sent to it queue->addProxy(ss); queue->addProxy(popup); } s->setup(ss, popup); zxdg_positioner_v6_destroy(p); return s; } XdgShellUnstableV6::XdgShellUnstableV6(QObject *parent) : XdgShell(new Private, parent) { } XdgShellUnstableV6::~XdgShellUnstableV6() = default; //A top level wraps both xdg_surface_v6 and xdg_top_level into the public API XdgShelllSurface class XdgTopLevelUnstableV6::Private : public XdgShellSurface::Private { public: Private(XdgShellSurface *q); WaylandPointer xdgtoplevelv6; WaylandPointer xdgsurfacev6; void setupV6(zxdg_surface_v6 *surface, zxdg_toplevel_v6 *toplevel) override; void release() override; void destroy() override; bool isValid() const override; using XdgShellSurface::Private::operator xdg_surface*; using XdgShellSurface::Private::operator xdg_toplevel*; operator zxdg_surface_v6*() override { return xdgsurfacev6; } operator zxdg_surface_v6*() const override { return xdgsurfacev6; } operator zxdg_toplevel_v6*() override { return xdgtoplevelv6; } operator zxdg_toplevel_v6*() const override { return xdgtoplevelv6; } void setTransientFor(XdgShellSurface *parent) override; void setTitle(const QString &title) override; void setAppId(const QByteArray &appId) override; void showWindowMenu(Seat *seat, quint32 serial, qint32 x, qint32 y) override; void move(Seat *seat, quint32 serial) override; void resize(Seat *seat, quint32 serial, Qt::Edges edges) override; void ackConfigure(quint32 serial) override; void setMaximized() override; void unsetMaximized() override; void setFullscreen(Output *output) override; void unsetFullscreen() override; void setMinimized() override; void setMaxSize(const QSize &size) override; void setMinSize(const QSize &size) override; private: QSize pendingSize; States pendingState; static void configureCallback(void *data, struct zxdg_toplevel_v6 *xdg_toplevel, int32_t width, int32_t height, struct wl_array *state); static void closeCallback(void *data, zxdg_toplevel_v6 *xdg_toplevel); static void surfaceConfigureCallback(void *data, zxdg_surface_v6 *xdg_surface, uint32_t serial); static const struct zxdg_toplevel_v6_listener s_toplevelListener; static const struct zxdg_surface_v6_listener s_surfaceListener; }; const struct zxdg_toplevel_v6_listener XdgTopLevelUnstableV6::Private::s_toplevelListener = { configureCallback, closeCallback }; const struct zxdg_surface_v6_listener XdgTopLevelUnstableV6::Private::s_surfaceListener = { surfaceConfigureCallback }; void XdgTopLevelUnstableV6::Private::surfaceConfigureCallback(void *data, struct zxdg_surface_v6 *surface, uint32_t serial) { Q_UNUSED(surface) auto s = reinterpret_cast(data); s->q->configureRequested(s->pendingSize, s->pendingState, serial); if (!s->pendingSize.isNull()) { s->q->setSize(s->pendingSize); s->pendingSize = QSize(); } - s->pendingState = nullptr; + s->pendingState = {}; } void XdgTopLevelUnstableV6::Private::configureCallback(void *data, struct zxdg_toplevel_v6 *xdg_toplevel, int32_t width, int32_t height, struct wl_array *state) { Q_UNUSED(xdg_toplevel) auto s = reinterpret_cast(data); States states; uint32_t *statePtr = reinterpret_cast(state->data); for (size_t i = 0; i < state->size / sizeof(uint32_t); i++) { switch (statePtr[i]) { case ZXDG_TOPLEVEL_V6_STATE_MAXIMIZED: states = states | XdgShellSurface::State::Maximized; break; case ZXDG_TOPLEVEL_V6_STATE_FULLSCREEN: states = states | XdgShellSurface::State::Fullscreen; break; case ZXDG_TOPLEVEL_V6_STATE_RESIZING: states = states | XdgShellSurface::State::Resizing; break; case ZXDG_TOPLEVEL_V6_STATE_ACTIVATED: states = states | XdgShellSurface::State::Activated; break; } } s->pendingSize = QSize(width, height); s->pendingState = states; } void XdgTopLevelUnstableV6::Private::closeCallback(void *data, zxdg_toplevel_v6 *xdg_toplevel) { auto s = reinterpret_cast(data); Q_ASSERT(s->xdgtoplevelv6 == xdg_toplevel); emit s->q->closeRequested(); } XdgTopLevelUnstableV6::Private::Private(XdgShellSurface *q) : XdgShellSurface::Private(q) { } void XdgTopLevelUnstableV6::Private::setupV6(zxdg_surface_v6 *surface, zxdg_toplevel_v6 *topLevel) { Q_ASSERT(surface); Q_ASSERT(!xdgtoplevelv6); xdgsurfacev6.setup(surface); xdgtoplevelv6.setup(topLevel); zxdg_surface_v6_add_listener(xdgsurfacev6, &s_surfaceListener, this); zxdg_toplevel_v6_add_listener(xdgtoplevelv6, &s_toplevelListener, this); } void XdgTopLevelUnstableV6::Private::release() { xdgtoplevelv6.release(); xdgsurfacev6.release(); } void XdgTopLevelUnstableV6::Private::destroy() { xdgtoplevelv6.destroy(); xdgsurfacev6.destroy(); } bool XdgTopLevelUnstableV6::Private::isValid() const { return xdgtoplevelv6.isValid() && xdgsurfacev6.isValid(); } void XdgTopLevelUnstableV6::Private::setTransientFor(XdgShellSurface *parent) { zxdg_toplevel_v6 *parentSurface = nullptr; if (parent) { parentSurface = *parent; } zxdg_toplevel_v6_set_parent(xdgtoplevelv6, parentSurface); } void XdgTopLevelUnstableV6::Private::setTitle(const QString & title) { zxdg_toplevel_v6_set_title(xdgtoplevelv6, title.toUtf8().constData()); } void XdgTopLevelUnstableV6::Private::setAppId(const QByteArray & appId) { zxdg_toplevel_v6_set_app_id(xdgtoplevelv6, appId.constData()); } void XdgTopLevelUnstableV6::Private::showWindowMenu(Seat *seat, quint32 serial, qint32 x, qint32 y) { zxdg_toplevel_v6_show_window_menu(xdgtoplevelv6, *seat, serial, x, y); } void XdgTopLevelUnstableV6::Private::move(Seat *seat, quint32 serial) { zxdg_toplevel_v6_move(xdgtoplevelv6, *seat, serial); } void XdgTopLevelUnstableV6::Private::resize(Seat *seat, quint32 serial, Qt::Edges edges) { uint wlEdge = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_NONE; if (edges.testFlag(Qt::TopEdge)) { if (edges.testFlag(Qt::LeftEdge) && ((edges & ~Qt::LeftEdge) == Qt::TopEdge)) { wlEdge = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_TOP_LEFT; } else if (edges.testFlag(Qt::RightEdge) && ((edges & ~Qt::RightEdge) == Qt::TopEdge)) { wlEdge = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_TOP_RIGHT; } else if ((edges & ~Qt::TopEdge) == Qt::Edges()) { wlEdge = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_TOP; } } else if (edges.testFlag(Qt::BottomEdge)) { if (edges.testFlag(Qt::LeftEdge) && ((edges & ~Qt::LeftEdge) == Qt::BottomEdge)) { wlEdge = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_BOTTOM_LEFT; } else if (edges.testFlag(Qt::RightEdge) && ((edges & ~Qt::RightEdge) == Qt::BottomEdge)) { wlEdge = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_BOTTOM_RIGHT; } else if ((edges & ~Qt::BottomEdge) == Qt::Edges()) { wlEdge = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_BOTTOM; } } else if (edges.testFlag(Qt::RightEdge) && ((edges & ~Qt::RightEdge) == Qt::Edges())) { wlEdge = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_RIGHT; } else if (edges.testFlag(Qt::LeftEdge) && ((edges & ~Qt::LeftEdge) == Qt::Edges())) { wlEdge = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_LEFT; } zxdg_toplevel_v6_resize(xdgtoplevelv6, *seat, serial, wlEdge); } void XdgTopLevelUnstableV6::Private::ackConfigure(quint32 serial) { zxdg_surface_v6_ack_configure(xdgsurfacev6, serial); } void XdgTopLevelUnstableV6::Private::setMaximized() { zxdg_toplevel_v6_set_maximized(xdgtoplevelv6); } void XdgTopLevelUnstableV6::Private::unsetMaximized() { zxdg_toplevel_v6_unset_maximized(xdgtoplevelv6); } void XdgTopLevelUnstableV6::Private::setFullscreen(Output *output) { wl_output *o = nullptr; if (output) { o = *output; } zxdg_toplevel_v6_set_fullscreen(xdgtoplevelv6, o); } void XdgTopLevelUnstableV6::Private::unsetFullscreen() { zxdg_toplevel_v6_unset_fullscreen(xdgtoplevelv6); } void XdgTopLevelUnstableV6::Private::setMinimized() { zxdg_toplevel_v6_set_minimized(xdgtoplevelv6); } void XdgTopLevelUnstableV6::Private::setMaxSize(const QSize &size) { zxdg_toplevel_v6_set_max_size(xdgtoplevelv6, size.width(), size.height()); } void XdgTopLevelUnstableV6::Private::setMinSize(const QSize &size) { zxdg_toplevel_v6_set_min_size(xdgtoplevelv6, size.width(), size.height()); } XdgTopLevelUnstableV6::XdgTopLevelUnstableV6(QObject *parent) : XdgShellSurface(new Private(this), parent) { } XdgTopLevelUnstableV6::~XdgTopLevelUnstableV6() = default; class XdgShellPopupUnstableV6::Private : public XdgShellPopup::Private { public: Private(XdgShellPopup *q); void setupV6(zxdg_surface_v6 *s, zxdg_popup_v6 *p) override; void release() override; void destroy() override; bool isValid() const override; void requestGrab(Seat *seat, quint32 serial) override; void ackConfigure(quint32 serial) override; using XdgShellPopup::Private::operator xdg_popup*; using XdgShellPopup::Private::operator xdg_surface*; operator zxdg_surface_v6*() override { return xdgsurfacev6; } operator zxdg_surface_v6*() const override { return xdgsurfacev6; } operator zxdg_popup_v6*() override { return xdgpopupv6; } operator zxdg_popup_v6*() const override { return xdgpopupv6; } WaylandPointer xdgsurfacev6; WaylandPointer xdgpopupv6; QRect pendingRect; private: static void configureCallback(void *data, zxdg_popup_v6 *xdg_popup, int32_t x, int32_t y, int32_t width, int32_t height); static void popupDoneCallback(void *data, zxdg_popup_v6 *xdg_popup); static void surfaceConfigureCallback(void *data, zxdg_surface_v6 *xdg_surface, uint32_t serial); static const struct zxdg_popup_v6_listener s_popupListener; static const struct zxdg_surface_v6_listener s_surfaceListener; }; const struct zxdg_popup_v6_listener XdgShellPopupUnstableV6::Private::s_popupListener = { configureCallback, popupDoneCallback }; const struct zxdg_surface_v6_listener XdgShellPopupUnstableV6::Private::s_surfaceListener = { surfaceConfigureCallback, }; void XdgShellPopupUnstableV6::Private::configureCallback(void *data, zxdg_popup_v6 *xdg_popup, int32_t x, int32_t y, int32_t width, int32_t height) { Q_UNUSED(xdg_popup); auto s = reinterpret_cast(data); s->pendingRect = QRect(x, y, width, height); } void XdgShellPopupUnstableV6::Private::surfaceConfigureCallback(void *data, struct zxdg_surface_v6 *surface, uint32_t serial) { Q_UNUSED(surface); auto s = reinterpret_cast(data); s->q->configureRequested(s->pendingRect, serial); s->pendingRect = QRect(); } void XdgShellPopupUnstableV6::Private::popupDoneCallback(void *data, zxdg_popup_v6 *xdg_popup) { auto s = reinterpret_cast(data); Q_ASSERT(s->xdgpopupv6 == xdg_popup); emit s->q->popupDone(); } XdgShellPopupUnstableV6::Private::Private(XdgShellPopup *q) : XdgShellPopup::Private(q) { } void XdgShellPopupUnstableV6::Private::setupV6(zxdg_surface_v6 *s, zxdg_popup_v6 *p) { Q_ASSERT(p); Q_ASSERT(!xdgsurfacev6); Q_ASSERT(!xdgpopupv6); xdgsurfacev6.setup(s); xdgpopupv6.setup(p); zxdg_surface_v6_add_listener(xdgsurfacev6, &s_surfaceListener, this); zxdg_popup_v6_add_listener(xdgpopupv6, &s_popupListener, this); } void XdgShellPopupUnstableV6::Private::release() { xdgpopupv6.release(); } void XdgShellPopupUnstableV6::Private::destroy() { xdgpopupv6.destroy(); } bool XdgShellPopupUnstableV6::Private::isValid() const { return xdgpopupv6.isValid(); } void XdgShellPopupUnstableV6::Private::requestGrab(Seat *seat, quint32 serial) { zxdg_popup_v6_grab(xdgpopupv6, *seat, serial); } void XdgShellPopupUnstableV6::Private::ackConfigure(quint32 serial) { zxdg_surface_v6_ack_configure(xdgsurfacev6, serial); } XdgShellPopupUnstableV6::XdgShellPopupUnstableV6(QObject *parent) : XdgShellPopup(new Private(this), parent) { } XdgShellPopupUnstableV6::~XdgShellPopupUnstableV6() = default; } }