From 7a95e32fc50516aa81915fe66d0f15d321bb06cd Mon Sep 17 00:00:00 2001 From: Tong Mu Date: Mon, 13 Jul 2020 13:32:13 -0700 Subject: [PATCH] Linux: Use a hash table to map cursors (#19561) Refactors the process of looking up system mouse cursor value, so that instead of a linear search it uses a hash table. --- .../platform/linux/fl_mouse_cursor_plugin.cc | 63 ++++++++++++------- 1 file changed, 42 insertions(+), 21 deletions(-) diff --git a/shell/platform/linux/fl_mouse_cursor_plugin.cc b/shell/platform/linux/fl_mouse_cursor_plugin.cc index d22f8231a3e65..e0669505a9712 100644 --- a/shell/platform/linux/fl_mouse_cursor_plugin.cc +++ b/shell/platform/linux/fl_mouse_cursor_plugin.cc @@ -14,16 +14,47 @@ static constexpr char kBadArgumentsError[] = "Bad Arguments"; static constexpr char kActivateSystemCursorMethod[] = "activateSystemCursor"; static constexpr char kKindKey[] = "kind"; +static constexpr char kFallbackCursor[] = "default"; + struct _FlMouseCursorPlugin { GObject parent_instance; FlMethodChannel* channel; FlView* view; + + GHashTable* system_cursor_table; }; G_DEFINE_TYPE(FlMouseCursorPlugin, fl_mouse_cursor_plugin, G_TYPE_OBJECT) +// Insert a new entry into a hashtable from strings to strings. +// +// Returns whether the newly added value was already in the hash table or not. +static bool define_system_cursor(GHashTable* table, + const gchar* key, + const gchar* value) { + return g_hash_table_insert( + table, reinterpret_cast(const_cast(key)), + reinterpret_cast(const_cast(value))); +} + +// Populate the hash table so that it maps from Flutter's cursor kinds to GTK's +// cursor values. +// +// The table must have been created as a hashtable from strings to strings. +static void populate_system_cursor_table(GHashTable* table) { + // The following mapping must be kept in sync with Flutter framework's + // mouse_cursor.dart. + define_system_cursor(table, "none", "none"); + define_system_cursor(table, "click", "pointer"); + define_system_cursor(table, "text", "text"); + define_system_cursor(table, "forbidden", "not-allowed"); + define_system_cursor(table, "grab", "grabbing"); + define_system_cursor(table, "resizeLeftRight", "ew-resize"); + define_system_cursor(table, "resizeUpDown", "ns-resize"); +} + // Sets the mouse cursor. FlMethodResponse* activate_system_cursor(FlMouseCursorPlugin* self, FlValue* args) { @@ -37,27 +68,15 @@ FlMethodResponse* activate_system_cursor(FlMouseCursorPlugin* self, if (fl_value_get_type(kind_value) == FL_VALUE_TYPE_STRING) kind = fl_value_get_string(kind_value); - const gchar* cursor_name = nullptr; - if (g_strcmp0(kind, "none") == 0) - cursor_name = "none"; - else if (g_strcmp0(kind, "basic") == 0) - cursor_name = "default"; - else if (g_strcmp0(kind, "click") == 0) - cursor_name = "pointer"; - else if (g_strcmp0(kind, "text") == 0) - cursor_name = "text"; - else if (g_strcmp0(kind, "forbidden") == 0) - cursor_name = "not-allowed"; - else if (g_strcmp0(kind, "grab") == 0) - cursor_name = "grab"; - else if (g_strcmp0(kind, "grabbing") == 0) - cursor_name = "grabbing"; - else if (g_strcmp0(kind, "resizeLeftRight") == 0) - cursor_name = "ew-resize"; - else if (g_strcmp0(kind, "resizeUpDown") == 0) - cursor_name = "ns-resize"; - else - cursor_name = "default"; + if (self->system_cursor_table == nullptr) { + self->system_cursor_table = g_hash_table_new(g_str_hash, g_str_equal); + populate_system_cursor_table(self->system_cursor_table); + } + + const gchar* cursor_name = reinterpret_cast( + g_hash_table_lookup(self->system_cursor_table, kind)); + if (cursor_name == nullptr) + cursor_name = kFallbackCursor; GdkWindow* window = gtk_widget_get_window(gtk_widget_get_toplevel(GTK_WIDGET(self->view))); @@ -102,6 +121,8 @@ static void fl_mouse_cursor_plugin_dispose(GObject* object) { self->view = nullptr; } + g_clear_pointer(&self->system_cursor_table, g_hash_table_unref); + G_OBJECT_CLASS(fl_mouse_cursor_plugin_parent_class)->dispose(object); }