Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Move FlMouseCursorHandler from FlView to FlEngine #56026

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions shell/platform/linux/fl_engine.cc
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ struct _FlEngine {
// Implements the flutter/platform channel.
FlPlatformHandler* platform_handler;

// Implements the flutter/mousecursor channel.
FlMouseCursorHandler* mouse_cursor_handler;

// Manages textures rendered by native code.
FlTextureRegistrar* texture_registrar;

Expand Down Expand Up @@ -449,6 +452,7 @@ static void fl_engine_dispose(GObject* object) {
g_clear_object(&self->binary_messenger);
g_clear_object(&self->settings_handler);
g_clear_object(&self->platform_handler);
g_clear_object(&self->mouse_cursor_handler);
g_clear_object(&self->task_runner);

if (self->platform_message_handler_destroy_notify) {
Expand Down Expand Up @@ -629,6 +633,8 @@ gboolean fl_engine_start(FlEngine* self, GError** error) {
fl_settings_handler_start(self->settings_handler, settings);

self->platform_handler = fl_platform_handler_new(self->binary_messenger);
self->mouse_cursor_handler =
fl_mouse_cursor_handler_new(self->binary_messenger);

result = self->embedder_api.UpdateSemanticsEnabled(self->engine, TRUE);
if (result != kSuccess) {
Expand Down Expand Up @@ -1051,3 +1057,8 @@ void fl_engine_request_app_exit(FlEngine* self) {
g_return_if_fail(FL_IS_ENGINE(self));
fl_platform_handler_request_app_exit(self->platform_handler);
}

FlMouseCursorHandler* fl_engine_get_mouse_cursor_handler(FlEngine* self) {
g_return_val_if_fail(FL_IS_ENGINE(self), nullptr);
return self->mouse_cursor_handler;
}
11 changes: 11 additions & 0 deletions shell/platform/linux/fl_engine_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <glib-object.h>

#include "flutter/shell/platform/embedder/embedder.h"
#include "flutter/shell/platform/linux/fl_mouse_cursor_handler.h"
#include "flutter/shell/platform/linux/fl_renderer.h"
#include "flutter/shell/platform/linux/fl_task_runner.h"
#include "flutter/shell/platform/linux/public/flutter_linux/fl_dart_project.h"
Expand Down Expand Up @@ -424,6 +425,16 @@ void fl_engine_update_accessibility_features(FlEngine* engine, int32_t flags);
*/
void fl_engine_request_app_exit(FlEngine* engine);

/**
* fl_engine_get_mouse_cursor_handler:
* @engine: an #FlEngine.
*
* Gets the mouse cursor handler used by this engine.
*
* Returns: a #FlMouseCursorHandler.
*/
FlMouseCursorHandler* fl_engine_get_mouse_cursor_handler(FlEngine* engine);

G_END_DECLS

#endif // FLUTTER_SHELL_PLATFORM_LINUX_FL_ENGINE_PRIVATE_H_
43 changes: 27 additions & 16 deletions shell/platform/linux/fl_mouse_cursor_handler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

#include "flutter/shell/platform/linux/fl_mouse_cursor_handler.h"

#include <gtk/gtk.h>
#include <cstring>

#include "flutter/shell/platform/linux/public/flutter_linux/fl_method_channel.h"
Expand All @@ -22,11 +21,16 @@ struct _FlMouseCursorHandler {

FlMethodChannel* channel;

GWeakRef view;

GHashTable* system_cursor_table;

// The current cursor.
gchar* cursor_name;
};

enum { kSignalCursorChanged, kSignalLastSignal };

static guint fl_mouse_cursor_handler_signals[kSignalLastSignal];

G_DEFINE_TYPE(FlMouseCursorHandler, fl_mouse_cursor_handler, G_TYPE_OBJECT)

// Insert a new entry into a hashtable from strings to strings.
Expand Down Expand Up @@ -109,14 +113,10 @@ FlMethodResponse* activate_system_cursor(FlMouseCursorHandler* self,
cursor_name = kFallbackCursor;
}

g_autoptr(FlView) view = FL_VIEW(g_weak_ref_get(&self->view));
if (view != nullptr) {
GdkWindow* window =
gtk_widget_get_window(gtk_widget_get_toplevel(GTK_WIDGET(view)));
g_autoptr(GdkCursor) cursor =
gdk_cursor_new_from_name(gdk_window_get_display(window), cursor_name);
gdk_window_set_cursor(window, cursor);
}
g_free(self->cursor_name);
self->cursor_name = g_strdup(cursor_name);

g_signal_emit(self, fl_mouse_cursor_handler_signals[kSignalCursorChanged], 0);

return FL_METHOD_RESPONSE(fl_method_success_response_new(nullptr));
}
Expand Down Expand Up @@ -147,21 +147,27 @@ static void fl_mouse_cursor_handler_dispose(GObject* object) {
FlMouseCursorHandler* self = FL_MOUSE_CURSOR_HANDLER(object);

g_clear_object(&self->channel);
g_weak_ref_clear(&self->view);
g_clear_pointer(&self->system_cursor_table, g_hash_table_unref);
g_clear_pointer(&self->cursor_name, g_free);

G_OBJECT_CLASS(fl_mouse_cursor_handler_parent_class)->dispose(object);
}

static void fl_mouse_cursor_handler_class_init(
FlMouseCursorHandlerClass* klass) {
G_OBJECT_CLASS(klass)->dispose = fl_mouse_cursor_handler_dispose;

fl_mouse_cursor_handler_signals[kSignalCursorChanged] =
g_signal_new("cursor-changed", fl_mouse_cursor_handler_get_type(),
G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 0);
}

static void fl_mouse_cursor_handler_init(FlMouseCursorHandler* self) {}
static void fl_mouse_cursor_handler_init(FlMouseCursorHandler* self) {
self->cursor_name = g_strdup("");
}

FlMouseCursorHandler* fl_mouse_cursor_handler_new(FlBinaryMessenger* messenger,
FlView* view) {
FlMouseCursorHandler* fl_mouse_cursor_handler_new(
FlBinaryMessenger* messenger) {
g_return_val_if_fail(FL_IS_BINARY_MESSENGER(messenger), nullptr);

FlMouseCursorHandler* self = FL_MOUSE_CURSOR_HANDLER(
Expand All @@ -172,7 +178,12 @@ FlMouseCursorHandler* fl_mouse_cursor_handler_new(FlBinaryMessenger* messenger,
fl_method_channel_new(messenger, kChannelName, FL_METHOD_CODEC(codec));
fl_method_channel_set_method_call_handler(self->channel, method_call_cb, self,
nullptr);
g_weak_ref_init(&self->view, view);

return self;
}

const gchar* fl_mouse_cursor_handler_get_cursor_name(
FlMouseCursorHandler* self) {
g_return_val_if_fail(FL_IS_MOUSE_CURSOR_HANDLER(self), nullptr);
return self->cursor_name;
}
16 changes: 12 additions & 4 deletions shell/platform/linux/fl_mouse_cursor_handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
#include <gdk/gdk.h>

#include "flutter/shell/platform/linux/public/flutter_linux/fl_binary_messenger.h"
#include "flutter/shell/platform/linux/public/flutter_linux/fl_view.h"

G_BEGIN_DECLS

Expand All @@ -28,15 +27,24 @@ G_DECLARE_FINAL_TYPE(FlMouseCursorHandler,
/**
* fl_mouse_cursor_handler_new:
* @messenger: an #FlBinaryMessenger.
* @view: an #FlView to control.
*
* Creates a new handler that implements SystemChannels.mouseCursor from the
* Flutter services library.
*
* Returns: a new #FlMouseCursorHandler.
*/
FlMouseCursorHandler* fl_mouse_cursor_handler_new(FlBinaryMessenger* messenger,
FlView* view);
FlMouseCursorHandler* fl_mouse_cursor_handler_new(FlBinaryMessenger* messenger);

/**
* fl_mouse_cursor_handler_get_cursor_name:
* @handler: an #FlMouseCursorHandler.
*
* Get the name of the current mouse cursor.
*
* Returns: a mouse cursor name.
*/
const gchar* fl_mouse_cursor_handler_get_cursor_name(
FlMouseCursorHandler* handler);

G_END_DECLS

Expand Down
42 changes: 36 additions & 6 deletions shell/platform/linux/fl_view.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
#include "flutter/shell/platform/linux/fl_keyboard_handler.h"
#include "flutter/shell/platform/linux/fl_keyboard_manager.h"
#include "flutter/shell/platform/linux/fl_keyboard_view_delegate.h"
#include "flutter/shell/platform/linux/fl_mouse_cursor_handler.h"
#include "flutter/shell/platform/linux/fl_plugin_registrar_private.h"
#include "flutter/shell/platform/linux/fl_pointer_manager.h"
#include "flutter/shell/platform/linux/fl_renderer_gdk.h"
Expand Down Expand Up @@ -68,11 +67,13 @@ struct _FlView {
// Flutter system channel handlers.
FlKeyboardHandler* keyboard_handler;
FlTextInputHandler* text_input_handler;
FlMouseCursorHandler* mouse_cursor_handler;

// Accessible tree from Flutter, exposed as an AtkPlug.
FlViewAccessible* view_accessible;

// Signal subscripton for cursor changes.
guint cursor_changed_cb_id;

GCancellable* cancellable;
};

Expand Down Expand Up @@ -184,6 +185,28 @@ static gboolean get_mouse_button(GdkEvent* event, int64_t* button) {
}
}

// Called when the mouse cursor changes.
static void cursor_changed_cb(FlView* self) {
FlMouseCursorHandler* handler =
fl_engine_get_mouse_cursor_handler(self->engine);
const gchar* cursor_name = fl_mouse_cursor_handler_get_cursor_name(handler);
GdkWindow* window =
gtk_widget_get_window(gtk_widget_get_toplevel(GTK_WIDGET(self)));
g_autoptr(GdkCursor) cursor =
gdk_cursor_new_from_name(gdk_window_get_display(window), cursor_name);
gdk_window_set_cursor(window, cursor);
}

// Set the mouse cursor.
static void setup_cursor(FlView* self) {
FlMouseCursorHandler* handler =
fl_engine_get_mouse_cursor_handler(self->engine);

self->cursor_changed_cb_id = g_signal_connect_swapped(
handler, "cursor-changed", G_CALLBACK(cursor_changed_cb), self);
cursor_changed_cb(self);
}

// Updates the engine with the current window metrics.
static void handle_geometry_changed(FlView* self) {
GtkAllocation allocation;
Expand Down Expand Up @@ -457,10 +480,7 @@ static GdkGLContext* create_context_cb(FlView* self) {
fl_renderer_gdk_set_window(self->renderer,
gtk_widget_get_parent_window(GTK_WIDGET(self)));

// Create system channel handlers.
FlBinaryMessenger* messenger = fl_engine_get_binary_messenger(self->engine);
init_scrolling(self);
self->mouse_cursor_handler = fl_mouse_cursor_handler_new(messenger, self);

g_autoptr(GError) error = nullptr;
if (!fl_renderer_gdk_create_contexts(self->renderer, &error)) {
Expand Down Expand Up @@ -505,6 +525,8 @@ static void realize_cb(FlView* self) {
return;
}

setup_cursor(self);

handle_geometry_changed(self);

self->view_accessible = fl_view_accessible_new(self->engine);
Expand Down Expand Up @@ -567,6 +589,13 @@ static void fl_view_dispose(GObject* object) {
fl_engine_set_update_semantics_handler(self->engine, nullptr, nullptr,
nullptr);

FlMouseCursorHandler* handler =
fl_engine_get_mouse_cursor_handler(self->engine);
if (self->cursor_changed_cb_id != 0) {
g_signal_handler_disconnect(handler, self->cursor_changed_cb_id);
self->cursor_changed_cb_id = 0;
}

// Stop rendering.
fl_renderer_remove_view(FL_RENDERER(self->renderer), self->view_id);

Expand All @@ -589,7 +618,6 @@ static void fl_view_dispose(GObject* object) {
g_clear_object(&self->pointer_manager);
g_clear_object(&self->keyboard_manager);
g_clear_object(&self->keyboard_handler);
g_clear_object(&self->mouse_cursor_handler);
g_clear_object(&self->view_accessible);
g_clear_object(&self->cancellable);

Expand Down Expand Up @@ -750,6 +778,8 @@ G_MODULE_EXPORT FlView* fl_view_new_for_engine(FlEngine* engine) {

self->pointer_manager = fl_pointer_manager_new(self->view_id, engine);

setup_cursor(self);

return self;
}

Expand Down
12 changes: 12 additions & 0 deletions shell/platform/linux/fl_view_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ TEST(FlViewTest, SecondaryView) {
return kSuccess;
}));

g_autoptr(GError) error = nullptr;
EXPECT_TRUE(fl_engine_start(engine, &error));

FlView* secondary_view = fl_view_new_for_engine(engine);
EXPECT_EQ(view_id, fl_view_get_id(secondary_view));
}
Expand All @@ -103,6 +106,9 @@ TEST(FlViewTest, SecondaryViewError) {
return kInvalidArguments;
}));

g_autoptr(GError) error = nullptr;
EXPECT_TRUE(fl_engine_start(engine, &error));

FlView* secondary_view = fl_view_new_for_engine(engine);
EXPECT_EQ(view_id, fl_view_get_id(secondary_view));
}
Expand All @@ -125,6 +131,9 @@ TEST(FlViewTest, ViewDestroy) {
return kSuccess;
}));

g_autoptr(GError) error = nullptr;
EXPECT_TRUE(fl_engine_start(engine, &error));

FlView* secondary_view = fl_view_new_for_engine(engine);

int64_t implicit_view_id = fl_view_get_id(implicit_view);
Expand Down Expand Up @@ -155,6 +164,9 @@ TEST(FlViewTest, ViewDestroyError) {
return kInvalidArguments;
}));

g_autoptr(GError) error = nullptr;
EXPECT_TRUE(fl_engine_start(engine, &error));

FlView* secondary_view = fl_view_new_for_engine(engine);

gtk_widget_destroy(GTK_WIDGET(secondary_view));
Expand Down
15 changes: 15 additions & 0 deletions shell/platform/linux/testing/mock_window.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,18 @@ MockWindow::MockWindow() {
GdkWindowState gdk_window_get_state(GdkWindow* window) {
return mock->gdk_window_get_state(window);
}

GdkDisplay* gdk_window_get_display(GdkWindow* window) {
return nullptr;
}

GdkMonitor* gdk_display_get_monitor_at_window(GdkDisplay* display,
GdkWindow* window) {
return nullptr;
}

GdkCursor* gdk_cursor_new_from_name(GdkDisplay* display, const gchar* name) {
return nullptr;
}

void gdk_window_set_cursor(GdkWindow* window, GdkCursor* cursor) {}