From 126fc92fae47a475d8e7cb2b5b75682f4dc16cc7 Mon Sep 17 00:00:00 2001 From: Karutoh Date: Mon, 8 Jul 2024 21:17:09 -0700 Subject: [PATCH] Fixed Wayland window resizing and closing. --- include/ehs/io/BaseWindow.h | 6 - include/ehs/io/Window_Way.h | 25 ++-- src/io/Window_Way.cpp | 221 ++++++++++++++++-------------------- 3 files changed, 114 insertions(+), 138 deletions(-) diff --git a/include/ehs/io/BaseWindow.h b/include/ehs/io/BaseWindow.h index 3dd0def..226406a 100644 --- a/include/ehs/io/BaseWindow.h +++ b/include/ehs/io/BaseWindow.h @@ -1,9 +1,7 @@ #pragma once -#include "ehs/EHS.h" #include "ehs/Str.h" #include "ehs/Vec2.h" -#include "ehs/Rect.h" #include "ehs/io/hid/Input.h" namespace ehs @@ -60,10 +58,6 @@ namespace ehs bool HasFocus() const; - void EnableResizing(bool enable); - - bool IsResizable() const; - /// Gets the cursors position on the desktop in pixels. /// @param [in] relative Whether the position should be relative to the windows client. /// @returns The current value. diff --git a/include/ehs/io/Window_Way.h b/include/ehs/io/Window_Way.h index 3011740..87454a4 100644 --- a/include/ehs/io/Window_Way.h +++ b/include/ehs/io/Window_Way.h @@ -18,16 +18,13 @@ namespace ehs xdg_wm_base *xdgShell; xdg_surface *xdgSurface; xdg_toplevel *xdgToplevel; - wl_shm *shm; - wl_buffer *buffer; zxdg_decoration_manager_v1 *decManager; zxdg_toplevel_decoration_v1 *dec; + wl_seat *seat; + wl_pointer *pointer; + Vec2_u32 scale; - static Int_32 CreateShmFile(Size size); - - void CreateBuffer(Vec2_u32 scale); - - static void SurfaceConfigure(void *data, xdg_surface *xdg_surface, UInt_32 serial); + static void SurfaceConfigEvent(void *data, xdg_surface *xdg_surface, UInt_32 serial); static void ShellPing(void *data, xdg_wm_base *shell, UInt_32 serial); @@ -35,7 +32,13 @@ namespace ehs static void RegistryRemoved(void *data, wl_registry *registry, UInt_32 id); - static void Resolution(void *data, struct xdg_toplevel *xdg_toplevel, Int_32 width, Int_32 height, wl_array *states); + static void ResizeEvent(void *data, xdg_toplevel *xdg_toplevel, Int_32 width, Int_32 height, wl_array *states); + + static void CloseEvent(void *data, xdg_toplevel *xdg_toplevel); + + static void SeatCapabilitiesEvent(void *data, wl_seat *seat, UInt_32 capabilities); + + static void PointerMotionEvent(void *data, wl_pointer *pointer, UInt_32 time, wl_fixed_t sx, wl_fixed_t sy); public: ~Window() override; @@ -50,11 +53,11 @@ namespace ehs Window &operator=(const Window &win); - void Create_32(const Str_32& title, const Vec2_s32& pos, const Vec2_u32 scale) override; + void Create_32(const Str_32& title, const Vec2_s32& pos, Vec2_u32 scale) override; - void Create_16(const Str_16& title, const Vec2_s32& pos, const Vec2_u32 scale) override; + void Create_16(const Str_16& title, const Vec2_s32& pos, Vec2_u32 scale) override; - void Create_8(const Str_8& title, const Vec2_s32& pos, const Vec2_u32 scale) override; + void Create_8(const Str_8& title, const Vec2_s32& pos, Vec2_u32 scale) override; void OnCreated() override; diff --git a/src/io/Window_Way.cpp b/src/io/Window_Way.cpp index 387d1a3..129fb5f 100644 --- a/src/io/Window_Way.cpp +++ b/src/io/Window_Way.cpp @@ -8,73 +8,13 @@ namespace ehs { - Int_32 Window::CreateShmFile(Size size) - { - const char *path = getenv("XDG_RUNTIME_DIR"); - if (!path) - { - EHS_LOG_INT(LogType::ERR, 0, "XDG_RUNTIME_DIR is not set."); - return -1; - } - - Str_8 tmplPath = Str_8(path) + "/wl_shm_XXXXXX"; - - Int_32 fd = mkstemp(tmplPath); - if (fd < 0) - { - EHS_LOG_INT(LogType::ERR, 1, "Failed to create shared memory file."); - return -1; - } - - if (unlink(tmplPath) < 0) - { - EHS_LOG_INT(LogType::ERR, 2, "Failed to unlink shared memory file."); - close(fd); - return -1; - } - - if (ftruncate(fd, size) < 0) - { - EHS_LOG_INT(LogType::ERR, 3, "Failed to set size of shared memory file to " + Str_8::FromNum(size) + "."); - close(fd); - return -1; - } - - EHS_LOG_SUCCESS(); - - return fd; - } - - void Window::CreateBuffer(Vec2_u32 scale) - { - const Size stride = scale.x * 4; - const Size size = stride * scale.y; - - const Int_32 fd = CreateShmFile(size); - - if (mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0) == MAP_FAILED) - { - EHS_LOG_INT(LogType::ERR, 0, "Failed to map shared memory file."); - close(fd); - return; - } - - wl_shm_pool *pool = wl_shm_create_pool(shm, fd, (int32_t)size); - - buffer = wl_shm_pool_create_buffer(pool, 0, (int32_t)scale.x, (int32_t)scale.y, (int32_t)stride, - WL_SHM_FORMAT_XRGB8888); - - wl_shm_pool_destroy(pool); - - close(fd); - } - - void Window::SurfaceConfigure(void* data, xdg_surface* xdg_surface, UInt_32 serial) + void Window::SurfaceConfigEvent(void* data, xdg_surface* xdg_surface, UInt_32 serial) { xdg_surface_ack_configure(xdg_surface, serial); - if (data) - wl_surface_commit(((Window*)data)->wlSurface); + Window* win = (Window *)data; + + wl_surface_commit(win->wlSurface); } void Window::ShellPing(void* data, xdg_wm_base* shell, UInt_32 serial) @@ -84,49 +24,66 @@ namespace ehs void Window::RegistryHandler(void* data, wl_registry* registry, UInt_32 id, const char* interface, UInt_32 version) { - Serializer* ser = (Serializer*)data; + Window *win = (Window *)data; if (Str_8::Cmp(interface, wl_compositor_interface.name)) - { - ser->SetOffset(0); - wl_compositor** comp = ser->Read(); - *comp = (wl_compositor*)wl_registry_bind(registry, id, &wl_compositor_interface, 1); - } + win->compositor = (wl_compositor*)wl_registry_bind(registry, id, &wl_compositor_interface, 1); else if (Str_8::Cmp(interface, xdg_wm_base_interface.name)) - { - ser->SetOffset(sizeof(void*)); - xdg_wm_base** base = ser->Read(); - *base = (xdg_wm_base*)wl_registry_bind(registry, id, &xdg_wm_base_interface, 1); - } - else if (Str_8::Cmp(interface, wl_shm_interface.name)) - { - ser->SetOffset(sizeof(void*) * 2); - wl_shm** shm = ser->Read(); - *shm = (wl_shm*)wl_registry_bind(registry, id, &wl_shm_interface, 1); - } + win->xdgShell = (xdg_wm_base*)wl_registry_bind(registry, id, &xdg_wm_base_interface, 1); else if (Str_8::Cmp(interface, zxdg_decoration_manager_v1_interface.name)) - { - ser->SetOffset(sizeof(void*) * 3); - zxdg_decoration_manager_v1** decManager = ser->Read(); - *decManager = (zxdg_decoration_manager_v1*)wl_registry_bind(registry, id, &zxdg_decoration_manager_v1_interface, 1); - } + win->decManager = (zxdg_decoration_manager_v1*)wl_registry_bind(registry, id, &zxdg_decoration_manager_v1_interface, 1); + else if (Str_8::Cmp(interface, wl_seat_interface.name)) + win->seat = (wl_seat *)wl_registry_bind(registry, id, &wl_seat_interface, 1); } void Window::RegistryRemoved(void* data, wl_registry* registry, UInt_32 id) { } - void Window::Resolution(void *data, struct xdg_toplevel *xdg_toplevel, Int_32 width, Int_32 height, wl_array *states) + void Window::ResizeEvent(void *data, struct xdg_toplevel *xdg_toplevel, Int_32 width, Int_32 height, wl_array *states) { - Console::Write_8("Resolution: " + Str_8::FromNum(width) + "x" + Str_8::FromNum(height)); + if (!width && !height) + return; + + Window *win = (Window *)data; + + win->scale = {(UInt_32)width, (UInt_32)height}; + } + + void Window::CloseEvent(void *data, xdg_toplevel *xdg_toplevel) + { + Window *win = (Window *)data; + win->Close(); + } + + void Window::SeatCapabilitiesEvent(void *data, wl_seat *seat, UInt_32 capabilities) + { + Window *win = (Window *)data; + + if (capabilities & WL_SEAT_CAPABILITY_POINTER) + { + win->pointer = wl_seat_get_pointer(seat); + + static const wl_pointer_listener pointer_listener = { + .motion = PointerMotionEvent + }; + + wl_pointer_add_listener(win->pointer, &pointer_listener, win); + } + } + + void Window::PointerMotionEvent(void *data, wl_pointer *pointer, UInt_32 time, wl_fixed_t sx, wl_fixed_t sy) + { + EHS_LOG_INT(LogType::INFO, 0, "Pointer Pos: <" + Str_8::FromNum(wl_fixed_to_double(sx)) + ", " + Str_8::FromNum(wl_fixed_to_double(sy)) + ">"); } Window::~Window() { + if (!created) + return; + zxdg_toplevel_decoration_v1_destroy(dec); zxdg_decoration_manager_v1_destroy(decManager); - wl_buffer_destroy(buffer); - wl_shm_destroy(shm); xdg_toplevel_destroy(xdgToplevel); xdg_surface_destroy(xdgSurface); xdg_wm_base_destroy(xdgShell); @@ -138,14 +95,14 @@ namespace ehs Window::Window() : display(nullptr), registry(nullptr), compositor(nullptr), wlSurface(nullptr), xdgShell(nullptr), - xdgSurface(nullptr), xdgToplevel(nullptr), shm(nullptr), buffer(nullptr), decManager(nullptr), dec(nullptr) + xdgSurface(nullptr), xdgToplevel(nullptr), decManager(nullptr), dec(nullptr), seat(nullptr), pointer(nullptr) { } Window::Window(Window &&win) noexcept : BaseWindow(win), display(win.display), registry(win.registry), compositor(win.compositor), wlSurface(win.wlSurface), xdgShell(win.xdgShell), xdgSurface(win.xdgSurface), xdgToplevel(win.xdgToplevel), - shm(win.shm), buffer(win.buffer), decManager(win.decManager), dec(win.dec) + decManager(win.decManager), dec(win.dec), seat(win.seat), pointer(win.pointer) { win.display = nullptr; win.registry = nullptr; @@ -154,16 +111,16 @@ namespace ehs win.xdgShell = nullptr; win.xdgSurface = nullptr; win.xdgToplevel = nullptr; - win.shm = nullptr; - win.buffer = nullptr; win.decManager = nullptr; win.dec = nullptr; + win.seat = nullptr; + win.pointer = nullptr; } Window::Window(const Window &win) : BaseWindow(win), display(nullptr), registry(nullptr), compositor(nullptr), wlSurface(nullptr), - xdgShell(nullptr), xdgSurface(nullptr), xdgToplevel(nullptr), shm(nullptr), buffer(nullptr), decManager(nullptr), - dec(nullptr) + xdgShell(nullptr), xdgSurface(nullptr), xdgToplevel(nullptr), decManager(nullptr), dec(nullptr), seat(nullptr), + pointer(nullptr) { } @@ -181,10 +138,10 @@ namespace ehs xdgShell = win.xdgShell; xdgSurface = win.xdgSurface; xdgToplevel = win.xdgToplevel; - shm = win.shm; - buffer = win.buffer; decManager = win.decManager; dec = win.dec; + seat = win.seat; + pointer = win.pointer; win.display = nullptr; win.registry = nullptr; @@ -193,10 +150,10 @@ namespace ehs win.xdgShell = nullptr; win.xdgSurface = nullptr; win.xdgToplevel = nullptr; - win.shm = nullptr; - win.buffer = nullptr; win.decManager = nullptr; win.dec = nullptr; + win.seat = nullptr; + win.pointer = nullptr; return *this; } @@ -215,10 +172,10 @@ namespace ehs xdgShell = nullptr; xdgSurface = nullptr; xdgToplevel = nullptr; - shm = nullptr; - buffer = nullptr; decManager = nullptr; dec = nullptr; + seat = nullptr; + pointer = nullptr; return *this; } @@ -235,6 +192,9 @@ namespace ehs void Window::Create_8(const Str_8& title, const Vec2_s32& pos, const Vec2_u32 scale) { + if (created) + return; + display = wl_display_connect(nullptr); if (!display) { @@ -242,19 +202,13 @@ namespace ehs return; } - Serializer data(Endianness::LE); - data.Write(&compositor); - data.Write(&xdgShell); - data.Write(&shm); - data.Write(&decManager); - static constexpr wl_registry_listener registry_listener = { - RegistryHandler, - RegistryRemoved + .global = RegistryHandler, + .global_remove = RegistryRemoved }; registry = wl_display_get_registry(display); - wl_registry_add_listener(registry, ®istry_listener, &data); + wl_registry_add_listener(registry, ®istry_listener, this); wl_display_dispatch(display); wl_display_roundtrip(display); @@ -265,7 +219,9 @@ namespace ehs return; } - static constexpr xdg_wm_base_listener xdg_shell_listener = {ShellPing}; + static constexpr xdg_wm_base_listener xdg_shell_listener = { + .ping = ShellPing + }; xdg_wm_base_add_listener(xdgShell, &xdg_shell_listener, nullptr); @@ -276,29 +232,34 @@ namespace ehs return; } - CreateBuffer(scale); - xdgSurface = xdg_wm_base_get_xdg_surface(xdgShell, wlSurface); - static constexpr xdg_surface_listener surfaceListener = {SurfaceConfigure}; + static constexpr xdg_surface_listener surfaceListener = { + .configure = SurfaceConfigEvent + }; xdg_surface_add_listener(xdgSurface, &surfaceListener, this); xdgToplevel = xdg_surface_get_toplevel(xdgSurface); static constexpr xdg_toplevel_listener topLevelListener = { - .configure = Resolution + .configure = ResizeEvent, + .close = CloseEvent }; - xdg_toplevel_add_listener(xdgToplevel, &topLevelListener, nullptr); + xdg_toplevel_add_listener(xdgToplevel, &topLevelListener, this); xdg_toplevel_set_title(xdgToplevel, title); - xdg_toplevel_set_app_id(xdgToplevel, "dsadasfsaAS"); + xdg_toplevel_set_app_id(xdgToplevel, title); dec = zxdg_decoration_manager_v1_get_toplevel_decoration(decManager, xdgToplevel); zxdg_toplevel_decoration_v1_set_mode(dec, ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE); - wl_surface_attach(wlSurface, buffer, 0, 0); + static constexpr wl_seat_listener seat_listener = { + .capabilities = SeatCapabilitiesEvent + }; + + wl_seat_add_listener(seat, &seat_listener, this); wl_display_roundtrip(display); @@ -306,6 +267,9 @@ namespace ehs wl_display_roundtrip(display); + this->scale = scale; + created = true; + OnCreated(); } @@ -315,6 +279,15 @@ namespace ehs void Window::Close() { + if (!created) + return; + + zxdg_toplevel_decoration_v1_destroy(dec); + dec = nullptr; + + zxdg_decoration_manager_v1_destroy(decManager); + decManager = nullptr; + xdg_toplevel_destroy(xdgToplevel); xdgToplevel = nullptr; @@ -335,6 +308,8 @@ namespace ehs wl_display_disconnect(display); display = nullptr; + + created = false; } void Window::Show() @@ -347,7 +322,11 @@ namespace ehs bool Window::Poll() { - wl_display_dispatch(display); + if (wl_display_dispatch_pending(display) == -1) + return false; + + if (!created) + return false; return true; } @@ -402,7 +381,7 @@ namespace ehs Vec2_u32 Window::GetScale() const { - return {}; + return scale; } Serializer Window::GetClipboard()