diff --git a/Userland/Libraries/LibGUI/Widget.cpp b/Userland/Libraries/LibGUI/Widget.cpp index 811ec1a312..6062142819 100644 --- a/Userland/Libraries/LibGUI/Widget.cpp +++ b/Userland/Libraries/LibGUI/Widget.cpp @@ -1036,14 +1036,23 @@ Gfx::IntRect Widget::children_clip_rect() const return rect(); } -void Widget::set_override_cursor(Gfx::StandardCursor cursor) +void Widget::set_override_cursor(AK::Variant> cursor) { - if (m_override_cursor == cursor) + auto const& are_cursors_the_same = [](AK::Variant> const& a, AK::Variant> const& b) { + if (a.has() != b.has()) + return false; + if (a.has()) + return a.get() == b.get(); + return a.get>().ptr() == b.get>().ptr(); + }; + + if (are_cursors_the_same(m_override_cursor, cursor)) return; - m_override_cursor = cursor; - if (auto* window = this->window()) + m_override_cursor = move(cursor); + if (auto* window = this->window()) { window->update_cursor({}); + } } bool Widget::load_from_gml(const StringView& gml_string) diff --git a/Userland/Libraries/LibGUI/Widget.h b/Userland/Libraries/LibGUI/Widget.h index 29ae0f0079..07b870e28a 100644 --- a/Userland/Libraries/LibGUI/Widget.h +++ b/Userland/Libraries/LibGUI/Widget.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -272,8 +273,8 @@ public: virtual Gfx::IntRect children_clip_rect() const; - Gfx::StandardCursor override_cursor() const { return m_override_cursor; } - void set_override_cursor(Gfx::StandardCursor); + AK::Variant> override_cursor() const { return m_override_cursor; } + void set_override_cursor(AK::Variant>); bool load_from_gml(const StringView&); bool load_from_gml(const StringView&, RefPtr (*unregistered_child_handler)(const String&)); @@ -373,7 +374,7 @@ private: WeakPtr m_focus_proxy; FocusPolicy m_focus_policy { FocusPolicy::NoFocus }; - Gfx::StandardCursor m_override_cursor { Gfx::StandardCursor::None }; + AK::Variant> m_override_cursor { Gfx::StandardCursor::None }; }; inline Widget* Widget::parent_widget() diff --git a/Userland/Libraries/LibGUI/Window.cpp b/Userland/Libraries/LibGUI/Window.cpp index 6e5f1cfe8c..6f7265f3ac 100644 --- a/Userland/Libraries/LibGUI/Window.cpp +++ b/Userland/Libraries/LibGUI/Window.cpp @@ -317,21 +317,28 @@ void Window::make_window_manager(unsigned event_mask) GUI::WindowManagerServerConnection::the().async_set_manager_window(m_window_id); } +bool Window::are_cursors_the_same(AK::Variant> const& left, AK::Variant> const& right) const +{ + if (left.has() != right.has()) + return false; + if (left.has()) + return left.get() == right.get(); + return left.get>().ptr() == right.get>().ptr(); +} + void Window::set_cursor(Gfx::StandardCursor cursor) { - if (m_cursor == cursor) + if (are_cursors_the_same(m_cursor, cursor)) return; m_cursor = cursor; - m_custom_cursor = nullptr; update_cursor(); } -void Window::set_cursor(const Gfx::Bitmap& cursor) +void Window::set_cursor(NonnullRefPtr cursor) { - if (m_custom_cursor == &cursor) + if (are_cursors_the_same(m_cursor, cursor)) return; - m_cursor = Gfx::StandardCursor::None; - m_custom_cursor = &cursor; + m_cursor = cursor; update_cursor(); } @@ -1135,21 +1142,22 @@ void Window::set_progress(Optional progress) void Window::update_cursor() { - Gfx::StandardCursor new_cursor; + auto new_cursor = m_cursor; - if (m_hovered_widget && m_hovered_widget->override_cursor() != Gfx::StandardCursor::None) - new_cursor = m_hovered_widget->override_cursor(); - else - new_cursor = m_cursor; + if (m_hovered_widget) { + auto override_cursor = m_hovered_widget->override_cursor(); + if (override_cursor.has>() || override_cursor.get() != Gfx::StandardCursor::None) + new_cursor = move(override_cursor); + } - if (!m_custom_cursor && m_effective_cursor == new_cursor) + if (are_cursors_the_same(m_effective_cursor, new_cursor)) return; m_effective_cursor = new_cursor; - if (m_custom_cursor) - WindowServerConnection::the().async_set_window_custom_cursor(m_window_id, m_custom_cursor->to_shareable_bitmap()); + if (new_cursor.has>()) + WindowServerConnection::the().async_set_window_custom_cursor(m_window_id, new_cursor.get>()->to_shareable_bitmap()); else - WindowServerConnection::the().async_set_window_cursor(m_window_id, (u32)m_effective_cursor); + WindowServerConnection::the().async_set_window_cursor(m_window_id, (u32)new_cursor.get()); } void Window::focus_a_widget_if_possible(FocusSource source) diff --git a/Userland/Libraries/LibGUI/Window.h b/Userland/Libraries/LibGUI/Window.h index 119a5529b7..6723b9ee09 100644 --- a/Userland/Libraries/LibGUI/Window.h +++ b/Userland/Libraries/LibGUI/Window.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -169,7 +170,7 @@ public: void set_resize_aspect_ratio(const Optional& ratio); void set_cursor(Gfx::StandardCursor); - void set_cursor(const Gfx::Bitmap&); + void set_cursor(NonnullRefPtr); void set_icon(const Gfx::Bitmap*); void apply_icon(); @@ -240,6 +241,8 @@ private: void flip(const Vector& dirty_rects); void force_update(); + bool are_cursors_the_same(AK::Variant> const&, AK::Variant> const&) const; + WeakPtr m_previously_focused_widget; OwnPtr m_front_store; @@ -248,7 +251,6 @@ private: NonnullRefPtr m_menubar; RefPtr m_icon; - RefPtr m_custom_cursor; int m_window_id { 0 }; float m_opacity_when_windowless { 1.0f }; float m_alpha_hit_threshold { 0.0f }; @@ -265,8 +267,8 @@ private: Gfx::IntSize m_base_size; Color m_background_color { Color::WarmGray }; WindowType m_window_type { WindowType::Normal }; - Gfx::StandardCursor m_cursor { Gfx::StandardCursor::None }; - Gfx::StandardCursor m_effective_cursor { Gfx::StandardCursor::None }; + AK::Variant> m_cursor { Gfx::StandardCursor::None }; + AK::Variant> m_effective_cursor { Gfx::StandardCursor::None }; bool m_is_active_input { false }; bool m_has_alpha_channel { false }; bool m_double_buffering_enabled { true };