diff --git a/Libraries/LibGUI/Widget.cpp b/Libraries/LibGUI/Widget.cpp index 52ae9e82e5..c79990c9ca 100644 --- a/Libraries/LibGUI/Widget.cpp +++ b/Libraries/LibGUI/Widget.cpp @@ -318,12 +318,14 @@ void Widget::handle_mousedoubleclick_event(MouseEvent& event) void Widget::handle_enter_event(Core::Event& event) { + window()->update_cursor({}); show_tooltip(); enter_event(event); } void Widget::handle_leave_event(Core::Event& event) { + window()->update_cursor({}); Application::the()->hide_tooltip(); leave_event(event); } @@ -878,4 +880,14 @@ Gfx::IntRect Widget::children_clip_rect() const return rect(); } +void Widget::set_override_cursor(Gfx::StandardCursor cursor) +{ + if (m_override_cursor == cursor) + return; + + m_override_cursor = cursor; + if (auto* window = this->window()) + window->update_cursor({}); +} + } diff --git a/Libraries/LibGUI/Widget.h b/Libraries/LibGUI/Widget.h index 67ab5965b1..72c9d83731 100644 --- a/Libraries/LibGUI/Widget.h +++ b/Libraries/LibGUI/Widget.h @@ -36,6 +36,7 @@ #include #include #include +#include #define REGISTER_WIDGET(class_name) \ extern WidgetClassRegistration registration_##class_name; \ @@ -277,6 +278,9 @@ public: virtual Gfx::IntRect children_clip_rect() const; + Gfx::StandardCursor override_cursor() const { return m_override_cursor; } + void set_override_cursor(Gfx::StandardCursor); + protected: Widget(); @@ -349,6 +353,8 @@ private: NonnullRefPtr m_palette; WeakPtr m_focus_proxy; + + Gfx::StandardCursor m_override_cursor { Gfx::StandardCursor::None }; }; inline Widget* Widget::parent_widget() diff --git a/Libraries/LibGUI/Window.cpp b/Libraries/LibGUI/Window.cpp index 6c4c0b226b..aba48f26f6 100644 --- a/Libraries/LibGUI/Window.cpp +++ b/Libraries/LibGUI/Window.cpp @@ -228,23 +228,20 @@ void Window::set_window_type(WindowType window_type) void Window::set_cursor(Gfx::StandardCursor cursor) { - if (!is_visible()) + if (m_cursor == cursor) return; - if (!m_custom_cursor && m_cursor == cursor) - return; - WindowServerConnection::the().send_sync(m_window_id, (u32)cursor); m_cursor = cursor; m_custom_cursor = nullptr; + update_cursor(); } void Window::set_cursor(const Gfx::Bitmap& cursor) { - if (!is_visible()) - return; - if (&cursor == m_custom_cursor.ptr()) + if (m_custom_cursor == &cursor) return; + m_cursor = Gfx::StandardCursor::None; m_custom_cursor = &cursor; - WindowServerConnection::the().send_sync(m_window_id, m_custom_cursor->to_shareable_bitmap(WindowServerConnection::the().server_pid())); + update_cursor(); } void Window::handle_drop_event(DropEvent& event) @@ -871,4 +868,24 @@ void Window::set_progress(int progress) ASSERT(m_window_id); WindowServerConnection::the().post_message(Messages::WindowServer::SetWindowProgress(m_window_id, progress)); } + +void Window::update_cursor() +{ + Gfx::StandardCursor new_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_effective_cursor == new_cursor) + return; + m_effective_cursor = new_cursor; + + if (m_custom_cursor) + WindowServerConnection::the().send_sync(m_window_id, m_custom_cursor->to_shareable_bitmap(WindowServerConnection::the().server_pid())); + else + WindowServerConnection::the().send_sync(m_window_id, (u32)m_effective_cursor); +} + } diff --git a/Libraries/LibGUI/Window.h b/Libraries/LibGUI/Window.h index 7e10bd6fcf..621693f57f 100644 --- a/Libraries/LibGUI/Window.h +++ b/Libraries/LibGUI/Window.h @@ -196,6 +196,8 @@ public: void set_progress(int); + void update_cursor(Badge) { update_cursor(); } + protected: Window(Core::Object* parent = nullptr); virtual void wm_event(WMEvent&); @@ -203,6 +205,8 @@ protected: private: virtual bool is_window() const override final { return true; } + void update_cursor(); + void handle_drop_event(DropEvent&); void handle_mouse_event(MouseEvent&); void handle_multi_paint_event(MultiPaintEvent&); @@ -242,6 +246,7 @@ private: 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 }; bool m_is_active { false }; bool m_is_active_input { false }; bool m_has_alpha_channel { false };