From 6bd51ac3459d828988245b6dd9d07d1cb1847961 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Sun, 10 Nov 2024 14:02:23 +0200 Subject: [PATCH] LibGUI: Client window now exits if it loses connection from server This can be prevented by installing callback for socket errors. --- userspace/libraries/LibGUI/Window.cpp | 64 ++++++++++--------- .../libraries/LibGUI/include/LibGUI/Window.h | 17 +++-- userspace/programs/TaskBar/main.cpp | 3 +- 3 files changed, 46 insertions(+), 38 deletions(-) diff --git a/userspace/libraries/LibGUI/Window.cpp b/userspace/libraries/LibGUI/Window.cpp index 783fdcaf..5d68d769 100644 --- a/userspace/libraries/LibGUI/Window.cpp +++ b/userspace/libraries/LibGUI/Window.cpp @@ -59,8 +59,7 @@ namespace LibGUI Window::~Window() { - munmap(m_framebuffer_smo, m_width * m_height * 4); - close(m_server_fd); + clear(); } BAN::ErrorOr> Window::create(uint32_t width, uint32_t height, BAN::StringView title) @@ -244,10 +243,10 @@ namespace LibGUI return true; } - bool Window::invalidate(int32_t x, int32_t y, uint32_t width, uint32_t height) + void Window::invalidate(int32_t x, int32_t y, uint32_t width, uint32_t height) { if (!clamp_to_framebuffer(x, y, width, height)) - return true; + return; for (uint32_t i = 0; i < height; i++) memcpy(&m_framebuffer_smo[(y + i) * m_width + x], &m_framebuffer[(y + i) * m_width + x], width * sizeof(uint32_t)); @@ -259,56 +258,59 @@ namespace LibGUI packet.height = height; if (auto ret = packet.send_serialized(m_server_fd); ret.is_error()) - { - dprintln("failed to invalidate window: {}", ret.error()); - return false; - } - - return true; + return on_socket_error(__FUNCTION__); } - bool Window::set_mouse_capture(bool captured) + void Window::set_mouse_capture(bool captured) { WindowPacket::WindowSetMouseCapture packet; packet.captured = captured; if (auto ret = packet.send_serialized(m_server_fd); ret.is_error()) - { - dprintln("failed to set mouse capture: {}", ret.error()); - return false; - } - - return true; + return on_socket_error(__FUNCTION__); } - bool Window::set_position(int32_t x, int32_t y) + void Window::set_position(int32_t x, int32_t y) { WindowPacket::WindowSetPosition packet; packet.x = x; packet.y = y; if (auto ret = packet.send_serialized(m_server_fd); ret.is_error()) - { - dprintln("failed to set window position: {}", ret.error()); - return false; - } - - return true; + return on_socket_error(__FUNCTION__); } - bool Window::set_attributes(Attributes attributes) + void Window::set_attributes(Attributes attributes) { WindowPacket::WindowSetAttributes packet; packet.attributes = attributes; if (auto ret = packet.send_serialized(m_server_fd); ret.is_error()) - { - dprintln("failed to set window attributes: {}", ret.error()); - return false; - } + return on_socket_error(__FUNCTION__); m_attributes = attributes; - return true; + } + + void Window::on_socket_error(BAN::StringView function) + { + if (m_handling_socket_error) + return; + m_handling_socket_error = true; + + dprintln("Socket error while running Window::{}", function); + + if (!m_socket_error_callback) + exit(1); + + m_socket_error_callback(); + clear(); + } + + void Window::clear() + { + munmap(m_framebuffer_smo, m_width * m_height * 4); + close(m_server_fd); + m_server_fd = -1; } #define TRY_OR_BREAK(...) ({ auto&& e = (__VA_ARGS__); if (e.is_error()) break; e.release_value(); }) @@ -328,7 +330,7 @@ namespace LibGUI auto packet_or_error = recv_packet(m_server_fd); if (packet_or_error.is_error()) - break; + return on_socket_error(__FUNCTION__); const auto [packet_type, packet_data] = packet_or_error.release_value(); switch (packet_type) diff --git a/userspace/libraries/LibGUI/include/LibGUI/Window.h b/userspace/libraries/LibGUI/include/LibGUI/Window.h index 756b7ac6..2e2bea8b 100644 --- a/userspace/libraries/LibGUI/include/LibGUI/Window.h +++ b/userspace/libraries/LibGUI/include/LibGUI/Window.h @@ -57,20 +57,21 @@ namespace LibGUI // fill_color is used when copying data outside of window bounds void copy_horizontal_slice(int32_t dst_y, int32_t src_y, uint32_t amount, uint32_t fill_color); - bool invalidate(int32_t x, int32_t y, uint32_t width, uint32_t height); - bool invalidate() { return invalidate(0, 0, width(), height()); } + void invalidate(int32_t x, int32_t y, uint32_t width, uint32_t height); + void invalidate() { return invalidate(0, 0, width(), height()); } - bool set_mouse_capture(bool captured); + void set_mouse_capture(bool captured); - bool set_position(int32_t x, int32_t y); + void set_position(int32_t x, int32_t y); Attributes get_attributes() const { return m_attributes; } - bool set_attributes(Attributes attributes); + void set_attributes(Attributes attributes); uint32_t width() const { return m_width; } uint32_t height() const { return m_height; } void poll_events(); + void set_socket_error_callback(BAN::Function callback) { m_socket_error_callback = callback; } void set_close_window_event_callback(BAN::Function callback) { m_close_window_event_callback = callback; } void set_key_event_callback(BAN::Function callback) { m_key_event_callback = callback; } void set_mouse_button_event_callback(BAN::Function callback) { m_mouse_button_event_callback = callback; } @@ -90,9 +91,14 @@ namespace LibGUI bool clamp_to_framebuffer(int32_t& x, int32_t& y, uint32_t& width, uint32_t& height) const; + void on_socket_error(BAN::StringView function); + void clear(); + private: int m_server_fd; + bool m_handling_socket_error { false }; + Attributes m_attributes; BAN::Vector m_framebuffer; @@ -100,6 +106,7 @@ namespace LibGUI uint32_t m_width; uint32_t m_height; + BAN::Function m_socket_error_callback; BAN::Function m_close_window_event_callback; BAN::Function m_key_event_callback; BAN::Function m_mouse_button_event_callback; diff --git a/userspace/programs/TaskBar/main.cpp b/userspace/programs/TaskBar/main.cpp index 3067c292..a286a404 100644 --- a/userspace/programs/TaskBar/main.cpp +++ b/userspace/programs/TaskBar/main.cpp @@ -53,8 +53,7 @@ int main() window->fill_rect(text_x, text_y, text_w, text_h, bg_color); window->draw_text(text, font, text_x, text_y, fg_color); - if (!window->invalidate(text_x, text_y, text_w, text_h)) - is_running = false; + window->invalidate(text_x, text_y, text_w, text_h); }; while (is_running)