| 1 | // Copyright (C) 2018 The Qt Company Ltd. |
| 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only |
| 3 | |
| 4 | #ifndef QWAYLANDXDGSHELL_P_H |
| 5 | #define QWAYLANDXDGSHELL_P_H |
| 6 | |
| 7 | #include <QtWaylandCompositor/private/qwaylandshellsurface_p.h> |
| 8 | #include <QtWaylandCompositor/private/qwaylandshell_p.h> |
| 9 | #include <QtWaylandCompositor/private/qwayland-server-xdg-shell.h> |
| 10 | |
| 11 | #include <QtWaylandCompositor/QWaylandXdgShell> |
| 12 | |
| 13 | #include <QtWaylandCompositor/private/qwaylandxdgdecorationv1_p.h> |
| 14 | |
| 15 | #include <QtCore/QSet> |
| 16 | |
| 17 | // |
| 18 | // W A R N I N G |
| 19 | // ------------- |
| 20 | // |
| 21 | // This file is not part of the Qt API. It exists purely as an |
| 22 | // implementation detail. This header file may change from version to |
| 23 | // version without notice, or even be removed. |
| 24 | // |
| 25 | // We mean it. |
| 26 | // |
| 27 | |
| 28 | QT_BEGIN_NAMESPACE |
| 29 | |
| 30 | struct Q_WAYLANDCOMPOSITOR_EXPORT QWaylandXdgPositionerData { |
| 31 | QSize size; |
| 32 | QRect anchorRect; |
| 33 | Qt::Edges anchorEdges = {}; |
| 34 | Qt::Edges gravityEdges = {}; |
| 35 | uint constraintAdjustments = XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_NONE; |
| 36 | QPoint offset; |
| 37 | QWaylandXdgPositionerData(); |
| 38 | bool isComplete() const; |
| 39 | QPoint anchorPoint() const; |
| 40 | QPoint unconstrainedPosition() const; |
| 41 | }; |
| 42 | |
| 43 | class Q_WAYLANDCOMPOSITOR_EXPORT QWaylandXdgShellPrivate |
| 44 | : public QWaylandShellPrivate |
| 45 | , public QtWaylandServer::xdg_wm_base |
| 46 | { |
| 47 | Q_DECLARE_PUBLIC(QWaylandXdgShell) |
| 48 | public: |
| 49 | QWaylandXdgShellPrivate(); |
| 50 | void ping(Resource *resource, uint32_t serial); |
| 51 | void registerXdgSurface(QWaylandXdgSurface *xdgSurface); |
| 52 | void unregisterXdgSurface(QWaylandXdgSurface *xdgSurface); |
| 53 | static QWaylandXdgShellPrivate *get(QWaylandXdgShell *xdgShell) { return xdgShell->d_func(); } |
| 54 | |
| 55 | QSet<uint32_t> m_pings; |
| 56 | QMultiMap<struct wl_client *, QWaylandXdgSurface *> m_xdgSurfaces; |
| 57 | |
| 58 | QWaylandXdgSurface *xdgSurfaceFromSurface(QWaylandSurface *surface); |
| 59 | |
| 60 | protected: |
| 61 | void xdg_wm_base_destroy(Resource *resource) override; |
| 62 | void xdg_wm_base_create_positioner(Resource *resource, uint32_t id) override; |
| 63 | void xdg_wm_base_get_xdg_surface(Resource *resource, uint32_t id, |
| 64 | struct ::wl_resource *surface) override; |
| 65 | void xdg_wm_base_pong(Resource *resource, uint32_t serial) override; |
| 66 | }; |
| 67 | |
| 68 | class Q_WAYLANDCOMPOSITOR_EXPORT QWaylandXdgSurfacePrivate |
| 69 | : public QWaylandShellSurfacePrivate |
| 70 | , public QtWaylandServer::xdg_surface |
| 71 | { |
| 72 | Q_DECLARE_PUBLIC(QWaylandXdgSurface) |
| 73 | public: |
| 74 | QWaylandXdgSurfacePrivate(); |
| 75 | void setWindowType(Qt::WindowType windowType); |
| 76 | void handleFocusLost(); |
| 77 | void handleFocusReceived(); |
| 78 | static QWaylandXdgSurfacePrivate *get(QWaylandXdgSurface *xdgSurface) { return xdgSurface->d_func(); } |
| 79 | |
| 80 | QRect calculateFallbackWindowGeometry() const; |
| 81 | void updateFallbackWindowGeometry(); |
| 82 | |
| 83 | private: |
| 84 | QWaylandXdgShell *m_xdgShell = nullptr; |
| 85 | QWaylandSurface *m_surface = nullptr; |
| 86 | |
| 87 | QWaylandXdgToplevel *m_toplevel = nullptr; |
| 88 | QWaylandXdgPopup *m_popup = nullptr; |
| 89 | QRect m_windowGeometry; |
| 90 | bool m_unsetWindowGeometry = true; |
| 91 | QMargins m_windowMargins; |
| 92 | Qt::WindowType m_windowType = Qt::WindowType::Window; |
| 93 | |
| 94 | void xdg_surface_destroy_resource(Resource *resource) override; |
| 95 | void xdg_surface_destroy(Resource *resource) override; |
| 96 | void xdg_surface_get_toplevel(Resource *resource, uint32_t id) override; |
| 97 | void xdg_surface_get_popup(Resource *resource, uint32_t id, struct ::wl_resource *parent, struct ::wl_resource *positioner) override; |
| 98 | void xdg_surface_ack_configure(Resource *resource, uint32_t serial) override; |
| 99 | void xdg_surface_set_window_geometry(Resource *resource, int32_t x, int32_t y, int32_t width, int32_t height) override; |
| 100 | }; |
| 101 | |
| 102 | class Q_WAYLANDCOMPOSITOR_EXPORT QWaylandXdgToplevelPrivate : public QObjectPrivate, public QtWaylandServer::xdg_toplevel |
| 103 | { |
| 104 | Q_DECLARE_PUBLIC(QWaylandXdgToplevel) |
| 105 | public: |
| 106 | struct ConfigureEvent { |
| 107 | ConfigureEvent() = default; |
| 108 | ConfigureEvent(const QList<QWaylandXdgToplevel::State> |
| 109 | &incomingStates, |
| 110 | const QSize &incomingSize, uint incomingSerial) |
| 111 | : states(incomingStates), size(incomingSize), serial(incomingSerial) |
| 112 | { } |
| 113 | QList<QWaylandXdgToplevel::State> states; |
| 114 | QSize size = {0, 0}; |
| 115 | uint serial = 0; |
| 116 | }; |
| 117 | |
| 118 | QWaylandXdgToplevelPrivate(QWaylandXdgSurface *xdgSurface, const QWaylandResource& resource); |
| 119 | ConfigureEvent lastSentConfigure() const { return m_pendingConfigures.empty() ? m_lastAckedConfigure : m_pendingConfigures.last(); } |
| 120 | void handleAckConfigure(uint serial); //TODO: move? |
| 121 | void handleFocusLost(); |
| 122 | void handleFocusReceived(); |
| 123 | |
| 124 | static QWaylandXdgToplevelPrivate *get(QWaylandXdgToplevel *toplevel) { return toplevel->d_func(); } |
| 125 | static Qt::Edges convertToEdges(resize_edge edge); |
| 126 | |
| 127 | protected: |
| 128 | |
| 129 | void xdg_toplevel_destroy_resource(Resource *resource) override; |
| 130 | |
| 131 | void xdg_toplevel_destroy(Resource *resource) override; |
| 132 | void xdg_toplevel_set_parent(Resource *resource, struct ::wl_resource *parent) override; |
| 133 | void xdg_toplevel_set_title(Resource *resource, const QString &title) override; |
| 134 | void xdg_toplevel_set_app_id(Resource *resource, const QString &app_id) override; |
| 135 | void xdg_toplevel_show_window_menu(Resource *resource, struct ::wl_resource *seat, uint32_t serial, int32_t x, int32_t y) override; |
| 136 | void xdg_toplevel_move(Resource *resource, struct ::wl_resource *seatResource, uint32_t serial) override; |
| 137 | void xdg_toplevel_resize(Resource *resource, struct ::wl_resource *seat, uint32_t serial, uint32_t edges) override; |
| 138 | void xdg_toplevel_set_max_size(Resource *resource, int32_t width, int32_t height) override; |
| 139 | void xdg_toplevel_set_min_size(Resource *resource, int32_t width, int32_t height) override; |
| 140 | void xdg_toplevel_set_maximized(Resource *resource) override; |
| 141 | void xdg_toplevel_unset_maximized(Resource *resource) override; |
| 142 | void xdg_toplevel_set_fullscreen(Resource *resource, struct ::wl_resource *output) override; |
| 143 | void xdg_toplevel_unset_fullscreen(Resource *resource) override; |
| 144 | void xdg_toplevel_set_minimized(Resource *resource) override; |
| 145 | |
| 146 | public: |
| 147 | QWaylandXdgSurface *m_xdgSurface = nullptr; |
| 148 | QWaylandXdgToplevel *m_parentToplevel = nullptr; |
| 149 | QList<ConfigureEvent> m_pendingConfigures; |
| 150 | ConfigureEvent m_lastAckedConfigure; |
| 151 | QString m_title; |
| 152 | QString m_appId; |
| 153 | QSize m_maxSize; |
| 154 | QSize m_minSize = {0, 0}; |
| 155 | QWaylandXdgToplevelDecorationV1 *m_decoration = nullptr; |
| 156 | bool m_modal = false; |
| 157 | |
| 158 | static QWaylandSurfaceRole s_role; |
| 159 | }; |
| 160 | |
| 161 | class Q_WAYLANDCOMPOSITOR_EXPORT QWaylandXdgPopupPrivate : public QObjectPrivate, public QtWaylandServer::xdg_popup |
| 162 | { |
| 163 | Q_DECLARE_PUBLIC(QWaylandXdgPopup) |
| 164 | public: |
| 165 | struct ConfigureEvent { |
| 166 | QRect geometry; |
| 167 | uint serial; |
| 168 | }; |
| 169 | |
| 170 | QWaylandXdgPopupPrivate(QWaylandXdgSurface *xdgSurface, QWaylandXdgSurface *parentXdgSurface, |
| 171 | QWaylandXdgPositioner *positioner, const QWaylandResource& resource); |
| 172 | |
| 173 | void handleAckConfigure(uint serial); |
| 174 | |
| 175 | static QWaylandXdgPopupPrivate *get(QWaylandXdgPopup *) { return popup->d_func(); } |
| 176 | |
| 177 | static QWaylandSurfaceRole s_role; |
| 178 | |
| 179 | private: |
| 180 | uint sendConfigure(const QRect &geometry); |
| 181 | |
| 182 | protected: |
| 183 | void xdg_popup_destroy(Resource *resource) override; |
| 184 | void xdg_popup_grab(Resource *resource, struct ::wl_resource *seat, uint32_t serial) override; |
| 185 | |
| 186 | private: |
| 187 | QWaylandXdgSurface *m_xdgSurface = nullptr; |
| 188 | QWaylandXdgSurface *m_parentXdgSurface = nullptr; |
| 189 | QWaylandXdgPositionerData m_positionerData; |
| 190 | QRect m_geometry; |
| 191 | QList<ConfigureEvent> m_pendingConfigures; |
| 192 | }; |
| 193 | |
| 194 | class Q_WAYLANDCOMPOSITOR_EXPORT QWaylandXdgPositioner : public QtWaylandServer::xdg_positioner |
| 195 | { |
| 196 | public: |
| 197 | QWaylandXdgPositioner(const QWaylandResource& resource); |
| 198 | static QWaylandXdgPositioner *fromResource(wl_resource *resource); |
| 199 | static Qt::Edges convertToEdges(anchor anchor); |
| 200 | static Qt::Edges convertToEdges(gravity gravity); |
| 201 | |
| 202 | protected: |
| 203 | void xdg_positioner_destroy_resource(Resource *resource) override; //TODO: do something special here? |
| 204 | |
| 205 | void xdg_positioner_destroy(Resource *resource) override; |
| 206 | void xdg_positioner_set_size(Resource *resource, int32_t width, int32_t height) override; |
| 207 | void xdg_positioner_set_anchor_rect(Resource *resource, int32_t x, int32_t y, int32_t width, int32_t height) override; |
| 208 | void xdg_positioner_set_anchor(Resource *resource, uint32_t anchor) override; |
| 209 | void xdg_positioner_set_gravity(Resource *resource, uint32_t gravity) override; |
| 210 | void xdg_positioner_set_constraint_adjustment(Resource *resource, uint32_t constraint_adjustment) override; |
| 211 | void xdg_positioner_set_offset(Resource *resource, int32_t x, int32_t y) override; |
| 212 | |
| 213 | public: |
| 214 | QWaylandXdgPositionerData m_data; |
| 215 | }; |
| 216 | |
| 217 | QT_END_NAMESPACE |
| 218 | |
| 219 | #endif // QWAYLANDXDGSHELL_P_H |
| 220 | |