1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-22 16:45:08 +00:00

LibGUI: Add Widget override cursor concept

We got ourselves into a mess by making widgets override the window
cursor whenever they wanted a custom cursor. This patch introduces a
better solution to that issue: per-widget override cursors.

Each widget now has an override cursor that overrides the window
cursor when that widget is hovered.
This commit is contained in:
Andreas Kling 2020-09-11 14:17:35 +02:00
parent b4f307f982
commit cf429a788c
4 changed files with 48 additions and 8 deletions

View file

@ -318,12 +318,14 @@ void Widget::handle_mousedoubleclick_event(MouseEvent& event)
void Widget::handle_enter_event(Core::Event& event) void Widget::handle_enter_event(Core::Event& event)
{ {
window()->update_cursor({});
show_tooltip(); show_tooltip();
enter_event(event); enter_event(event);
} }
void Widget::handle_leave_event(Core::Event& event) void Widget::handle_leave_event(Core::Event& event)
{ {
window()->update_cursor({});
Application::the()->hide_tooltip(); Application::the()->hide_tooltip();
leave_event(event); leave_event(event);
} }
@ -878,4 +880,14 @@ Gfx::IntRect Widget::children_clip_rect() const
return rect(); 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({});
}
} }

View file

@ -36,6 +36,7 @@
#include <LibGfx/Forward.h> #include <LibGfx/Forward.h>
#include <LibGfx/Orientation.h> #include <LibGfx/Orientation.h>
#include <LibGfx/Rect.h> #include <LibGfx/Rect.h>
#include <LibGfx/StandardCursor.h>
#define REGISTER_WIDGET(class_name) \ #define REGISTER_WIDGET(class_name) \
extern WidgetClassRegistration registration_##class_name; \ extern WidgetClassRegistration registration_##class_name; \
@ -277,6 +278,9 @@ public:
virtual Gfx::IntRect children_clip_rect() const; virtual Gfx::IntRect children_clip_rect() const;
Gfx::StandardCursor override_cursor() const { return m_override_cursor; }
void set_override_cursor(Gfx::StandardCursor);
protected: protected:
Widget(); Widget();
@ -349,6 +353,8 @@ private:
NonnullRefPtr<Gfx::PaletteImpl> m_palette; NonnullRefPtr<Gfx::PaletteImpl> m_palette;
WeakPtr<Widget> m_focus_proxy; WeakPtr<Widget> m_focus_proxy;
Gfx::StandardCursor m_override_cursor { Gfx::StandardCursor::None };
}; };
inline Widget* Widget::parent_widget() inline Widget* Widget::parent_widget()

View file

@ -228,23 +228,20 @@ void Window::set_window_type(WindowType window_type)
void Window::set_cursor(Gfx::StandardCursor cursor) void Window::set_cursor(Gfx::StandardCursor cursor)
{ {
if (!is_visible()) if (m_cursor == cursor)
return; return;
if (!m_custom_cursor && m_cursor == cursor)
return;
WindowServerConnection::the().send_sync<Messages::WindowServer::SetWindowCursor>(m_window_id, (u32)cursor);
m_cursor = cursor; m_cursor = cursor;
m_custom_cursor = nullptr; m_custom_cursor = nullptr;
update_cursor();
} }
void Window::set_cursor(const Gfx::Bitmap& cursor) void Window::set_cursor(const Gfx::Bitmap& cursor)
{ {
if (!is_visible()) if (m_custom_cursor == &cursor)
return;
if (&cursor == m_custom_cursor.ptr())
return; return;
m_cursor = Gfx::StandardCursor::None;
m_custom_cursor = &cursor; m_custom_cursor = &cursor;
WindowServerConnection::the().send_sync<Messages::WindowServer::SetWindowCustomCursor>(m_window_id, m_custom_cursor->to_shareable_bitmap(WindowServerConnection::the().server_pid())); update_cursor();
} }
void Window::handle_drop_event(DropEvent& event) void Window::handle_drop_event(DropEvent& event)
@ -871,4 +868,24 @@ void Window::set_progress(int progress)
ASSERT(m_window_id); ASSERT(m_window_id);
WindowServerConnection::the().post_message(Messages::WindowServer::SetWindowProgress(m_window_id, progress)); 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<Messages::WindowServer::SetWindowCustomCursor>(m_window_id, m_custom_cursor->to_shareable_bitmap(WindowServerConnection::the().server_pid()));
else
WindowServerConnection::the().send_sync<Messages::WindowServer::SetWindowCursor>(m_window_id, (u32)m_effective_cursor);
}
} }

View file

@ -196,6 +196,8 @@ public:
void set_progress(int); void set_progress(int);
void update_cursor(Badge<Widget>) { update_cursor(); }
protected: protected:
Window(Core::Object* parent = nullptr); Window(Core::Object* parent = nullptr);
virtual void wm_event(WMEvent&); virtual void wm_event(WMEvent&);
@ -203,6 +205,8 @@ protected:
private: private:
virtual bool is_window() const override final { return true; } virtual bool is_window() const override final { return true; }
void update_cursor();
void handle_drop_event(DropEvent&); void handle_drop_event(DropEvent&);
void handle_mouse_event(MouseEvent&); void handle_mouse_event(MouseEvent&);
void handle_multi_paint_event(MultiPaintEvent&); void handle_multi_paint_event(MultiPaintEvent&);
@ -242,6 +246,7 @@ private:
Color m_background_color { Color::WarmGray }; Color m_background_color { Color::WarmGray };
WindowType m_window_type { WindowType::Normal }; WindowType m_window_type { WindowType::Normal };
Gfx::StandardCursor m_cursor { Gfx::StandardCursor::None }; Gfx::StandardCursor m_cursor { Gfx::StandardCursor::None };
Gfx::StandardCursor m_effective_cursor { Gfx::StandardCursor::None };
bool m_is_active { false }; bool m_is_active { false };
bool m_is_active_input { false }; bool m_is_active_input { false };
bool m_has_alpha_channel { false }; bool m_has_alpha_channel { false };