summaryrefslogtreecommitdiff
path: root/Userland/Libraries
diff options
context:
space:
mode:
authorMarco Cutecchia <marco.cutecchia@outlook.it>2021-10-15 22:24:41 +0200
committerAndreas Kling <kling@serenityos.org>2021-10-31 12:37:49 +0100
commit116bb4888fb7c7f5c80091caca6f3cdf68ef6383 (patch)
treeafa59f7b21d9d88f96c4176af3c1a9b850ce745a /Userland/Libraries
parent4bfe060336b96926dfd72bc3b0ef0b7ffdf5e168 (diff)
downloadserenity-116bb4888fb7c7f5c80091caca6f3cdf68ef6383.zip
LibGUI: Support using a bitmap as override cursor
Diffstat (limited to 'Userland/Libraries')
-rw-r--r--Userland/Libraries/LibGUI/Widget.cpp17
-rw-r--r--Userland/Libraries/LibGUI/Widget.h7
-rw-r--r--Userland/Libraries/LibGUI/Window.cpp38
-rw-r--r--Userland/Libraries/LibGUI/Window.h10
4 files changed, 46 insertions, 26 deletions
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<Gfx::StandardCursor, NonnullRefPtr<Gfx::Bitmap>> cursor)
{
- if (m_override_cursor == cursor)
+ auto const& are_cursors_the_same = [](AK::Variant<Gfx::StandardCursor, NonnullRefPtr<Gfx::Bitmap>> const& a, AK::Variant<Gfx::StandardCursor, NonnullRefPtr<Gfx::Bitmap>> const& b) {
+ if (a.has<Gfx::StandardCursor>() != b.has<Gfx::StandardCursor>())
+ return false;
+ if (a.has<Gfx::StandardCursor>())
+ return a.get<Gfx::StandardCursor>() == b.get<Gfx::StandardCursor>();
+ return a.get<NonnullRefPtr<Gfx::Bitmap>>().ptr() == b.get<NonnullRefPtr<Gfx::Bitmap>>().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 <AK/EnumBits.h>
#include <AK/JsonObject.h>
#include <AK/String.h>
+#include <AK/Variant.h>
#include <LibCore/Object.h>
#include <LibGUI/Event.h>
#include <LibGUI/FocusPolicy.h>
@@ -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<Gfx::StandardCursor, NonnullRefPtr<Gfx::Bitmap>> override_cursor() const { return m_override_cursor; }
+ void set_override_cursor(AK::Variant<Gfx::StandardCursor, NonnullRefPtr<Gfx::Bitmap>>);
bool load_from_gml(const StringView&);
bool load_from_gml(const StringView&, RefPtr<Core::Object> (*unregistered_child_handler)(const String&));
@@ -373,7 +374,7 @@ private:
WeakPtr<Widget> m_focus_proxy;
FocusPolicy m_focus_policy { FocusPolicy::NoFocus };
- Gfx::StandardCursor m_override_cursor { Gfx::StandardCursor::None };
+ AK::Variant<Gfx::StandardCursor, NonnullRefPtr<Gfx::Bitmap>> 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<Gfx::StandardCursor, NonnullRefPtr<Gfx::Bitmap>> const& left, AK::Variant<Gfx::StandardCursor, NonnullRefPtr<Gfx::Bitmap>> const& right) const
+{
+ if (left.has<Gfx::StandardCursor>() != right.has<Gfx::StandardCursor>())
+ return false;
+ if (left.has<Gfx::StandardCursor>())
+ return left.get<Gfx::StandardCursor>() == right.get<Gfx::StandardCursor>();
+ return left.get<NonnullRefPtr<Gfx::Bitmap>>().ptr() == right.get<NonnullRefPtr<Gfx::Bitmap>>().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<Gfx::Bitmap> 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<int> 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<NonnullRefPtr<Gfx::Bitmap>>() || override_cursor.get<Gfx::StandardCursor>() != 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<NonnullRefPtr<Gfx::Bitmap>>())
+ WindowServerConnection::the().async_set_window_custom_cursor(m_window_id, new_cursor.get<NonnullRefPtr<Gfx::Bitmap>>()->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<Gfx::StandardCursor>());
}
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 <AK/Function.h>
#include <AK/OwnPtr.h>
#include <AK/String.h>
+#include <AK/Variant.h>
#include <AK/WeakPtr.h>
#include <LibCore/Object.h>
#include <LibGUI/FocusSource.h>
@@ -169,7 +170,7 @@ public:
void set_resize_aspect_ratio(const Optional<Gfx::IntSize>& ratio);
void set_cursor(Gfx::StandardCursor);
- void set_cursor(const Gfx::Bitmap&);
+ void set_cursor(NonnullRefPtr<Gfx::Bitmap>);
void set_icon(const Gfx::Bitmap*);
void apply_icon();
@@ -240,6 +241,8 @@ private:
void flip(const Vector<Gfx::IntRect, 32>& dirty_rects);
void force_update();
+ bool are_cursors_the_same(AK::Variant<Gfx::StandardCursor, NonnullRefPtr<Gfx::Bitmap>> const&, AK::Variant<Gfx::StandardCursor, NonnullRefPtr<Gfx::Bitmap>> const&) const;
+
WeakPtr<Widget> m_previously_focused_widget;
OwnPtr<WindowBackingStore> m_front_store;
@@ -248,7 +251,6 @@ private:
NonnullRefPtr<Menubar> m_menubar;
RefPtr<Gfx::Bitmap> m_icon;
- RefPtr<Gfx::Bitmap> 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<Gfx::StandardCursor, NonnullRefPtr<Gfx::Bitmap>> m_cursor { Gfx::StandardCursor::None };
+ AK::Variant<Gfx::StandardCursor, NonnullRefPtr<Gfx::Bitmap>> m_effective_cursor { Gfx::StandardCursor::None };
bool m_is_active_input { false };
bool m_has_alpha_channel { false };
bool m_double_buffering_enabled { true };