#ifndef QT_WAYLAND_XDG_SHELL
#define QT_WAYLAND_XDG_SHELL

#include "wayland-xdg-shell-client-protocol.h"
#include <QByteArray>
#include <QString>

struct wl_registry;

QT_BEGIN_NAMESPACE
QT_WARNING_PUSH
QT_WARNING_DISABLE_GCC("-Wmissing-field-initializers")

namespace QtWayland {
    class  xdg_wm_base
    {
    public:
        xdg_wm_base(struct ::wl_registry *registry, int id, int version);
        xdg_wm_base(struct ::xdg_wm_base *object);
        xdg_wm_base();

        virtual ~xdg_wm_base();

        void init(struct ::wl_registry *registry, int id, int version);
        void init(struct ::xdg_wm_base *object);

        struct ::xdg_wm_base *object() { return m_xdg_wm_base; }
        const struct ::xdg_wm_base *object() const { return m_xdg_wm_base; }
        static xdg_wm_base *fromObject(struct ::xdg_wm_base *object);

        bool isInitialized() const;

        static const struct ::wl_interface *interface();

        enum error {
            error_role = 0, // given wl_surface has another role
            error_defunct_surfaces = 1, // xdg_wm_base was destroyed before children
            error_not_the_topmost_popup = 2, // the client tried to map or destroy a non-topmost popup
            error_invalid_popup_parent = 3, // the client specified an invalid popup parent surface
            error_invalid_surface_state = 4, // the client provided an invalid surface state
            error_invalid_positioner = 5 // the client provided an invalid positioner
        };

        void destroy();
        struct ::xdg_positioner *create_positioner();
        struct ::xdg_surface *get_xdg_surface(struct ::wl_surface *surface);
        void pong(uint32_t serial);

    protected:
        virtual void xdg_wm_base_ping(uint32_t serial);

    private:
        void init_listener();
        static const struct xdg_wm_base_listener m_xdg_wm_base_listener;
        static void handle_ping(
            void *data,
            struct ::xdg_wm_base *object,
            uint32_t serial);
        struct ::xdg_wm_base *m_xdg_wm_base;
    };

    class  xdg_positioner
    {
    public:
        xdg_positioner(struct ::wl_registry *registry, int id, int version);
        xdg_positioner(struct ::xdg_positioner *object);
        xdg_positioner();

        virtual ~xdg_positioner();

        void init(struct ::wl_registry *registry, int id, int version);
        void init(struct ::xdg_positioner *object);

        struct ::xdg_positioner *object() { return m_xdg_positioner; }
        const struct ::xdg_positioner *object() const { return m_xdg_positioner; }
        static xdg_positioner *fromObject(struct ::xdg_positioner *object);

        bool isInitialized() const;

        static const struct ::wl_interface *interface();

        enum error {
            error_invalid_input = 0 // invalid input provided
        };

        enum anchor {
            anchor_none = 0,
            anchor_top = 1,
            anchor_bottom = 2,
            anchor_left = 3,
            anchor_right = 4,
            anchor_top_left = 5,
            anchor_bottom_left = 6,
            anchor_top_right = 7,
            anchor_bottom_right = 8
        };

        enum gravity {
            gravity_none = 0,
            gravity_top = 1,
            gravity_bottom = 2,
            gravity_left = 3,
            gravity_right = 4,
            gravity_top_left = 5,
            gravity_bottom_left = 6,
            gravity_top_right = 7,
            gravity_bottom_right = 8
        };

        enum constraint_adjustment {
            constraint_adjustment_none = 0,
            constraint_adjustment_slide_x = 1,
            constraint_adjustment_slide_y = 2,
            constraint_adjustment_flip_x = 4,
            constraint_adjustment_flip_y = 8,
            constraint_adjustment_resize_x = 16,
            constraint_adjustment_resize_y = 32
        };

        void destroy();
        void set_size(int32_t width, int32_t height);
        void set_anchor_rect(int32_t x, int32_t y, int32_t width, int32_t height);
        void set_anchor(uint32_t anchor);
        void set_gravity(uint32_t gravity);
        void set_constraint_adjustment(uint32_t constraint_adjustment);
        void set_offset(int32_t x, int32_t y);

    private:
        struct ::xdg_positioner *m_xdg_positioner;
    };

    class  xdg_surface
    {
    public:
        xdg_surface(struct ::wl_registry *registry, int id, int version);
        xdg_surface(struct ::xdg_surface *object);
        xdg_surface();

        virtual ~xdg_surface();

        void init(struct ::wl_registry *registry, int id, int version);
        void init(struct ::xdg_surface *object);

        struct ::xdg_surface *object() { return m_xdg_surface; }
        const struct ::xdg_surface *object() const { return m_xdg_surface; }
        static xdg_surface *fromObject(struct ::xdg_surface *object);

        bool isInitialized() const;

        static const struct ::wl_interface *interface();

        enum error {
            error_not_constructed = 1,
            error_already_constructed = 2,
            error_unconfigured_buffer = 3
        };

        void destroy();
        struct ::xdg_toplevel *get_toplevel();
        struct ::xdg_popup *get_popup(struct ::xdg_surface *parent, struct ::xdg_positioner *positioner);
        void set_window_geometry(int32_t x, int32_t y, int32_t width, int32_t height);
        void ack_configure(uint32_t serial);

    protected:
        virtual void xdg_surface_configure(uint32_t serial);

    private:
        void init_listener();
        static const struct xdg_surface_listener m_xdg_surface_listener;
        static void handle_configure(
            void *data,
            struct ::xdg_surface *object,
            uint32_t serial);
        struct ::xdg_surface *m_xdg_surface;
    };

    class  xdg_toplevel
    {
    public:
        xdg_toplevel(struct ::wl_registry *registry, int id, int version);
        xdg_toplevel(struct ::xdg_toplevel *object);
        xdg_toplevel();

        virtual ~xdg_toplevel();

        void init(struct ::wl_registry *registry, int id, int version);
        void init(struct ::xdg_toplevel *object);

        struct ::xdg_toplevel *object() { return m_xdg_toplevel; }
        const struct ::xdg_toplevel *object() const { return m_xdg_toplevel; }
        static xdg_toplevel *fromObject(struct ::xdg_toplevel *object);

        bool isInitialized() const;

        static const struct ::wl_interface *interface();

        enum resize_edge {
            resize_edge_none = 0,
            resize_edge_top = 1,
            resize_edge_bottom = 2,
            resize_edge_left = 4,
            resize_edge_top_left = 5,
            resize_edge_bottom_left = 6,
            resize_edge_right = 8,
            resize_edge_top_right = 9,
            resize_edge_bottom_right = 10
        };

        enum state {
            state_maximized = 1, // the surface is maximized
            state_fullscreen = 2, // the surface is fullscreen
            state_resizing = 3, // the surface is being resized
            state_activated = 4 // the surface is now activated
        };

        void destroy();
        void set_parent(struct ::xdg_toplevel *parent);
        void set_title(const QString &title);
        void set_app_id(const QString &app_id);
        void show_window_menu(struct ::wl_seat *seat, uint32_t serial, int32_t x, int32_t y);
        void move(struct ::wl_seat *seat, uint32_t serial);
        void resize(struct ::wl_seat *seat, uint32_t serial, uint32_t edges);
        void set_max_size(int32_t width, int32_t height);
        void set_min_size(int32_t width, int32_t height);
        void set_maximized();
        void unset_maximized();
        void set_fullscreen(struct ::wl_output *output);
        void unset_fullscreen();
        void set_minimized();

    protected:
        virtual void xdg_toplevel_configure(int32_t width, int32_t height, wl_array *states);
        virtual void xdg_toplevel_close();

    private:
        void init_listener();
        static const struct xdg_toplevel_listener m_xdg_toplevel_listener;
        static void handle_configure(
            void *data,
            struct ::xdg_toplevel *object,
            int32_t width,
            int32_t height,
            wl_array *states);
        static void handle_close(
            void *data,
            struct ::xdg_toplevel *object);
        struct ::xdg_toplevel *m_xdg_toplevel;
    };

    class  xdg_popup
    {
    public:
        xdg_popup(struct ::wl_registry *registry, int id, int version);
        xdg_popup(struct ::xdg_popup *object);
        xdg_popup();

        virtual ~xdg_popup();

        void init(struct ::wl_registry *registry, int id, int version);
        void init(struct ::xdg_popup *object);

        struct ::xdg_popup *object() { return m_xdg_popup; }
        const struct ::xdg_popup *object() const { return m_xdg_popup; }
        static xdg_popup *fromObject(struct ::xdg_popup *object);

        bool isInitialized() const;

        static const struct ::wl_interface *interface();

        enum error {
            error_invalid_grab = 0 // tried to grab after being mapped
        };

        void destroy();
        void grab(struct ::wl_seat *seat, uint32_t serial);

    protected:
        virtual void xdg_popup_configure(int32_t x, int32_t y, int32_t width, int32_t height);
        virtual void xdg_popup_popup_done();

    private:
        void init_listener();
        static const struct xdg_popup_listener m_xdg_popup_listener;
        static void handle_configure(
            void *data,
            struct ::xdg_popup *object,
            int32_t x,
            int32_t y,
            int32_t width,
            int32_t height);
        static void handle_popup_done(
            void *data,
            struct ::xdg_popup *object);
        struct ::xdg_popup *m_xdg_popup;
    };
}

QT_WARNING_POP
QT_END_NAMESPACE

#endif
