diff --git a/modules/surface/private/linux/system.cpp b/modules/surface/private/linux/system.cpp index 870ae27..cf41093 100644 --- a/modules/surface/private/linux/system.cpp +++ b/modules/surface/private/linux/system.cpp @@ -54,12 +54,6 @@ System::System(memory::Ref registry): m_registry(std::move(regist "Failed to initialize surface system: registry has surface component(s)" ); - m_registry->connect_on_construct( - [this](ecs::Registry ®istry, ecs::EntityId entity) { - on_surface_construct(registry, entity); - } - ); - m_registry->connect_on_destruct( [this](ecs::Registry ®istry, ecs::EntityId entity) { on_surface_destruct(registry, entity); @@ -106,97 +100,99 @@ void System::on_unregister() { } -void System::on_surface_construct(ecs::Registry ®istry, ecs::EntityId entity) +auto System::create_component(ecs::EntityId entity, SurfaceComponent::CreateInfo info) + -> std::optional +try { - try + auto &component = m_registry->add(entity, info); + auto &surface = m_registry->get(entity); + const auto &resolution = surface.get_resolution(); + const auto &position = surface.get_position(); + ensure_component_sanity(surface); + + // TODO(Light): refactor "environment" into standalone module + // NOLINTNEXTLINE(concurrency-mt-unsafe) + auto *display_env = std::getenv("DISPLAY"); + ensure(display_env != nullptr, "DISPLAY env var not found!"); + + auto *display = XOpenDisplay(display_env); + ensure(display, "Failed to open XDisplay with DISPLAY: {}", display_env); + + auto root_window = XDefaultRootWindow(display); + + auto border_width = 0; + auto depth = int32_t { CopyFromParent }; + auto window_class = CopyFromParent; + auto *visual = (Visual *)CopyFromParent; + + auto attribute_value_mask = CWBackPixel | CWEventMask; + auto attributes = XSetWindowAttributes { + .background_pixel = 0xffafe9af, + .event_mask = all_events_mask, + }; + + typedef struct Hints { - auto &surface = registry.get(entity); - const auto &resolution = surface.get_resolution(); - const auto &position = surface.get_position(); - ensure_component_sanity(surface); + unsigned long flags; + unsigned long functions; + unsigned long decorations; + long inputMode; + unsigned long status; + } Hints; - // TODO(Light): refactor "environment" into standalone module - // NOLINTNEXTLINE(concurrency-mt-unsafe) - auto *display_env = std::getenv("DISPLAY"); - ensure(display_env != nullptr, "DISPLAY env var not found!"); + auto main_window = XCreateWindow( + display, + root_window, + position.x, + position.y, + resolution.x, + resolution.y, + border_width, + depth, + window_class, + visual, + attribute_value_mask, + &attributes + ); + surface.m_native_data.display = display; + surface.m_native_data.window = main_window; - auto *display = XOpenDisplay(display_env); - ensure(display, "Failed to open XDisplay with DISPLAY: {}", display_env); + surface.m_native_data.wm_delete_message = XInternAtom(display, "WM_DELETE_WINDOW", False); + XSetWMProtocols(display, main_window, &surface.m_native_data.wm_delete_message, 1); - auto root_window = XDefaultRootWindow(display); + // code to remove decoration + auto hints = std::array { 2, 0, 0, 0, 0 }; + const auto motif_hints = XInternAtom(display, "_MOTIF_WM_HINTS", False); - auto border_width = 0; - auto depth = int32_t { CopyFromParent }; - auto window_class = CopyFromParent; - auto *visual = (Visual *)CopyFromParent; + XChangeProperty( + display, + surface.m_native_data.window, + motif_hints, + motif_hints, + 32, + PropModeReplace, + hints.data(), + 5 + ); - auto attribute_value_mask = CWBackPixel | CWEventMask; - auto attributes = XSetWindowAttributes { - .background_pixel = 0xffafe9af, - .event_mask = all_events_mask, - }; + XMapWindow(display, main_window); + XStoreName(display, main_window, surface.m_title.c_str()); + XFlush(display); - typedef struct Hints - { - unsigned long flags; - unsigned long functions; - unsigned long decorations; - long inputMode; - unsigned long status; - } Hints; - - auto main_window = XCreateWindow( - display, - root_window, - position.x, - position.y, - resolution.x, - resolution.y, - border_width, - depth, - window_class, - visual, - attribute_value_mask, - &attributes - ); - surface.m_native_data.display = display; - surface.m_native_data.window = main_window; - - surface.m_native_data.wm_delete_message = XInternAtom(display, "WM_DELETE_WINDOW", False); - XSetWMProtocols(display, main_window, &surface.m_native_data.wm_delete_message, 1); - - // code to remove decoration - auto hints = std::array { 2, 0, 0, 0, 0 }; - const auto motif_hints = XInternAtom(display, "_MOTIF_WM_HINTS", False); - - XChangeProperty( - display, - surface.m_native_data.window, - motif_hints, - motif_hints, - 32, - PropModeReplace, - hints.data(), - 5 - ); - - XMapWindow(display, main_window); - XStoreName(display, main_window, surface.m_title.c_str()); - XFlush(display); - - if (!surface.is_visible()) - { - XUnmapWindow(display, main_window); - } - } - catch (const std::exception &exp) + if (!surface.is_visible()) { - log_err("Exception thrown when on_constructing surface component"); - log_err("\tentity: {}", entity); - log_err("\twhat: {}", exp.what()); - registry.remove(entity); - throw; + XUnmapWindow(display, main_window); } + + return &component; +} +catch (const std::exception &exp) +{ + log_err("Exception thrown when on_constructing surface component"); + log_err("\tentity: {}", entity); + log_err("\twhat: {}", exp.what()); + m_registry->remove(entity); + return {}; } void System::on_surface_destruct(ecs::Registry ®istry, ecs::EntityId entity) @@ -285,7 +281,6 @@ void System::handle_events(SurfaceComponent &surface) const auto new_height = event.xconfigure.height; if (prev_width != new_width || prev_height != new_height) { - log_dbg("resized: {} - {}", new_width, new_height); surface.m_resolution.x = new_width; surface.m_resolution.y = new_height; queue.emplace_back(ResizedEvent { @@ -342,7 +337,7 @@ void System::modify_title(SurfaceComponent &surface, const ModifyTitleRequest &r void System::modify_resolution(SurfaceComponent &surface, const ModifyResolutionRequest &request) { - surface.m_resolution = request.resolution; + // surface.m_resolution = request.resolution; auto &[display, window, _] = surface.m_native_data; const auto &[width, height] = request.resolution; diff --git a/modules/surface/public/components.hpp b/modules/surface/public/components.hpp index 30fa8dd..3c231bc 100644 --- a/modules/surface/public/components.hpp +++ b/modules/surface/public/components.hpp @@ -13,7 +13,10 @@ typedef struct _XDisplay Display; namespace lt::surface { -/** Represents a platform's surface (eg. a Window). */ +/** Represents a platform's surface (eg. a Window). + * + * @note This is a "system component" + */ class SurfaceComponent { public: @@ -66,15 +69,6 @@ public: bool visible; }; - SurfaceComponent(const CreateInfo &info) - : m_title(info.title) - , m_resolution(info.resolution) - , m_vsync(info.vsync) - , m_visible(info.visible) - , m_native_data({}) - { - } - [[nodiscard]] auto get_title() const -> std::string_view { return m_title; @@ -127,6 +121,15 @@ public: } private: + SurfaceComponent(const CreateInfo &info) + : m_title(info.title) + , m_resolution(info.resolution) + , m_vsync(info.vsync) + , m_visible(info.visible) + , m_native_data({}) + { + } + std::string m_title; math::uvec2 m_resolution; diff --git a/modules/surface/public/system.hpp b/modules/surface/public/system.hpp index ad448c8..e3ce324 100644 --- a/modules/surface/public/system.hpp +++ b/modules/surface/public/system.hpp @@ -4,6 +4,7 @@ #include #include #include +#include namespace lt::surface { @@ -26,6 +27,9 @@ public: void on_unregister() override; + auto create_component(ecs::EntityId entity, SurfaceComponent::CreateInfo info) + -> std::optional; + void tick(app::TickInfo tick) override; [[nodiscard]] auto get_last_tick_result() const -> const app::TickResult & override @@ -34,8 +38,6 @@ public: } private: - void on_surface_construct(ecs::Registry ®istry, ecs::EntityId entity); - void on_surface_destruct(ecs::Registry ®istry, ecs::EntityId entity); void handle_requests(struct SurfaceComponent &surface);