// ===================================================================================================================== // fennec, a free and open source game engine // Copyright © 2025 Medusa Slockbower // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // ===================================================================================================================== #include #include #include #include #include #include using namespace fennec; wayland_window::wayland_window(display_server* server, uint32_t id, const config& cfg) : window_base(server, id, cfg) , surface(nullptr) , xdgsurface(nullptr) { } wayland_window::~wayland_window() { } void wayland_window::show() { static constexpr wl_surface_listener surface_listener = { listen_enter, listen_leave, listen_preferred_buffer_scale, listen_preferred_buffer_transform }; static constexpr xdg_surface_listener xdg_surface_listener = { listen_xdg_surface_configure }; static constexpr xdg_toplevel_listener xdg_toplevel_listener = { listen_xdg_toplevel_configure, listen_xdg_toplevel_close, listen_xdg_toplevel_configure_bounds, listen_xdg_toplevel_capabilities }; static constexpr wl_callback_listener frame_callback_listener = { listen_frame_callback }; if (is_visible()) { return; } wayland_window* root = this; while (root != nullptr and root->is_popup()) { root = static_cast(root->get_parent()); } assertf(root != nullptr, "Failed to find appropriate top-level window."); wayland_server* wl_server = static_cast(server); surface = wl_compositor_create_surface(wl_server->compositor); wl_surface_add_listener(surface, &surface_listener, this); xdgsurface = xdg_wm_base_get_xdg_surface(wl_server->xdg, surface); xdg_surface_add_listener(xdgsurface, &xdg_surface_listener, this); xdgtoplevel = xdg_surface_get_toplevel(xdgsurface); xdg_toplevel_add_listener(xdgtoplevel, &xdg_toplevel_listener, this); frame_callback = wl_surface_frame(surface); wl_callback_add_listener(frame_callback, &frame_callback_listener, this); wl_surface_commit(surface); wl_display_roundtrip(wl_server->display); cfg.flags.set(flag_visible); cfg.flags.set(flag_running); gfx_surface = wl_server->get_gfx_context()->create_surface(this); } void wayland_window::hide() { if (not is_running()) { return; } wayland_server* wl_server = static_cast(server); if (xdgtoplevel) { xdg_toplevel_destroy(xdgtoplevel); xdgtoplevel = nullptr; } if (frame_callback) { wl_callback_destroy(frame_callback); frame_callback = nullptr; } if (xdgsurface) { xdg_surface_destroy(xdgsurface); xdgsurface = nullptr; } if (surface) { wl_surface_destroy(surface); surface = nullptr; } wl_display_roundtrip(wl_server->display); cfg.flags.clear(flag_visible); cfg.flags.clear(flag_running); } void* wayland_window::get_native_handle() { return surface; } bool wayland_window::set_flag(uint8_t, bool) { return false; } void wayland_window::listen_enter(void*, wl_surface*, wl_output*) {} void wayland_window::listen_leave(void*, wl_surface*, wl_output*) {} void wayland_window::listen_preferred_buffer_scale(void*, wl_surface*, int32_t) {} void wayland_window::listen_preferred_buffer_transform(void*, wl_surface*, uint32_t) {} void wayland_window::listen_frame_callback(void*, wl_callback*, uint32_t) {} void wayland_window::listen_xdg_surface_configure(void*, xdg_surface* xdg, uint32_t serial) { xdg_surface_ack_configure(xdg, serial); } void wayland_window::listen_xdg_toplevel_configure(void*, xdg_toplevel*, int32_t, int32_t, wl_array*) {} void wayland_window::listen_xdg_toplevel_configure_bounds(void*, xdg_toplevel*, int32_t, int32_t) {} void wayland_window::listen_xdg_toplevel_close(void* data, xdg_toplevel*) { wayland_window* window = static_cast(data); window->hide(); } void wayland_window::listen_xdg_toplevel_capabilities(void*, xdg_toplevel*, wl_array*) {}