From fa2e5f80bc97154f0beda1c4a8cfbeb30eb269a6 Mon Sep 17 00:00:00 2001 From: Qwinci <32550582+Qwinci@users.noreply.github.com> Date: Wed, 16 Oct 2024 22:23:41 +0300 Subject: [PATCH] apps/desktop: Close windows if owning connection is closed --- apps/desktop/src/main.cpp | 161 +++++++++++++++++++++----------------- 1 file changed, 91 insertions(+), 70 deletions(-) diff --git a/apps/desktop/src/main.cpp b/apps/desktop/src/main.cpp index 65e3b8d..0c85d51 100644 --- a/apps/desktop/src/main.cpp +++ b/apps/desktop/src/main.cpp @@ -58,10 +58,12 @@ struct Connection { CrescentHandle event; }; -static NoDestroy> CONNECTIONS {}; +// todo mutex +static NoDestroy>> CONNECTIONS {}; struct WindowInfo { Window* window; + Connection* connection; CrescentHandle event_pipe; }; @@ -143,10 +145,11 @@ void listener_thread(void* arg) { // todo check status while (sys_socket_send(connection_socket, &resp, sizeof(resp)) == ERR_TRY_AGAIN); - CONNECTIONS->push_back({ + CONNECTIONS->push_back(std::make_unique(Connection { .process = peer_addr.target, .control = connection_socket, - .event = event_write_handle}); + .event = event_write_handle + })); } } @@ -166,6 +169,66 @@ void send_event_to_window(Window* window, protocol::WindowEvent event) { sys_write(event_pipe, &event, 0, sizeof(event)); } +static void destroy_window(Desktop& desktop, Window* window) { + if (window->parent->active_child == window) { + window->parent->active_child = nullptr; + } + + desktop.dragging = nullptr; + + if (desktop.last_mouse_over == window || + desktop.last_mouse_over == window->titlebar.get()) { + desktop.last_mouse_over = nullptr; + } + else { + std::vector stack; + stack.push_back(window); + if (!window->no_decorations) { + stack.push_back(window->titlebar.get()); + } + + while (!stack.empty()) { + auto entry = stack.back(); + stack.pop_back(); + if (desktop.last_mouse_over == entry) { + desktop.last_mouse_over = nullptr; + } + + for (auto& child : entry->children) { + stack.push_back(child.get()); + } + } + } + + for (size_t i = 0; i < window->parent->children.size(); ++i) { + if (window->parent->children[i].get() == window) { + auto dirty_rect = window->get_abs_rect(); + if (!window->no_decorations) { + dirty_rect.width += BORDER_WIDTH * 2; + dirty_rect.height += TITLEBAR_HEIGHT + BORDER_WIDTH; + } + desktop.ctx.dirty_rects.push_back(dirty_rect); + + window->parent->children.erase( + window->parent->children.begin() + + static_cast>::difference_type>(i)); + break; + } + } + + for (size_t i = 0; i < WINDOW_TO_INFO->size(); ++i) { + auto& iter = (*WINDOW_TO_INFO)[i]; + if (iter.window == window) { + assert(sys_unmap(window->fb, window->rect.width * window->rect.height * 4) == 0); + + WINDOW_TO_INFO->erase( + WINDOW_TO_INFO->begin() + + static_cast>::difference_type>(i)); + break; + } + } +} + int main() { //dumb_loop(); @@ -327,10 +390,28 @@ int main() { for (auto& connection : *CONNECTIONS) { protocol::Request req {}; size_t received; - auto req_status = sys_socket_receive(connection.control, &req, sizeof(req), received); + auto req_status = sys_socket_receive(connection->control, &req, sizeof(req), received); if (req_status == ERR_TRY_AGAIN) { continue; } + else if (req_status == ERR_INVALID_ARGUMENT) { + assert(sys_close_handle(connection->process) == 0); + assert(sys_close_handle(connection->control) == 0); + assert(sys_close_handle(connection->event) == 0); + + for (size_t i = 0; i < WINDOW_TO_INFO->size();) { + auto& window_info = (*WINDOW_TO_INFO)[i]; + if (window_info.connection == connection.get()) { + destroy_window(desktop, window_info.window); + } + else { + ++i; + } + } + + CONNECTIONS->erase(&connection); + continue; + } // todo check status and size @@ -347,7 +428,7 @@ int main() { CrescentHandle fb_shared_mem_handle; sys_shared_mem_alloc(fb_shared_mem_handle, window->rect.width * window->rect.height * 4); CrescentHandle fb_shareable_handle; - sys_shared_mem_share(fb_shared_mem_handle, connection.process, fb_shareable_handle); + sys_shared_mem_share(fb_shared_mem_handle, connection->process, fb_shareable_handle); sys_shared_mem_map(fb_shared_mem_handle, reinterpret_cast(&window->fb)); memset(window->fb, 0, window->rect.width * window->rect.height * 4); sys_close_handle(fb_shared_mem_handle); @@ -370,79 +451,19 @@ int main() { WINDOW_TO_INFO->push_back({ .window = window_ptr, - .event_pipe = connection.event + .connection = connection.get(), + .event_pipe = connection->event }); // todo check status - while (sys_socket_send(connection.control, &resp, sizeof(resp)) == ERR_TRY_AGAIN); + while (sys_socket_send(connection->control, &resp, sizeof(resp)) == ERR_TRY_AGAIN); break; } case protocol::Request::CloseWindow: { auto* window = static_cast(req.close_window.window_handle); - - if (window->parent->active_child == window) { - window->parent->active_child = nullptr; - } - - desktop.dragging = nullptr; - - if (desktop.last_mouse_over == window || - desktop.last_mouse_over == window->titlebar.get()) { - desktop.last_mouse_over = nullptr; - } - else { - std::vector stack; - stack.push_back(window); - if (!window->no_decorations) { - stack.push_back(window->titlebar.get()); - } - - while (!stack.empty()) { - auto entry = stack.back(); - stack.pop_back(); - if (desktop.last_mouse_over == entry) { - desktop.last_mouse_over = nullptr; - } - - for (auto& child : entry->children) { - stack.push_back(child.get()); - } - } - } - - for (size_t i = 0; i < window->parent->children.size(); ++i) { - if (window->parent->children[i].get() == window) { - auto dirty_rect = window->get_abs_rect(); - if (!window->no_decorations) { - dirty_rect.width += BORDER_WIDTH * 2; - dirty_rect.height += TITLEBAR_HEIGHT + BORDER_WIDTH; - } - ctx.dirty_rects.push_back(dirty_rect); - - window->parent->children.erase( - window->parent->children.begin() + - static_cast>::difference_type>(i)); - break; - } - } - - for (size_t i = 0; i < WINDOW_TO_INFO->size(); ++i) { - auto& iter = (*WINDOW_TO_INFO)[i]; - if (iter.window == window) { - assert(sys_unmap(window->fb, window->rect.width * window->rect.height * 4) == 0); - - WINDOW_TO_INFO->erase( - WINDOW_TO_INFO->begin() + - static_cast>::difference_type>(i)); - break; - } - } - - // todo check status - while (sys_socket_send(connection.control, &resp, sizeof(resp)) == ERR_TRY_AGAIN); - + destroy_window(desktop, window); break; } case protocol::Request::Redraw: @@ -452,7 +473,7 @@ int main() { resp.ack.window_handle = window; // todo check status - while (sys_socket_send(connection.control, &resp, sizeof(resp)) == ERR_TRY_AGAIN); + while (sys_socket_send(connection->control, &resp, sizeof(resp)) == ERR_TRY_AGAIN); break; }