From 5367bbb82c5ff5f2bb657b6f93ec79807ebc57d5 Mon Sep 17 00:00:00 2001 From: Linus Groh Date: Sun, 4 Apr 2021 00:02:22 +0200 Subject: [PATCH] LibGUI: Add ScreenRectChangeEvent and deliver it to windows and widgets Having to rely on GUI::Desktop's on_rect_change is quite limiting and a bit awkward (continuing to use it would mean having to setup the callback in every application using a webview) - we need a better way of letting widgets know of a screen rect change automatically. The specific use case will be IPWV/OOPWV which need to keep track of the screen rect and notify the WebContent service of any change (which on its own deliberately can't interact with WindowServer at all). It'll also be useful for notification windows and the taskbar, which currently both rely on the GUI::Desktop callback but will now be able to listen and react to the event themselves. --- Userland/Libraries/LibGUI/Event.h | 15 ++++++++++++ Userland/Libraries/LibGUI/Forward.h | 1 + Userland/Libraries/LibGUI/Widget.cpp | 4 ++++ Userland/Libraries/LibGUI/Widget.h | 1 + Userland/Libraries/LibGUI/Window.cpp | 23 +++++++++++++++++++ Userland/Libraries/LibGUI/Window.h | 2 ++ .../LibGUI/WindowServerConnection.cpp | 3 +++ 7 files changed, 49 insertions(+) diff --git a/Userland/Libraries/LibGUI/Event.h b/Userland/Libraries/LibGUI/Event.h index 0841e2026d..5f841cff02 100644 --- a/Userland/Libraries/LibGUI/Event.h +++ b/Userland/Libraries/LibGUI/Event.h @@ -71,6 +71,7 @@ public: DragMove, Drop, ThemeChange, + ScreenRectChange, __Begin_WM_Events, WM_WindowRemoved, @@ -399,6 +400,20 @@ public: } }; +class ScreenRectChangeEvent final : public Event { +public: + explicit ScreenRectChangeEvent(const Gfx::IntRect& rect) + : Event(Type::ScreenRectChange) + , m_rect(rect) + { + } + + const Gfx::IntRect& rect() const { return m_rect; } + +private: + Gfx::IntRect m_rect; +}; + class FocusEvent final : public Event { public: explicit FocusEvent(Type type, FocusSource source) diff --git a/Userland/Libraries/LibGUI/Forward.h b/Userland/Libraries/LibGUI/Forward.h index 7e9e2948cd..e25c63c7c6 100644 --- a/Userland/Libraries/LibGUI/Forward.h +++ b/Userland/Libraries/LibGUI/Forward.h @@ -72,6 +72,7 @@ class Painter; class RadioButton; class ResizeCorner; class ResizeEvent; +class ScreenRectChangeEvent; class ScrollBar; class ScrollableWidget; class Slider; diff --git a/Userland/Libraries/LibGUI/Widget.cpp b/Userland/Libraries/LibGUI/Widget.cpp index 0a4b406949..2097d828ef 100644 --- a/Userland/Libraries/LibGUI/Widget.cpp +++ b/Userland/Libraries/LibGUI/Widget.cpp @@ -556,6 +556,10 @@ void Widget::theme_change_event(ThemeChangeEvent&) { } +void Widget::screen_rect_change_event(ScreenRectChangeEvent&) +{ +} + void Widget::update() { if (rect().is_empty()) diff --git a/Userland/Libraries/LibGUI/Widget.h b/Userland/Libraries/LibGUI/Widget.h index f9829a1843..45a2411fd2 100644 --- a/Userland/Libraries/LibGUI/Widget.h +++ b/Userland/Libraries/LibGUI/Widget.h @@ -342,6 +342,7 @@ protected: virtual void drag_leave_event(Event&); virtual void drop_event(DropEvent&); virtual void theme_change_event(ThemeChangeEvent&); + virtual void screen_rect_change_event(ScreenRectChangeEvent&); virtual void did_begin_inspection() override; virtual void did_end_inspection() override; diff --git a/Userland/Libraries/LibGUI/Window.cpp b/Userland/Libraries/LibGUI/Window.cpp index e0ddab3d25..a67effb791 100644 --- a/Userland/Libraries/LibGUI/Window.cpp +++ b/Userland/Libraries/LibGUI/Window.cpp @@ -507,6 +507,22 @@ void Window::handle_theme_change_event(ThemeChangeEvent& event) dispatch_theme_change(*m_main_widget.ptr(), dispatch_theme_change); } +void Window::handle_screen_rect_change_event(ScreenRectChangeEvent& event) +{ + if (!m_main_widget) + return; + auto dispatch_screen_rect_change = [&](auto& widget, auto recursive) { + widget.dispatch_event(event, this); + widget.for_each_child_widget([&](auto& widget) -> IterationDecision { + widget.dispatch_event(event, this); + recursive(widget, recursive); + return IterationDecision::Continue; + }); + }; + dispatch_screen_rect_change(*m_main_widget.ptr(), dispatch_screen_rect_change); + screen_rect_change_event(event); +} + void Window::handle_drag_move_event(DragEvent& event) { if (!m_main_widget) @@ -574,6 +590,9 @@ void Window::event(Core::Event& event) if (event.type() == Event::ThemeChange) return handle_theme_change_event(static_cast(event)); + if (event.type() == Event::ScreenRectChange) + return handle_screen_rect_change_event(static_cast(event)); + Core::Object::event(event); } @@ -799,6 +818,10 @@ void Window::wm_event(WMEvent&) { } +void Window::screen_rect_change_event(ScreenRectChangeEvent&) +{ +} + void Window::set_icon(const Gfx::Bitmap* icon) { if (m_icon == icon) diff --git a/Userland/Libraries/LibGUI/Window.h b/Userland/Libraries/LibGUI/Window.h index 06bea7ef55..a3675484f3 100644 --- a/Userland/Libraries/LibGUI/Window.h +++ b/Userland/Libraries/LibGUI/Window.h @@ -216,6 +216,7 @@ public: protected: Window(Core::Object* parent = nullptr); virtual void wm_event(WMEvent&); + virtual void screen_rect_change_event(ScreenRectChangeEvent&); private: void update_cursor(); @@ -230,6 +231,7 @@ private: void handle_became_active_or_inactive_event(Core::Event&); void handle_close_request(); void handle_theme_change_event(ThemeChangeEvent&); + void handle_screen_rect_change_event(ScreenRectChangeEvent&); void handle_drag_move_event(DragEvent&); void handle_left_event(); diff --git a/Userland/Libraries/LibGUI/WindowServerConnection.cpp b/Userland/Libraries/LibGUI/WindowServerConnection.cpp index 847c6febab..5ce4fad6a4 100644 --- a/Userland/Libraries/LibGUI/WindowServerConnection.cpp +++ b/Userland/Libraries/LibGUI/WindowServerConnection.cpp @@ -297,6 +297,9 @@ void WindowServerConnection::handle(const Messages::WindowClient::WM_WindowRemov void WindowServerConnection::handle(const Messages::WindowClient::ScreenRectChanged& message) { Desktop::the().did_receive_screen_rect({}, message.rect()); + Window::for_each_window({}, [message](auto& window) { + Core::EventLoop::current().post_event(window, make(message.rect())); + }); } void WindowServerConnection::handle(const Messages::WindowClient::AsyncSetWallpaperFinished&)