#include "ehs/io/Window_Way.h" #include #include #include "ehs/io/Console.h" #include "ehs/io/xdg-shell-client-protocol.h" 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) { xdg_surface_ack_configure(xdg_surface, serial); if (data) wl_surface_commit(((Window*)data)->wlSurface); } void Window::ShellPing(void* data, xdg_wm_base* shell, UInt_32 serial) { xdg_wm_base_pong(shell, serial); } void Window::RegistryHandler(void* data, wl_registry* registry, UInt_32 id, const char* interface, UInt_32 version) { Serializer* ser = (Serializer*)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); } 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); } 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); } } 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) { Console::Write_8("Resolution: " + Str_8::FromNum(width) + "x" + Str_8::FromNum(height)); } Window::~Window() { 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); wl_surface_destroy(wlSurface); wl_compositor_destroy(compositor); wl_registry_destroy(registry); wl_display_disconnect(display); } Window::Window() : display(nullptr), registry(nullptr), compositor(nullptr), wlSurface(nullptr), xdgShell(nullptr), xdgSurface(nullptr), xdgToplevel(nullptr), shm(nullptr), buffer(nullptr), decManager(nullptr), dec(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) { win.display = nullptr; win.registry = nullptr; win.compositor = nullptr; win.wlSurface = nullptr; win.xdgShell = nullptr; win.xdgSurface = nullptr; win.xdgToplevel = nullptr; win.shm = nullptr; win.buffer = nullptr; win.decManager = nullptr; win.dec = 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) { } Window & Window::operator=(Window &&win) noexcept { if (this == &win) return *this; BaseWindow::operator=(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; win.display = nullptr; win.registry = nullptr; win.compositor = nullptr; win.wlSurface = nullptr; win.xdgShell = nullptr; win.xdgSurface = nullptr; win.xdgToplevel = nullptr; win.shm = nullptr; win.buffer = nullptr; win.decManager = nullptr; win.dec = nullptr; return *this; } Window & Window::operator=(const Window &win) { if (this == &win) return *this; BaseWindow::operator=(win); display = nullptr; registry = nullptr; compositor = nullptr; wlSurface = nullptr; xdgShell = nullptr; xdgSurface = nullptr; xdgToplevel = nullptr; shm = nullptr; buffer = nullptr; decManager = nullptr; dec = nullptr; return *this; } void Window::Create_32(const Str_32& title, const Vec2_s32& pos, const Vec2_u32 scale) { Create_8(UTF::To_8(title), pos, scale); } void Window::Create_16(const Str_16& title, const Vec2_s32& pos, const Vec2_u32 scale) { Create_8(UTF::To_8(title), pos, scale); } void Window::Create_8(const Str_8& title, const Vec2_s32& pos, const Vec2_u32 scale) { display = wl_display_connect(nullptr); if (!display) { EHS_LOG_INT(LogType::ERR, 0, "Failed to connect to display server."); 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 }; registry = wl_display_get_registry(display); wl_registry_add_listener(registry, ®istry_listener, &data); wl_display_dispatch(display); wl_display_roundtrip(display); if (!compositor || !xdgShell) { EHS_LOG_INT(LogType::ERR, 1, "Can't find required interfaces."); return; } static constexpr xdg_wm_base_listener xdg_shell_listener = {ShellPing}; xdg_wm_base_add_listener(xdgShell, &xdg_shell_listener, nullptr); wlSurface = wl_compositor_create_surface(compositor); if (!wlSurface) { EHS_LOG_INT(LogType::ERR, 2, "Can't create surface."); return; } CreateBuffer(scale); xdgSurface = xdg_wm_base_get_xdg_surface(xdgShell, wlSurface); static constexpr xdg_surface_listener surfaceListener = {SurfaceConfigure}; xdg_surface_add_listener(xdgSurface, &surfaceListener, this); xdgToplevel = xdg_surface_get_toplevel(xdgSurface); static constexpr xdg_toplevel_listener topLevelListener = { .configure = Resolution }; xdg_toplevel_add_listener(xdgToplevel, &topLevelListener, nullptr); xdg_toplevel_set_title(xdgToplevel, title); xdg_toplevel_set_app_id(xdgToplevel, "dsadasfsaAS"); 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); wl_display_roundtrip(display); wl_surface_commit(wlSurface); wl_display_roundtrip(display); OnCreated(); } void Window::OnCreated() { } void Window::Close() { xdg_toplevel_destroy(xdgToplevel); xdgToplevel = nullptr; xdg_surface_destroy(xdgSurface); xdgSurface = nullptr; xdg_wm_base_destroy(xdgShell); xdgShell = nullptr; wl_surface_destroy(wlSurface); wlSurface = nullptr; wl_compositor_destroy(compositor); compositor = nullptr; wl_registry_destroy(registry); registry = nullptr; wl_display_disconnect(display); display = nullptr; } void Window::Show() { } void Window::Hide() { } bool Window::Poll() { wl_display_dispatch(display); return true; } void Window::ShowCursor(bool toggle) { } void Window::ConstrainCursor(const bool constrain) { } void Window::SetTitle_32(const Str_32& newTitle) { } Str_32 Window::GetTitle_32() const { return {}; } void Window::SetTitle_16(const Str_16& newTitle) { } Str_16 Window::GetTitle_16() const { return {}; } void Window::SetTitle_8(const Str_8& newTitle) { } Str_8 Window::GetTitle_8() const { return {}; } void Window::SetPos(const Vec2_s32& newPos) { } Vec2_s32 Window::GetPos() const { return {}; } void Window::SetScale(const Vec2_u32& newScale) { } Vec2_u32 Window::GetScale() const { return {}; } Serializer Window::GetClipboard() { return {}; } void Window::SetClipboard(Serializer data) { } void Window::SetCursorImg(const CursorImg img) { } }