|
| 1 | +#pragma once |
| 2 | + |
| 3 | +#include <vsg/app/Window.h> |
| 4 | +#include <vsg/ui/KeyEvent.h> |
| 5 | + |
| 6 | +#include <wayland-client.h> |
| 7 | +#include <wayland-cursor.h> |
| 8 | +#include <wayland-egl.h> |
| 9 | +#include <xkbcommon/xkbcommon.h> |
| 10 | + |
| 11 | +#include <vector> |
| 12 | +#include <vsg/core/Objects.h> |
| 13 | +#include <vsg/platform/wayland/wayland-xdg-shell-client-protocol.h> |
| 14 | +#include <vsg/platform/wayland/xdg-decoration-client.h> |
| 15 | +#include <vsg/ui/PointerEvent.h> |
| 16 | +#include <vulkan/vulkan_wayland.h> |
| 17 | + |
| 18 | +namespace vsgWayland |
| 19 | +{ |
| 20 | + class Wayland_Window; |
| 21 | + |
| 22 | + /* |
| 23 | + * This is similar to xcb surface, but we store the pointer to window |
| 24 | + * which will be used by wayland api to access window object |
| 25 | + */ |
| 26 | + class Wayland_surface : public vsg::Surface |
| 27 | + { |
| 28 | + public: |
| 29 | + Wayland_surface(vsg::Instance* instance, wl_display* wlDisplay, wl_surface* wlSurface); |
| 30 | + |
| 31 | + protected: |
| 32 | + Wayland_Window* windowData; |
| 33 | + }; |
| 34 | + |
| 35 | + /* |
| 36 | + * This is the object which holds wayland session infomration which is shared across all the windows |
| 37 | + * It uses global static object which will be referred by all the windows |
| 38 | + * Here we reuse vsg::Objects which will add the Wayland_Windows under it |
| 39 | + * the currentWindow member will track the actie window |
| 40 | + */ |
| 41 | + class WaylandRegistryState : public vsg::Inherit<vsg::Objects, WaylandRegistryState> |
| 42 | + { |
| 43 | + friend class Wayland_Window; |
| 44 | + |
| 45 | + public: |
| 46 | + WaylandRegistryState(const WaylandRegistryState&) = delete; |
| 47 | + WaylandRegistryState& operator=(const WaylandRegistryState&) = delete; |
| 48 | + static WaylandRegistryState* initOrSetState(Wayland_Window* window); // hook for initializing it or adding a new window to it |
| 49 | + ~WaylandRegistryState(); |
| 50 | + |
| 51 | + /* |
| 52 | + * The below declerations are the listeners used by wayland, for some I used empty decleration |
| 53 | + * to avoid warnings, these can be implemented as per future need |
| 54 | + */ |
| 55 | + static void keymapEvent(void* data, wl_keyboard* wl_keyboard, uint32_t format, int32_t fd, uint32_t size); |
| 56 | + static void kbd_enter_event(void* data, struct wl_keyboard* wl_keyboard, uint32_t serial, struct wl_surface* surface, struct wl_array* keys); |
| 57 | + static void kbd_leave_event(void* data, struct wl_keyboard* wl_keyboard, uint32_t serial, struct wl_surface* surface){}; |
| 58 | + static void kbd_key_event(void* data, struct wl_keyboard* wl_keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t state); |
| 59 | + static void kbd_modifier_event(void* data, struct wl_keyboard* wl_keyboard, uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group); |
| 60 | + static void kbd_repeat_event(void* data, wl_keyboard* wl_keyboard, int rate, int delay){}; |
| 61 | + constexpr static struct wl_keyboard_listener wl_keyboard_listener = { |
| 62 | + .keymap = keymapEvent, |
| 63 | + .enter = kbd_enter_event, |
| 64 | + .leave = kbd_leave_event, |
| 65 | + .key = kbd_key_event, |
| 66 | + .modifiers = kbd_modifier_event, |
| 67 | + .repeat_info = kbd_repeat_event}; |
| 68 | + |
| 69 | + static void pointer_enter(void* data, struct wl_pointer* pointer, uint32_t serial, struct wl_surface* surface, wl_fixed_t surface_x, wl_fixed_t surface_y); |
| 70 | + static void pointer_leave(void* data, struct wl_pointer* pointer, uint32_t serial, struct wl_surface* surface){}; |
| 71 | + static void pointer_motion(void* data, struct wl_pointer* pointer, uint32_t time, wl_fixed_t x, wl_fixed_t y); |
| 72 | + static void pointer_button(void* data, struct wl_pointer* pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state); |
| 73 | + static void pointer_axis(void* data, struct wl_pointer* pointer, uint32_t time, uint32_t axis, wl_fixed_t value); |
| 74 | + static void pointer_frame(void* data, wl_pointer* wl_pointer){}; |
| 75 | + static void pointer_axis_source(void* data, wl_pointer* wl_pointer, uint axis_source){}; |
| 76 | + static void pointer_axis_stop(void* data, wl_pointer* wl_pointer, uint time, uint axis){}; |
| 77 | + static void pointer_axis_discrete(void* data, wl_pointer* wl_pointer, uint axis, int discrete){}; |
| 78 | + constexpr static struct wl_pointer_listener pointer_listener = { |
| 79 | + .enter = pointer_enter, |
| 80 | + .leave = pointer_leave, |
| 81 | + .motion = pointer_motion, |
| 82 | + .button = pointer_button, |
| 83 | + .axis = pointer_axis, |
| 84 | + .frame = pointer_frame, |
| 85 | + .axis_source = pointer_axis_source, |
| 86 | + .axis_stop = pointer_axis_stop, |
| 87 | + .axis_discrete = pointer_axis_discrete}; |
| 88 | + |
| 89 | + static void seat_capabilities(void* data, struct wl_seat* seat, uint32_t capabilities); |
| 90 | + static void seat_name(void* data, wl_seat* wl_seat, const char* name){}; |
| 91 | + constexpr static struct wl_seat_listener seat_listener = { |
| 92 | + .capabilities = seat_capabilities, |
| 93 | + .name = seat_name}; |
| 94 | + |
| 95 | + static void registry_add_object(void* data, struct wl_registry* registry, uint32_t id, const char* interface, uint32_t version); |
| 96 | + static void registry_remove_object(void* data, struct wl_registry* registry, uint32_t id){}; |
| 97 | + constexpr static struct wl_registry_listener registry_listener = { |
| 98 | + .global = registry_add_object, |
| 99 | + .global_remove = registry_remove_object}; |
| 100 | + |
| 101 | + protected: |
| 102 | + struct wl_display* _wlDisplay = nullptr; |
| 103 | + struct wl_registry* _wlRegistry = nullptr; |
| 104 | + struct wl_compositor* _wlCompositor = nullptr; |
| 105 | + struct wl_seat* _seat = nullptr; |
| 106 | + struct wl_shm* _shm = nullptr; |
| 107 | + struct xdg_wm_base* _xdgWmBase = nullptr; |
| 108 | + struct zxdg_decoration_manager_v1* _decorationManager = nullptr; |
| 109 | + struct wl_cursor_theme* _cursorTheme = nullptr; |
| 110 | + struct xkb_state* _xkb_state; |
| 111 | + struct xkb_context* _xkb_context; |
| 112 | + struct xkb_keymap* _xkb_keymap; |
| 113 | + struct wl_surface* _cursorSurface = nullptr; |
| 114 | + uint16_t maskButtons; |
| 115 | + Wayland_Window* currentWindow; |
| 116 | + static inline WaylandRegistryState* state; |
| 117 | + static inline bool initialized; |
| 118 | + |
| 119 | + WaylandRegistryState(){}; //empty initializer needed for initializing from the initOrSetState |
| 120 | + }; |
| 121 | + |
| 122 | + /* |
| 123 | + * The Wayland_Window class can access members of WaylandStateRegistry class and vice versa |
| 124 | + * |
| 125 | + */ |
| 126 | + class Wayland_Window : public vsg::Inherit<vsg::Window, Wayland_Window> |
| 127 | + { |
| 128 | + friend class WaylandRegistryState; |
| 129 | + |
| 130 | + public: |
| 131 | + Wayland_Window(vsg::ref_ptr<vsg::WindowTraits> traits); |
| 132 | + Wayland_Window() = delete; |
| 133 | + Wayland_Window(const Wayland_Window&) = delete; |
| 134 | + Wayland_Window& operator=(const Wayland_Window&) = delete; |
| 135 | + |
| 136 | + const char* instanceExtensionSurfaceName() const override { return VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME; } |
| 137 | + |
| 138 | + bool valid() const override; |
| 139 | + |
| 140 | + bool visible() const override; |
| 141 | + |
| 142 | + void releaseWindow() override; |
| 143 | + void releaseConnection() override; |
| 144 | + |
| 145 | + bool pollEvents(vsg::UIEvents& events) override; |
| 146 | + |
| 147 | + void resize() override; |
| 148 | + |
| 149 | + protected: |
| 150 | + ~Wayland_Window(); |
| 151 | + static WaylandRegistryState registryStateRef; |
| 152 | + void _initSurface() override; |
| 153 | + |
| 154 | + /* |
| 155 | + * The below declerations are the listeners used by wayland, for some I used empty decleration |
| 156 | + * to avoid warnings, these can be implemented as per future need |
| 157 | + */ |
| 158 | + static void xdg_surface_handle_configure(void* data, struct xdg_surface* xdg_surface, uint32_t serial); |
| 159 | + constexpr static struct xdg_surface_listener xdg_surface_listener = { |
| 160 | + .configure = xdg_surface_handle_configure, |
| 161 | + }; |
| 162 | + |
| 163 | + static void xdg_toplevel_handle_configure(void* data, struct xdg_toplevel* xdg_toplevel, int32_t width, int32_t height, struct wl_array* states); |
| 164 | + static void xdg_toplevel_handle_close(void* data, struct xdg_toplevel* xdg_toplevel); |
| 165 | + static void xdg_toplevel_handle_configure_bounds(void* data, struct xdg_toplevel* xdg_toplevel, int32_t width, int32_t height){}; |
| 166 | + constexpr static struct xdg_toplevel_listener xdg_toplevel_listener = { |
| 167 | + .configure = xdg_toplevel_handle_configure, |
| 168 | + .close = xdg_toplevel_handle_close, |
| 169 | + .configure_bounds = xdg_toplevel_handle_configure_bounds}; |
| 170 | + |
| 171 | + static void shell_surface_ping(void* data, struct wl_shell_surface* shell_surface, uint32_t serial); |
| 172 | + static void shell_surface_configure(void* data, struct wl_shell_surface* shell_surface, uint32_t edges, int32_t width, int32_t height); |
| 173 | + static void shell_surface_popup_done(void* data, struct wl_shell_surface* shell_surface); |
| 174 | + constexpr static struct wl_shell_surface_listener shell_surface_listener = { |
| 175 | + .ping = shell_surface_ping, |
| 176 | + .configure = shell_surface_configure, |
| 177 | + .popup_done = shell_surface_popup_done}; |
| 178 | + static void xdg_wm_base_ping(void* data, struct xdg_wm_base* xdg_wm_base, uint32_t serial); |
| 179 | + constexpr static struct xdg_wm_base_listener xdg_wm_base_listener = { |
| 180 | + .ping = xdg_wm_base_ping}; |
| 181 | + |
| 182 | + struct wl_surface* _wlSurface = nullptr; |
| 183 | + struct xdg_surface* _xdgSurface = nullptr; |
| 184 | + struct xdg_toplevel* _xdgToplevel = nullptr; |
| 185 | + struct wl_surface* _currentSurface = nullptr; |
| 186 | + struct zxdg_toplevel_decoration_v1* _topDecoration = nullptr; |
| 187 | + WaylandRegistryState* _state; |
| 188 | + int _width = 256; |
| 189 | + int _height = 256; |
| 190 | + int cursor_x = -1; |
| 191 | + int cursor_y = -1; |
| 192 | + bool _resize = false; |
| 193 | + std::string _windowTitle; |
| 194 | + }; |
| 195 | +} // namespace vsgWayland |
| 196 | + |
| 197 | +EVSG_type_name(vsgWayland::Wayland_Window); |
0 commit comments