mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Add FlPlatformPlugin (flutter/engine#18316)
Fixes https://github.com/flutter/flutter/issues/54857
This commit is contained in:
parent
d2b7646e68
commit
86e7ef2334
@ -1225,6 +1225,8 @@ FILE: ../../../flutter/shell/platform/linux/fl_method_codec_private.h
|
||||
FILE: ../../../flutter/shell/platform/linux/fl_method_codec_test.cc
|
||||
FILE: ../../../flutter/shell/platform/linux/fl_method_response.cc
|
||||
FILE: ../../../flutter/shell/platform/linux/fl_method_response_test.cc
|
||||
FILE: ../../../flutter/shell/platform/linux/fl_platform_plugin.cc
|
||||
FILE: ../../../flutter/shell/platform/linux/fl_platform_plugin.h
|
||||
FILE: ../../../flutter/shell/platform/linux/fl_plugin_registrar.cc
|
||||
FILE: ../../../flutter/shell/platform/linux/fl_plugin_registrar_private.h
|
||||
FILE: ../../../flutter/shell/platform/linux/fl_plugin_registry.cc
|
||||
|
||||
@ -89,6 +89,7 @@ source_set("flutter_linux_sources") {
|
||||
"fl_method_channel.cc",
|
||||
"fl_method_codec.cc",
|
||||
"fl_method_response.cc",
|
||||
"fl_platform_plugin.cc",
|
||||
"fl_plugin_registrar.cc",
|
||||
"fl_plugin_registry.cc",
|
||||
"fl_renderer.cc",
|
||||
|
||||
171
engine/src/flutter/shell/platform/linux/fl_platform_plugin.cc
Normal file
171
engine/src/flutter/shell/platform/linux/fl_platform_plugin.cc
Normal file
@ -0,0 +1,171 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "flutter/shell/platform/linux/fl_platform_plugin.h"
|
||||
#include "flutter/shell/platform/linux/public/flutter_linux/fl_json_method_codec.h"
|
||||
#include "flutter/shell/platform/linux/public/flutter_linux/fl_method_channel.h"
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
static constexpr char kChannelName[] = "flutter/platform";
|
||||
static constexpr char kBadArgumentsError[] = "Bad Arguments";
|
||||
static constexpr char kUnknownClipboardFormatError[] =
|
||||
"Unknown Clipboard Format";
|
||||
static constexpr char kClipboardRequestError[] = "Clipboard Request Failed";
|
||||
static constexpr char kFailedError[] = "Failed";
|
||||
static constexpr char kGetClipboardDataMethod[] = "Clipboard.getData";
|
||||
static constexpr char kSetClipboardDataMethod[] = "Clipboard.setData";
|
||||
static constexpr char kSystemNavigatorPopMethod[] = "SystemNavigator.pop";
|
||||
static constexpr char kTextKey[] = "text";
|
||||
|
||||
static constexpr char kTextPlainFormat[] = "text/plain";
|
||||
|
||||
struct _FlPlatformPlugin {
|
||||
GObject parent_instance;
|
||||
|
||||
FlMethodChannel* channel;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(FlPlatformPlugin, fl_platform_plugin, G_TYPE_OBJECT)
|
||||
|
||||
// Sends the method call response to Flutter.
|
||||
static void send_response(FlMethodCall* method_call,
|
||||
FlMethodResponse* response) {
|
||||
g_autoptr(GError) error = nullptr;
|
||||
if (!fl_method_call_respond(method_call, response, &error))
|
||||
g_warning("Failed to send method call response: %s", error->message);
|
||||
}
|
||||
|
||||
// Called when clipboard text received.
|
||||
static void clipboard_text_cb(GtkClipboard* clipboard,
|
||||
const gchar* text,
|
||||
gpointer user_data) {
|
||||
g_autoptr(FlMethodCall) method_call = FL_METHOD_CALL(user_data);
|
||||
|
||||
g_autoptr(FlMethodResponse) response = nullptr;
|
||||
if (text != nullptr) {
|
||||
g_autoptr(FlValue) result = fl_value_new_map();
|
||||
fl_value_set_string_take(result, kTextKey, fl_value_new_string(text));
|
||||
response = FL_METHOD_RESPONSE(fl_method_success_response_new(nullptr));
|
||||
} else {
|
||||
response = FL_METHOD_RESPONSE(fl_method_error_response_new(
|
||||
kClipboardRequestError, "Failed to retrieve clipboard text from GTK",
|
||||
nullptr));
|
||||
}
|
||||
|
||||
send_response(method_call, response);
|
||||
}
|
||||
|
||||
// Called when Flutter wants to copy to the clipboard.
|
||||
static FlMethodResponse* clipboard_set_data(FlPlatformPlugin* self,
|
||||
FlValue* args) {
|
||||
if (fl_value_get_type(args) != FL_VALUE_TYPE_MAP) {
|
||||
return FL_METHOD_RESPONSE(fl_method_error_response_new(
|
||||
kBadArgumentsError, "Argument map missing or malformed", nullptr));
|
||||
}
|
||||
|
||||
FlValue* text_value = fl_value_lookup_string(args, kTextKey);
|
||||
if (text_value == nullptr ||
|
||||
fl_value_get_type(text_value) != FL_VALUE_TYPE_STRING) {
|
||||
return FL_METHOD_RESPONSE(fl_method_error_response_new(
|
||||
kBadArgumentsError, "Missing clipboard text", nullptr));
|
||||
}
|
||||
|
||||
GtkClipboard* clipboard =
|
||||
gtk_clipboard_get_default(gdk_display_get_default());
|
||||
gtk_clipboard_set_text(clipboard, fl_value_get_string(text_value), -1);
|
||||
|
||||
return FL_METHOD_RESPONSE(fl_method_success_response_new(nullptr));
|
||||
}
|
||||
|
||||
// Called when Flutter wants to paste from the clipboard.
|
||||
static FlMethodResponse* clipboard_get_data_async(FlPlatformPlugin* self,
|
||||
FlMethodCall* method_call) {
|
||||
FlValue* args = fl_method_call_get_args(method_call);
|
||||
|
||||
if (fl_value_get_type(args) != FL_VALUE_TYPE_STRING) {
|
||||
return FL_METHOD_RESPONSE(fl_method_error_response_new(
|
||||
kBadArgumentsError, "Expected string", nullptr));
|
||||
}
|
||||
|
||||
const gchar* format = fl_value_get_string(args);
|
||||
if (strcmp(format, kTextPlainFormat) != 0) {
|
||||
return FL_METHOD_RESPONSE(fl_method_error_response_new(
|
||||
kUnknownClipboardFormatError, "GTK clipboard API only supports text",
|
||||
nullptr));
|
||||
}
|
||||
|
||||
GtkClipboard* clipboard =
|
||||
gtk_clipboard_get_default(gdk_display_get_default());
|
||||
gtk_clipboard_request_text(clipboard, clipboard_text_cb,
|
||||
g_object_ref(method_call));
|
||||
|
||||
// Will response later.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Called when Flutter wants to quit the application.
|
||||
static FlMethodResponse* system_navigator_pop(FlPlatformPlugin* self) {
|
||||
GApplication* app = g_application_get_default();
|
||||
if (app == nullptr) {
|
||||
return FL_METHOD_RESPONSE(fl_method_error_response_new(
|
||||
kFailedError, "Unable to get GApplication", nullptr));
|
||||
}
|
||||
|
||||
g_application_quit(app);
|
||||
|
||||
return FL_METHOD_RESPONSE(fl_method_success_response_new(nullptr));
|
||||
}
|
||||
|
||||
// Called when a method call is received from Flutter.
|
||||
static void method_call_cb(FlMethodChannel* channel,
|
||||
FlMethodCall* method_call,
|
||||
gpointer user_data) {
|
||||
FlPlatformPlugin* self = FL_PLATFORM_PLUGIN(user_data);
|
||||
|
||||
const gchar* method = fl_method_call_get_name(method_call);
|
||||
FlValue* args = fl_method_call_get_args(method_call);
|
||||
|
||||
g_autoptr(FlMethodResponse) response = nullptr;
|
||||
if (strcmp(method, kSetClipboardDataMethod) == 0)
|
||||
response = clipboard_set_data(self, args);
|
||||
else if (strcmp(method, kGetClipboardDataMethod) == 0)
|
||||
response = clipboard_get_data_async(self, method_call);
|
||||
else if (strcmp(method, kSystemNavigatorPopMethod) == 0)
|
||||
response = system_navigator_pop(self);
|
||||
else
|
||||
response = FL_METHOD_RESPONSE(fl_method_not_implemented_response_new());
|
||||
|
||||
if (response != nullptr)
|
||||
send_response(method_call, response);
|
||||
}
|
||||
|
||||
static void fl_platform_plugin_dispose(GObject* object) {
|
||||
FlPlatformPlugin* self = FL_PLATFORM_PLUGIN(object);
|
||||
|
||||
g_clear_object(&self->channel);
|
||||
|
||||
G_OBJECT_CLASS(fl_platform_plugin_parent_class)->dispose(object);
|
||||
}
|
||||
|
||||
static void fl_platform_plugin_class_init(FlPlatformPluginClass* klass) {
|
||||
G_OBJECT_CLASS(klass)->dispose = fl_platform_plugin_dispose;
|
||||
}
|
||||
|
||||
static void fl_platform_plugin_init(FlPlatformPlugin* self) {}
|
||||
|
||||
FlPlatformPlugin* fl_platform_plugin_new(FlBinaryMessenger* messenger) {
|
||||
g_return_val_if_fail(FL_IS_BINARY_MESSENGER(messenger), nullptr);
|
||||
|
||||
FlPlatformPlugin* self =
|
||||
FL_PLATFORM_PLUGIN(g_object_new(fl_platform_plugin_get_type(), nullptr));
|
||||
|
||||
g_autoptr(FlJsonMethodCodec) codec = fl_json_method_codec_new();
|
||||
self->channel =
|
||||
fl_method_channel_new(messenger, kChannelName, FL_METHOD_CODEC(codec));
|
||||
fl_method_channel_set_method_call_handler(self->channel, method_call_cb, self,
|
||||
nullptr);
|
||||
|
||||
return self;
|
||||
}
|
||||
38
engine/src/flutter/shell/platform/linux/fl_platform_plugin.h
Normal file
38
engine/src/flutter/shell/platform/linux/fl_platform_plugin.h
Normal file
@ -0,0 +1,38 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef FLUTTER_SHELL_PLATFORM_LINUX_FL_PLATFORM_PLUGIN_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_LINUX_FL_PLATFORM_PLUGIN_H_
|
||||
|
||||
#include "flutter/shell/platform/linux/public/flutter_linux/fl_binary_messenger.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
G_DECLARE_FINAL_TYPE(FlPlatformPlugin,
|
||||
fl_platform_plugin,
|
||||
FL,
|
||||
PLATFORM_PLUGIN,
|
||||
GObject);
|
||||
|
||||
/**
|
||||
* FlPlatformPlugin:
|
||||
*
|
||||
* #FlPlatformPlugin is a plugin that implements the shell side
|
||||
* of PlatformPlugins.platform from the Flutter services library.
|
||||
*/
|
||||
|
||||
/**
|
||||
* fl_platform_plugin_new:
|
||||
* @messenger: an #FlBinaryMessenger
|
||||
*
|
||||
* Creates a new plugin that implements SystemChannels.platform from the
|
||||
* Flutter services library.
|
||||
*
|
||||
* Returns: a new #FlPlatformPlugin
|
||||
*/
|
||||
FlPlatformPlugin* fl_platform_plugin_new(FlBinaryMessenger* messenger);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif // FLUTTER_SHELL_PLATFORM_LINUX_FL_PLATFORM_PLUGIN_H_
|
||||
@ -6,6 +6,7 @@
|
||||
|
||||
#include "flutter/shell/platform/linux/fl_engine_private.h"
|
||||
#include "flutter/shell/platform/linux/fl_key_event_plugin.h"
|
||||
#include "flutter/shell/platform/linux/fl_platform_plugin.h"
|
||||
#include "flutter/shell/platform/linux/fl_plugin_registrar_private.h"
|
||||
#include "flutter/shell/platform/linux/fl_renderer_x11.h"
|
||||
#include "flutter/shell/platform/linux/fl_text_input_plugin.h"
|
||||
@ -33,6 +34,7 @@ struct _FlView {
|
||||
|
||||
// Flutter system channel handlers.
|
||||
FlKeyEventPlugin* key_event_plugin;
|
||||
FlPlatformPlugin* platform_plugin;
|
||||
FlTextInputPlugin* text_input_plugin;
|
||||
};
|
||||
|
||||
@ -129,6 +131,7 @@ static void fl_view_constructed(GObject* object) {
|
||||
// Create system channel handlers.
|
||||
FlBinaryMessenger* messenger = fl_engine_get_binary_messenger(self->engine);
|
||||
self->key_event_plugin = fl_key_event_plugin_new(messenger);
|
||||
self->platform_plugin = fl_platform_plugin_new(messenger);
|
||||
self->text_input_plugin = fl_text_input_plugin_new(messenger);
|
||||
}
|
||||
|
||||
@ -183,6 +186,7 @@ static void fl_view_dispose(GObject* object) {
|
||||
g_clear_object(&self->renderer);
|
||||
g_clear_object(&self->engine);
|
||||
g_clear_object(&self->key_event_plugin);
|
||||
g_clear_object(&self->platform_plugin);
|
||||
g_clear_object(&self->text_input_plugin);
|
||||
|
||||
G_OBJECT_CLASS(fl_view_parent_class)->dispose(object);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user