Fixed Wayland window resizing and closing.

This commit is contained in:
Arron David Nelson 2024-07-08 21:17:09 -07:00
parent 2ef28273b0
commit 126fc92fae
3 changed files with 114 additions and 138 deletions

View File

@ -1,9 +1,7 @@
#pragma once #pragma once
#include "ehs/EHS.h"
#include "ehs/Str.h" #include "ehs/Str.h"
#include "ehs/Vec2.h" #include "ehs/Vec2.h"
#include "ehs/Rect.h"
#include "ehs/io/hid/Input.h" #include "ehs/io/hid/Input.h"
namespace ehs namespace ehs
@ -60,10 +58,6 @@ namespace ehs
bool HasFocus() const; bool HasFocus() const;
void EnableResizing(bool enable);
bool IsResizable() const;
/// Gets the cursors position on the desktop in pixels. /// Gets the cursors position on the desktop in pixels.
/// @param [in] relative Whether the position should be relative to the windows client. /// @param [in] relative Whether the position should be relative to the windows client.
/// @returns The current value. /// @returns The current value.

View File

@ -18,16 +18,13 @@ namespace ehs
xdg_wm_base *xdgShell; xdg_wm_base *xdgShell;
xdg_surface *xdgSurface; xdg_surface *xdgSurface;
xdg_toplevel *xdgToplevel; xdg_toplevel *xdgToplevel;
wl_shm *shm;
wl_buffer *buffer;
zxdg_decoration_manager_v1 *decManager; zxdg_decoration_manager_v1 *decManager;
zxdg_toplevel_decoration_v1 *dec; zxdg_toplevel_decoration_v1 *dec;
wl_seat *seat;
wl_pointer *pointer;
Vec2_u32 scale;
static Int_32 CreateShmFile(Size size); static void SurfaceConfigEvent(void *data, xdg_surface *xdg_surface, UInt_32 serial);
void CreateBuffer(Vec2_u32 scale);
static void SurfaceConfigure(void *data, xdg_surface *xdg_surface, UInt_32 serial);
static void ShellPing(void *data, xdg_wm_base *shell, 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 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: public:
~Window() override; ~Window() override;
@ -50,11 +53,11 @@ namespace ehs
Window &operator=(const Window &win); 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; void OnCreated() override;

View File

@ -8,73 +8,13 @@
namespace ehs namespace ehs
{ {
Int_32 Window::CreateShmFile(Size size) void Window::SurfaceConfigEvent(void* data, xdg_surface* xdg_surface, UInt_32 serial)
{
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)
{ {
xdg_surface_ack_configure(xdg_surface, serial); xdg_surface_ack_configure(xdg_surface, serial);
if (data) Window* win = (Window *)data;
wl_surface_commit(((Window*)data)->wlSurface);
wl_surface_commit(win->wlSurface);
} }
void Window::ShellPing(void* data, xdg_wm_base* shell, UInt_32 serial) 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) void Window::RegistryHandler(void* data, wl_registry* registry, UInt_32 id, const char* interface, UInt_32 version)
{ {
Serializer<UInt_64>* ser = (Serializer<UInt_64>*)data; Window *win = (Window *)data;
if (Str_8::Cmp(interface, wl_compositor_interface.name)) if (Str_8::Cmp(interface, wl_compositor_interface.name))
{ win->compositor = (wl_compositor*)wl_registry_bind(registry, id, &wl_compositor_interface, 1);
ser->SetOffset(0);
wl_compositor** comp = ser->Read<wl_compositor**>();
*comp = (wl_compositor*)wl_registry_bind(registry, id, &wl_compositor_interface, 1);
}
else if (Str_8::Cmp(interface, xdg_wm_base_interface.name)) else if (Str_8::Cmp(interface, xdg_wm_base_interface.name))
{ win->xdgShell = (xdg_wm_base*)wl_registry_bind(registry, id, &xdg_wm_base_interface, 1);
ser->SetOffset(sizeof(void*));
xdg_wm_base** base = ser->Read<xdg_wm_base**>();
*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<wl_shm**>();
*shm = (wl_shm*)wl_registry_bind(registry, id, &wl_shm_interface, 1);
}
else if (Str_8::Cmp(interface, zxdg_decoration_manager_v1_interface.name)) else if (Str_8::Cmp(interface, zxdg_decoration_manager_v1_interface.name))
{ win->decManager = (zxdg_decoration_manager_v1*)wl_registry_bind(registry, id, &zxdg_decoration_manager_v1_interface, 1);
ser->SetOffset(sizeof(void*) * 3); else if (Str_8::Cmp(interface, wl_seat_interface.name))
zxdg_decoration_manager_v1** decManager = ser->Read<zxdg_decoration_manager_v1**>(); win->seat = (wl_seat *)wl_registry_bind(registry, id, &wl_seat_interface, 1);
*decManager = (zxdg_decoration_manager_v1*)wl_registry_bind(registry, id, &zxdg_decoration_manager_v1_interface, 1);
}
} }
void Window::RegistryRemoved(void* data, wl_registry* registry, UInt_32 id) 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() Window::~Window()
{ {
if (!created)
return;
zxdg_toplevel_decoration_v1_destroy(dec); zxdg_toplevel_decoration_v1_destroy(dec);
zxdg_decoration_manager_v1_destroy(decManager); zxdg_decoration_manager_v1_destroy(decManager);
wl_buffer_destroy(buffer);
wl_shm_destroy(shm);
xdg_toplevel_destroy(xdgToplevel); xdg_toplevel_destroy(xdgToplevel);
xdg_surface_destroy(xdgSurface); xdg_surface_destroy(xdgSurface);
xdg_wm_base_destroy(xdgShell); xdg_wm_base_destroy(xdgShell);
@ -138,14 +95,14 @@ namespace ehs
Window::Window() Window::Window()
: display(nullptr), registry(nullptr), compositor(nullptr), wlSurface(nullptr), xdgShell(nullptr), : 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 Window::Window(Window &&win) noexcept
: BaseWindow(win), display(win.display), registry(win.registry), compositor(win.compositor), : BaseWindow(win), display(win.display), registry(win.registry), compositor(win.compositor),
wlSurface(win.wlSurface), xdgShell(win.xdgShell), xdgSurface(win.xdgSurface), xdgToplevel(win.xdgToplevel), 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.display = nullptr;
win.registry = nullptr; win.registry = nullptr;
@ -154,16 +111,16 @@ namespace ehs
win.xdgShell = nullptr; win.xdgShell = nullptr;
win.xdgSurface = nullptr; win.xdgSurface = nullptr;
win.xdgToplevel = nullptr; win.xdgToplevel = nullptr;
win.shm = nullptr;
win.buffer = nullptr;
win.decManager = nullptr; win.decManager = nullptr;
win.dec = nullptr; win.dec = nullptr;
win.seat = nullptr;
win.pointer = nullptr;
} }
Window::Window(const Window &win) Window::Window(const Window &win)
: BaseWindow(win), display(nullptr), registry(nullptr), compositor(nullptr), wlSurface(nullptr), : BaseWindow(win), display(nullptr), registry(nullptr), compositor(nullptr), wlSurface(nullptr),
xdgShell(nullptr), xdgSurface(nullptr), xdgToplevel(nullptr), shm(nullptr), buffer(nullptr), decManager(nullptr), xdgShell(nullptr), xdgSurface(nullptr), xdgToplevel(nullptr), decManager(nullptr), dec(nullptr), seat(nullptr),
dec(nullptr) pointer(nullptr)
{ {
} }
@ -181,10 +138,10 @@ namespace ehs
xdgShell = win.xdgShell; xdgShell = win.xdgShell;
xdgSurface = win.xdgSurface; xdgSurface = win.xdgSurface;
xdgToplevel = win.xdgToplevel; xdgToplevel = win.xdgToplevel;
shm = win.shm;
buffer = win.buffer;
decManager = win.decManager; decManager = win.decManager;
dec = win.dec; dec = win.dec;
seat = win.seat;
pointer = win.pointer;
win.display = nullptr; win.display = nullptr;
win.registry = nullptr; win.registry = nullptr;
@ -193,10 +150,10 @@ namespace ehs
win.xdgShell = nullptr; win.xdgShell = nullptr;
win.xdgSurface = nullptr; win.xdgSurface = nullptr;
win.xdgToplevel = nullptr; win.xdgToplevel = nullptr;
win.shm = nullptr;
win.buffer = nullptr;
win.decManager = nullptr; win.decManager = nullptr;
win.dec = nullptr; win.dec = nullptr;
win.seat = nullptr;
win.pointer = nullptr;
return *this; return *this;
} }
@ -215,10 +172,10 @@ namespace ehs
xdgShell = nullptr; xdgShell = nullptr;
xdgSurface = nullptr; xdgSurface = nullptr;
xdgToplevel = nullptr; xdgToplevel = nullptr;
shm = nullptr;
buffer = nullptr;
decManager = nullptr; decManager = nullptr;
dec = nullptr; dec = nullptr;
seat = nullptr;
pointer = nullptr;
return *this; return *this;
} }
@ -235,6 +192,9 @@ namespace ehs
void Window::Create_8(const Str_8& title, const Vec2_s32& pos, const Vec2_u32 scale) void Window::Create_8(const Str_8& title, const Vec2_s32& pos, const Vec2_u32 scale)
{ {
if (created)
return;
display = wl_display_connect(nullptr); display = wl_display_connect(nullptr);
if (!display) if (!display)
{ {
@ -242,19 +202,13 @@ namespace ehs
return; return;
} }
Serializer<UInt_64> data(Endianness::LE);
data.Write(&compositor);
data.Write(&xdgShell);
data.Write(&shm);
data.Write(&decManager);
static constexpr wl_registry_listener registry_listener = { static constexpr wl_registry_listener registry_listener = {
RegistryHandler, .global = RegistryHandler,
RegistryRemoved .global_remove = RegistryRemoved
}; };
registry = wl_display_get_registry(display); registry = wl_display_get_registry(display);
wl_registry_add_listener(registry, &registry_listener, &data); wl_registry_add_listener(registry, &registry_listener, this);
wl_display_dispatch(display); wl_display_dispatch(display);
wl_display_roundtrip(display); wl_display_roundtrip(display);
@ -265,7 +219,9 @@ namespace ehs
return; 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); xdg_wm_base_add_listener(xdgShell, &xdg_shell_listener, nullptr);
@ -276,29 +232,34 @@ namespace ehs
return; return;
} }
CreateBuffer(scale);
xdgSurface = xdg_wm_base_get_xdg_surface(xdgShell, wlSurface); 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); xdg_surface_add_listener(xdgSurface, &surfaceListener, this);
xdgToplevel = xdg_surface_get_toplevel(xdgSurface); xdgToplevel = xdg_surface_get_toplevel(xdgSurface);
static constexpr xdg_toplevel_listener topLevelListener = { 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_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); dec = zxdg_decoration_manager_v1_get_toplevel_decoration(decManager, xdgToplevel);
zxdg_toplevel_decoration_v1_set_mode(dec, ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE); 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); wl_display_roundtrip(display);
@ -306,6 +267,9 @@ namespace ehs
wl_display_roundtrip(display); wl_display_roundtrip(display);
this->scale = scale;
created = true;
OnCreated(); OnCreated();
} }
@ -315,6 +279,15 @@ namespace ehs
void Window::Close() 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); xdg_toplevel_destroy(xdgToplevel);
xdgToplevel = nullptr; xdgToplevel = nullptr;
@ -335,6 +308,8 @@ namespace ehs
wl_display_disconnect(display); wl_display_disconnect(display);
display = nullptr; display = nullptr;
created = false;
} }
void Window::Show() void Window::Show()
@ -347,7 +322,11 @@ namespace ehs
bool Window::Poll() bool Window::Poll()
{ {
wl_display_dispatch(display); if (wl_display_dispatch_pending(display) == -1)
return false;
if (!created)
return false;
return true; return true;
} }
@ -402,7 +381,7 @@ namespace ehs
Vec2_u32 Window::GetScale() const Vec2_u32 Window::GetScale() const
{ {
return {}; return scale;
} }
Serializer<UInt_64> Window::GetClipboard() Serializer<UInt_64> Window::GetClipboard()