From a023811c264d17d62ab333b2ab3c8ef435bc4708 Mon Sep 17 00:00:00 2001 From: apio Date: Tue, 29 Aug 2023 15:26:34 +0200 Subject: [PATCH] libui+wind: Handle mouse leave events when the mouse leaves a window --- apps/gclient.cpp | 2 +- libui/include/ui/Button.h | 2 +- libui/include/ui/Container.h | 2 +- libui/include/ui/Image.h | 2 +- libui/include/ui/Layout.h | 4 ++-- libui/include/ui/Widget.h | 2 +- libui/include/ui/Window.h | 1 + libui/include/ui/ipc/Client.h | 8 ++++++++ libui/src/App.cpp | 8 ++++++++ libui/src/Button.cpp | 4 ++-- libui/src/Container.cpp | 4 ++-- libui/src/Image.cpp | 2 +- libui/src/Layout.cpp | 12 ++++++------ libui/src/Window.cpp | 7 +++++++ wind/Mouse.cpp | 14 ++++++++++++++ wind/Mouse.h | 2 ++ 16 files changed, 58 insertions(+), 18 deletions(-) diff --git a/apps/gclient.cpp b/apps/gclient.cpp index 404f6f8c..ba08db5d 100644 --- a/apps/gclient.cpp +++ b/apps/gclient.cpp @@ -14,7 +14,7 @@ struct ColorWidget : public ui::Widget return ui::EventResult::DidHandle; } - Result handle_mouse_leave(ui::Point) override + Result handle_mouse_leave() override { m_color = m_first_color; return ui::EventResult::DidHandle; diff --git a/libui/include/ui/Button.h b/libui/include/ui/Button.h index f2715f5b..aa01dab1 100644 --- a/libui/include/ui/Button.h +++ b/libui/include/ui/Button.h @@ -21,7 +21,7 @@ namespace ui void set_action(void (*action)(void)); Result handle_mouse_move(Point position) override; - Result handle_mouse_leave(Point position) override; + Result handle_mouse_leave() override; Result handle_mouse_down(Point position, int buttons) override; Result handle_mouse_up(Point position, int buttons) override; Result draw(Canvas& canvas) override; diff --git a/libui/include/ui/Container.h b/libui/include/ui/Container.h index 6bd703a2..aec537d7 100644 --- a/libui/include/ui/Container.h +++ b/libui/include/ui/Container.h @@ -21,7 +21,7 @@ namespace ui void set_widget(Widget& widget); Result handle_mouse_move(Point position) override; - Result handle_mouse_leave(Point position) override; + Result handle_mouse_leave() override; Result handle_mouse_down(Point position, int buttons) override; Result handle_mouse_up(Point position, int buttons) override; Result draw(Canvas& canvas) override; diff --git a/libui/include/ui/Image.h b/libui/include/ui/Image.h index 2db7579f..481154f6 100644 --- a/libui/include/ui/Image.h +++ b/libui/include/ui/Image.h @@ -85,7 +85,7 @@ namespace ui static Result> load(const os::Path& path); Result handle_mouse_move(Point position) override; - Result handle_mouse_leave(Point position) override; + Result handle_mouse_leave() override; Result handle_mouse_down(Point position, int buttons) override; Result handle_mouse_up(Point position, int buttons) override; Result draw(Canvas& canvas) override; diff --git a/libui/include/ui/Layout.h b/libui/include/ui/Layout.h index 47b54fda..62ebe8c8 100644 --- a/libui/include/ui/Layout.h +++ b/libui/include/ui/Layout.h @@ -31,7 +31,7 @@ namespace ui HorizontalLayout(AdjustHeight adjust_height = AdjustHeight::Yes, AdjustWidth adjust_width = AdjustWidth::Yes); Result handle_mouse_move(Point position) override; - Result handle_mouse_leave(Point position) override; + Result handle_mouse_leave() override; Result handle_mouse_down(Point position, int buttons) override; Result handle_mouse_up(Point position, int buttons) override; @@ -52,7 +52,7 @@ namespace ui VerticalLayout(AdjustHeight adjust_height = AdjustHeight::Yes, AdjustWidth adjust_width = AdjustWidth::Yes); Result handle_mouse_move(Point position) override; - Result handle_mouse_leave(Point position) override; + Result handle_mouse_leave() override; Result handle_mouse_down(Point position, int buttons) override; Result handle_mouse_up(Point position, int buttons) override; diff --git a/libui/include/ui/Widget.h b/libui/include/ui/Widget.h index 74ee1435..cd40f1bd 100644 --- a/libui/include/ui/Widget.h +++ b/libui/include/ui/Widget.h @@ -29,7 +29,7 @@ namespace ui virtual Result handle_mouse_move(Point position); virtual Result handle_mouse_down(Point position, int buttons); virtual Result handle_mouse_up(Point position, int buttons); - virtual Result handle_mouse_leave(Point position); + virtual Result handle_mouse_leave(); virtual Result draw(Canvas& canvas); diff --git a/libui/include/ui/Window.h b/libui/include/ui/Window.h index 9f440a36..ede664d8 100644 --- a/libui/include/ui/Window.h +++ b/libui/include/ui/Window.h @@ -46,6 +46,7 @@ namespace ui void close(); Result draw(); + Result handle_mouse_leave(); Result handle_mouse_move(ui::Point position); Result handle_mouse_buttons(ui::Point position, int buttons); diff --git a/libui/include/ui/ipc/Client.h b/libui/include/ui/ipc/Client.h index 16f6bf68..6e277066 100644 --- a/libui/include/ui/ipc/Client.h +++ b/libui/include/ui/ipc/Client.h @@ -19,6 +19,7 @@ namespace ui CREATE_WINDOW_RESPONSE_ID, WINDOW_CLOSE_REQUEST_ID, MOUSE_EVENT_REQUEST_ID, + MOUSE_LEAVE_REQUEST_ID, GET_SCREEN_RECT_RESPONSE_ID }; @@ -46,6 +47,13 @@ namespace ui int buttons; }; + struct MouseLeaveRequest + { + static constexpr u8 ID = MOUSE_LEAVE_REQUEST_ID; + + int window; + }; + struct GetScreenRectResponse { static constexpr u8 ID = GET_SCREEN_RECT_RESPONSE_ID; diff --git a/libui/src/App.cpp b/libui/src/App.cpp index 78e5f8e5..20496e8e 100644 --- a/libui/src/App.cpp +++ b/libui/src/App.cpp @@ -122,6 +122,14 @@ namespace ui window->draw(); return {}; } + case MOUSE_LEAVE_REQUEST_ID: { + MouseLeaveRequest request; + READ_MESSAGE(request); + auto* window = find_window(request.window); + window->handle_mouse_leave(); + window->draw(); + return {}; + } default: fail("Unexpected IPC request from server!"); } } diff --git a/libui/src/Button.cpp b/libui/src/Button.cpp index 487cfa53..08c50d15 100644 --- a/libui/src/Button.cpp +++ b/libui/src/Button.cpp @@ -35,10 +35,10 @@ namespace ui return m_child->handle_mouse_move(position); } - Result Button::handle_mouse_leave(Point position) + Result Button::handle_mouse_leave() { m_hovered = m_clicked = false; - return m_child->handle_mouse_leave(position); + return m_child->handle_mouse_leave(); } Result Button::handle_mouse_down(Point position, int buttons) diff --git a/libui/src/Container.cpp b/libui/src/Container.cpp index 876013ac..d188a07f 100644 --- a/libui/src/Container.cpp +++ b/libui/src/Container.cpp @@ -29,9 +29,9 @@ namespace ui return m_widget->handle_mouse_move(position); } - Result Container::handle_mouse_leave(Point position) + Result Container::handle_mouse_leave() { - return m_widget->handle_mouse_leave(position); + return m_widget->handle_mouse_leave(); } Result Container::handle_mouse_down(Point position, int buttons) diff --git a/libui/src/Image.cpp b/libui/src/Image.cpp index 050bef2b..70db97bc 100644 --- a/libui/src/Image.cpp +++ b/libui/src/Image.cpp @@ -45,7 +45,7 @@ namespace ui return EventResult::DidNotHandle; } - Result ImageWidget::handle_mouse_leave(Point) + Result ImageWidget::handle_mouse_leave() { return EventResult::DidNotHandle; } diff --git a/libui/src/Layout.cpp b/libui/src/Layout.cpp index 4beeb1a4..8df908c5 100644 --- a/libui/src/Layout.cpp +++ b/libui/src/Layout.cpp @@ -25,15 +25,15 @@ namespace ui { if (widget->rect().contains(position)) result = TRY(widget->handle_mouse_move(position)); else - TRY(widget->handle_mouse_leave(position)); + TRY(widget->handle_mouse_leave()); } return result; } - Result HorizontalLayout::handle_mouse_leave(Point position) + Result HorizontalLayout::handle_mouse_leave() { - for (auto widget : m_widgets) TRY(widget->handle_mouse_leave(position)); + for (auto widget : m_widgets) TRY(widget->handle_mouse_leave()); return ui::EventResult::DidNotHandle; } @@ -114,15 +114,15 @@ namespace ui { if (widget->rect().contains(position)) result = TRY(widget->handle_mouse_move(position)); else - TRY(widget->handle_mouse_leave(position)); + TRY(widget->handle_mouse_leave()); } return result; } - Result VerticalLayout::handle_mouse_leave(Point position) + Result VerticalLayout::handle_mouse_leave() { - for (auto widget : m_widgets) TRY(widget->handle_mouse_leave(position)); + for (auto widget : m_widgets) TRY(widget->handle_mouse_leave()); return ui::EventResult::DidNotHandle; } diff --git a/libui/src/Window.cpp b/libui/src/Window.cpp index cbbfc068..29b197e9 100644 --- a/libui/src/Window.cpp +++ b/libui/src/Window.cpp @@ -101,6 +101,13 @@ namespace ui return {}; } + Result Window::handle_mouse_leave() + { + if (!m_main_widget) return {}; + TRY(m_main_widget->handle_mouse_leave()); + return {}; + } + Result Window::handle_mouse_move(ui::Point position) { if (!m_main_widget) return {}; diff --git a/wind/Mouse.cpp b/wind/Mouse.cpp index 7f3d72e2..0ba7d1ea 100644 --- a/wind/Mouse.cpp +++ b/wind/Mouse.cpp @@ -79,6 +79,8 @@ void Mouse::update(const moon::MousePacket& packet) } } + Window* new_active_window = nullptr; + for (Window* window = g_windows.last().value_or(nullptr); window; window = g_windows.previous(window).value_or(nullptr)) { @@ -92,7 +94,19 @@ void Mouse::update(const moon::MousePacket& packet) request.position = contents.relative(m_position); request.buttons = packet.buttons; os::IPC::send_async(window->client->conn, request); + new_active_window = window; break; } } + + if (m_active_window != new_active_window) + { + if (m_active_window) + { + ui::MouseLeaveRequest request; + request.window = m_active_window->id; + os::IPC::send_async(m_active_window->client->conn, request); + } + m_active_window = new_active_window; + } } diff --git a/wind/Mouse.h b/wind/Mouse.h index 17d79c6d..bee42f4c 100644 --- a/wind/Mouse.h +++ b/wind/Mouse.h @@ -19,4 +19,6 @@ class Mouse Window* m_dragging_window = nullptr; ui::Point m_initial_drag_position; + + Window* m_active_window = nullptr; };