Flutter Engine
fl_text_input_plugin.cc File Reference
#include "flutter/shell/platform/linux/fl_text_input_plugin.h"
#include <gtk/gtk.h>
#include "flutter/shell/platform/common/cpp/text_input_model.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"

Go to the source code of this file.

Classes

struct  _FlTextInputPlugin
 

Functions

static gboolean finish_method (GObject *object, GAsyncResult *result, GError **error)
 
static void update_editing_state_response_cb (GObject *object, GAsyncResult *result, gpointer user_data)
 
static void update_editing_state (FlTextInputPlugin *self)
 
static void perform_action_response_cb (GObject *object, GAsyncResult *result, gpointer user_data)
 
static void perform_action (FlTextInputPlugin *self)
 
static void im_preedit_start_cb (FlTextInputPlugin *self)
 
static void im_preedit_changed_cb (FlTextInputPlugin *self)
 
static void im_commit_cb (FlTextInputPlugin *self, const gchar *text)
 
static void im_preedit_end_cb (FlTextInputPlugin *self)
 
static gboolean im_retrieve_surrounding_cb (FlTextInputPlugin *self)
 
static gboolean im_delete_surrounding_cb (FlTextInputPlugin *self, gint offset, gint n_chars)
 
static FlMethodResponse * set_client (FlTextInputPlugin *self, FlValue *args)
 
static FlMethodResponse * show (FlTextInputPlugin *self)
 
static FlMethodResponse * set_editing_state (FlTextInputPlugin *self, FlValue *args)
 
static FlMethodResponse * clear_client (FlTextInputPlugin *self)
 
static FlMethodResponse * hide (FlTextInputPlugin *self)
 
static void update_im_cursor_position (FlTextInputPlugin *self)
 
static FlMethodResponse * set_editable_size_and_transform (FlTextInputPlugin *self, FlValue *args)
 
static FlMethodResponse * set_marked_text_rect (FlTextInputPlugin *self, FlValue *args)
 
static void method_call_cb (FlMethodChannel *channel, FlMethodCall *method_call, gpointer user_data)
 
static void view_weak_notify_cb (gpointer user_data, GObject *object)
 
static void fl_text_input_plugin_dispose (GObject *object)
 
static void fl_text_input_plugin_class_init (FlTextInputPluginClass *klass)
 
static void fl_text_input_plugin_init (FlTextInputPlugin *self)
 
FlTextInputPlugin * fl_text_input_plugin_new (FlBinaryMessenger *messenger, FlView *view)
 
gboolean fl_text_input_plugin_filter_keypress (FlTextInputPlugin *self, GdkEventKey *event)
 

Variables

static constexpr char kChannelName [] = "flutter/textinput"
 
static constexpr char kBadArgumentsError [] = "Bad Arguments"
 
static constexpr char kSetClientMethod [] = "TextInput.setClient"
 
static constexpr char kShowMethod [] = "TextInput.show"
 
static constexpr char kSetEditingStateMethod [] = "TextInput.setEditingState"
 
static constexpr char kClearClientMethod [] = "TextInput.clearClient"
 
static constexpr char kHideMethod [] = "TextInput.hide"
 
static constexpr char kUpdateEditingStateMethod []
 
static constexpr char kPerformActionMethod [] = "TextInputClient.performAction"
 
static constexpr char kSetEditableSizeAndTransform []
 
static constexpr char kSetMarkedTextRect [] = "TextInput.setMarkedTextRect"
 
static constexpr char kInputActionKey [] = "inputAction"
 
static constexpr char kTextInputTypeKey [] = "inputType"
 
static constexpr char kTextInputTypeNameKey [] = "name"
 
static constexpr char kTextKey [] = "text"
 
static constexpr char kSelectionBaseKey [] = "selectionBase"
 
static constexpr char kSelectionExtentKey [] = "selectionExtent"
 
static constexpr char kSelectionAffinityKey [] = "selectionAffinity"
 
static constexpr char kSelectionIsDirectionalKey [] = "selectionIsDirectional"
 
static constexpr char kComposingBaseKey [] = "composingBase"
 
static constexpr char kComposingExtentKey [] = "composingExtent"
 
static constexpr char kTransform [] = "transform"
 
static constexpr char kTextAffinityDownstream [] = "TextAffinity.downstream"
 
static constexpr char kMultilineInputType [] = "TextInputType.multiline"
 
static constexpr int64_t kClientIdUnset = -1
 

Function Documentation

◆ clear_client()

static FlMethodResponse* clear_client ( FlTextInputPlugin *  self)
static

Definition at line 302 of file fl_text_input_plugin.cc.

References fl_method_success_response_new(), and kClientIdUnset.

Referenced by method_call_cb().

302  {
303  self->client_id = kClientIdUnset;
304 
305  return FL_METHOD_RESPONSE(fl_method_success_response_new(nullptr));
306 }
G_MODULE_EXPORT FlMethodSuccessResponse * fl_method_success_response_new(FlValue *result)
static constexpr int64_t kClientIdUnset

◆ finish_method()

static gboolean finish_method ( GObject *  object,
GAsyncResult *  result,
GError **  error 
)
static

Definition at line 83 of file fl_text_input_plugin.cc.

References fl_method_channel_invoke_method_finish(), and fl_method_response_get_result().

Referenced by perform_action_response_cb(), and update_editing_state_response_cb().

85  {
86  g_autoptr(FlMethodResponse) response = fl_method_channel_invoke_method_finish(
87  FL_METHOD_CHANNEL(object), result, error);
88  if (response == nullptr) {
89  return FALSE;
90  }
91  return fl_method_response_get_result(response, error) != nullptr;
92 }
G_MODULE_EXPORT FlMethodResponse * fl_method_channel_invoke_method_finish(FlMethodChannel *self, GAsyncResult *result, GError **error)
FlMethodResponse GError ** error
G_MODULE_EXPORT FlValue * fl_method_response_get_result(FlMethodResponse *self, GError **error)

◆ fl_text_input_plugin_class_init()

static void fl_text_input_plugin_class_init ( FlTextInputPluginClass *  klass)
static

Definition at line 445 of file fl_text_input_plugin.cc.

References fl_text_input_plugin_dispose().

445  {
446  G_OBJECT_CLASS(klass)->dispose = fl_text_input_plugin_dispose;
447 }
static void fl_text_input_plugin_dispose(GObject *object)

◆ fl_text_input_plugin_dispose()

static void fl_text_input_plugin_dispose ( GObject *  object)
static

Definition at line 431 of file fl_text_input_plugin.cc.

Referenced by fl_text_input_plugin_class_init().

431  {
432  FlTextInputPlugin* self = FL_TEXT_INPUT_PLUGIN(object);
433 
434  g_clear_object(&self->channel);
435  g_clear_pointer(&self->input_action, g_free);
436  g_clear_object(&self->im_context);
437  if (self->text_model != nullptr) {
438  delete self->text_model;
439  self->text_model = nullptr;
440  }
441 
442  G_OBJECT_CLASS(fl_text_input_plugin_parent_class)->dispose(object);
443 }

◆ fl_text_input_plugin_filter_keypress()

gboolean fl_text_input_plugin_filter_keypress ( FlTextInputPlugin *  plugin,
GdkEventKey *  event 
)

fl_text_input_plugin_filter_keypress : an #FlTextInputPlugin. : a #GdkEventKey

Process a Gdk key event.

Returns: TRUE if the event was used.

Definition at line 491 of file fl_text_input_plugin.cc.

References kClientIdUnset, perform_action(), TRUE, and update_editing_state().

Referenced by fl_view_key_press_event(), and fl_view_key_release_event().

492  {
493  g_return_val_if_fail(FL_IS_TEXT_INPUT_PLUGIN(self), FALSE);
494 
495  if (self->client_id == kClientIdUnset) {
496  return FALSE;
497  }
498 
499  if (gtk_im_context_filter_keypress(self->im_context, event)) {
500  return TRUE;
501  }
502 
503  // Handle the enter/return key.
504  gboolean do_action = FALSE;
505  // Handle navigation keys.
506  gboolean changed = FALSE;
507  if (event->type == GDK_KEY_PRESS) {
508  switch (event->keyval) {
509  case GDK_KEY_BackSpace:
510  changed = self->text_model->Backspace();
511  break;
512  case GDK_KEY_Delete:
513  case GDK_KEY_KP_Delete:
514  // Already handled inside Flutter.
515  break;
516  case GDK_KEY_End:
517  case GDK_KEY_KP_End:
518  changed = self->text_model->MoveCursorToEnd();
519  break;
520  case GDK_KEY_Return:
521  case GDK_KEY_KP_Enter:
522  case GDK_KEY_ISO_Enter:
523  if (self->input_multiline == TRUE) {
524  self->text_model->AddCodePoint('\n');
525  changed = TRUE;
526  }
527  do_action = TRUE;
528  break;
529  case GDK_KEY_Home:
530  case GDK_KEY_KP_Home:
531  changed = self->text_model->MoveCursorToBeginning();
532  break;
533  case GDK_KEY_Left:
534  case GDK_KEY_KP_Left:
535  // Already handled inside Flutter.
536  break;
537  case GDK_KEY_Right:
538  case GDK_KEY_KP_Right:
539  // Already handled inside Flutter.
540  break;
541  }
542  }
543 
544  if (changed) {
545  update_editing_state(self);
546  }
547  if (do_action) {
548  perform_action(self);
549  }
550 
551  return FALSE;
552 }
static void update_editing_state(FlTextInputPlugin *self)
static void perform_action(FlTextInputPlugin *self)
static constexpr int64_t kClientIdUnset
GdkEventButton * event
Definition: fl_view.cc:62
return TRUE
Definition: fl_view.cc:107

◆ fl_text_input_plugin_init()

static void fl_text_input_plugin_init ( FlTextInputPlugin *  self)
static

Definition at line 449 of file fl_text_input_plugin.cc.

References im_commit_cb(), im_delete_surrounding_cb(), im_preedit_changed_cb(), im_preedit_end_cb(), im_preedit_start_cb(), im_retrieve_surrounding_cb(), and kClientIdUnset.

449  {
450  self->client_id = kClientIdUnset;
451  self->im_context = gtk_im_multicontext_new();
452  self->input_multiline = FALSE;
453  g_signal_connect_object(self->im_context, "preedit-start",
454  G_CALLBACK(im_preedit_start_cb), self,
455  G_CONNECT_SWAPPED);
456  g_signal_connect_object(self->im_context, "preedit-end",
457  G_CALLBACK(im_preedit_end_cb), self,
458  G_CONNECT_SWAPPED);
459  g_signal_connect_object(self->im_context, "preedit-changed",
460  G_CALLBACK(im_preedit_changed_cb), self,
461  G_CONNECT_SWAPPED);
462  g_signal_connect_object(self->im_context, "commit", G_CALLBACK(im_commit_cb),
463  self, G_CONNECT_SWAPPED);
464  g_signal_connect_object(self->im_context, "retrieve-surrounding",
465  G_CALLBACK(im_retrieve_surrounding_cb), self,
466  G_CONNECT_SWAPPED);
467  g_signal_connect_object(self->im_context, "delete-surrounding",
468  G_CALLBACK(im_delete_surrounding_cb), self,
469  G_CONNECT_SWAPPED);
470  self->text_model = new flutter::TextInputModel();
471 }
static gboolean im_delete_surrounding_cb(FlTextInputPlugin *self, gint offset, gint n_chars)
static void im_preedit_end_cb(FlTextInputPlugin *self)
static gboolean im_retrieve_surrounding_cb(FlTextInputPlugin *self)
static void im_preedit_start_cb(FlTextInputPlugin *self)
static void im_commit_cb(FlTextInputPlugin *self, const gchar *text)
static constexpr int64_t kClientIdUnset
static void im_preedit_changed_cb(FlTextInputPlugin *self)

◆ fl_text_input_plugin_new()

FlTextInputPlugin* fl_text_input_plugin_new ( FlBinaryMessenger *  messenger,
FlView *  view 
)

FlTextInputPlugin:

#FlTextInputPlugin is a plugin that implements the shell side of SystemChannels.textInput from the Flutter services library. fl_text_input_plugin_new: : an #FlBinaryMessenger. : the #FlView with which the text input plugin is associated.

Creates a new plugin that implements SystemChannels.textInput from the Flutter services library.

Returns: a new #FlTextInputPlugin.

Definition at line 473 of file fl_text_input_plugin.cc.

References fl_json_method_codec_new(), fl_method_channel_new(), fl_method_channel_set_method_call_handler(), kChannelName, method_call_cb(), _FlTextInputPlugin::view, and view_weak_notify_cb().

Referenced by fl_view_constructed().

474  {
475  g_return_val_if_fail(FL_IS_BINARY_MESSENGER(messenger), nullptr);
476 
477  FlTextInputPlugin* self = FL_TEXT_INPUT_PLUGIN(
478  g_object_new(fl_text_input_plugin_get_type(), nullptr));
479 
480  g_autoptr(FlJsonMethodCodec) codec = fl_json_method_codec_new();
481  self->channel =
482  fl_method_channel_new(messenger, kChannelName, FL_METHOD_CODEC(codec));
484  nullptr);
485  self->view = view;
486  g_object_weak_ref(G_OBJECT(view), view_weak_notify_cb, self);
487 
488  return self;
489 }
static void view_weak_notify_cb(gpointer user_data, GObject *object)
G_MODULE_EXPORT FlJsonMethodCodec * fl_json_method_codec_new()
G_MODULE_EXPORT void fl_method_channel_set_method_call_handler(FlMethodChannel *self, FlMethodChannelMethodCallHandler handler, gpointer user_data, GDestroyNotify destroy_notify)
G_MODULE_EXPORT FlMethodChannel * fl_method_channel_new(FlBinaryMessenger *messenger, const gchar *name, FlMethodCodec *codec)
static constexpr char kChannelName[]
static void method_call_cb(FlMethodChannel *channel, FlMethodCall *method_call, gpointer user_data)

◆ hide()

static FlMethodResponse* hide ( FlTextInputPlugin *  self)
static

Definition at line 309 of file fl_text_input_plugin.cc.

References fl_method_success_response_new().

Referenced by method_call_cb().

309  {
310  gtk_im_context_focus_out(self->im_context);
311 
312  return FL_METHOD_RESPONSE(fl_method_success_response_new(nullptr));
313 }
G_MODULE_EXPORT FlMethodSuccessResponse * fl_method_success_response_new(FlValue *result)

◆ im_commit_cb()

static void im_commit_cb ( FlTextInputPlugin *  self,
const gchar *  text 
)
static

Definition at line 192 of file fl_text_input_plugin.cc.

References update_editing_state().

Referenced by fl_text_input_plugin_init().

192  {
193  self->text_model->AddText(text);
194  if (self->text_model->composing()) {
195  self->text_model->CommitComposing();
196  }
197  update_editing_state(self);
198 }
static void update_editing_state(FlTextInputPlugin *self)

◆ im_delete_surrounding_cb()

static gboolean im_delete_surrounding_cb ( FlTextInputPlugin *  self,
gint  offset,
gint  n_chars 
)
static

Definition at line 216 of file fl_text_input_plugin.cc.

References TRUE, and update_editing_state().

Referenced by fl_text_input_plugin_init().

218  {
219  if (self->text_model->DeleteSurrounding(offset, n_chars)) {
220  update_editing_state(self);
221  }
222  return TRUE;
223 }
static void update_editing_state(FlTextInputPlugin *self)
return TRUE
Definition: fl_view.cc:107

◆ im_preedit_changed_cb()

static void im_preedit_changed_cb ( FlTextInputPlugin *  self)
static

Definition at line 179 of file fl_text_input_plugin.cc.

References update_editing_state().

Referenced by fl_text_input_plugin_init().

179  {
180  g_autofree gchar* buf = nullptr;
181  gint cursor_offset = 0;
182  gtk_im_context_get_preedit_string(self->im_context, &buf, nullptr,
183  &cursor_offset);
184  cursor_offset += self->text_model->composing_range().base();
185  self->text_model->UpdateComposingText(buf);
186  self->text_model->SetSelection(TextRange(cursor_offset, cursor_offset));
187 
188  update_editing_state(self);
189 }
static void update_editing_state(FlTextInputPlugin *self)

◆ im_preedit_end_cb()

static void im_preedit_end_cb ( FlTextInputPlugin *  self)
static

Definition at line 201 of file fl_text_input_plugin.cc.

References update_editing_state().

Referenced by fl_text_input_plugin_init().

201  {
202  self->text_model->EndComposing();
203  update_editing_state(self);
204 }
static void update_editing_state(FlTextInputPlugin *self)

◆ im_preedit_start_cb()

static void im_preedit_start_cb ( FlTextInputPlugin *  self)
static

Definition at line 169 of file fl_text_input_plugin.cc.

Referenced by fl_text_input_plugin_init().

169  {
170  self->text_model->BeginComposing();
171 
172  // Set the top-level window used for system input method windows.
173  GdkWindow* window =
174  gtk_widget_get_window(gtk_widget_get_toplevel(GTK_WIDGET(self->view)));
175  gtk_im_context_set_client_window(self->im_context, window);
176 }

◆ im_retrieve_surrounding_cb()

static gboolean im_retrieve_surrounding_cb ( FlTextInputPlugin *  self)
static

Definition at line 207 of file fl_text_input_plugin.cc.

References TRUE.

Referenced by fl_text_input_plugin_init().

207  {
208  auto text = self->text_model->GetText();
209  size_t cursor_offset = self->text_model->GetCursorOffset();
210  gtk_im_context_set_surrounding(self->im_context, text.c_str(), -1,
211  cursor_offset);
212  return TRUE;
213 }
return TRUE
Definition: fl_view.cc:107

◆ method_call_cb()

static void method_call_cb ( FlMethodChannel *  channel,
FlMethodCall *  method_call,
gpointer  user_data 
)
static

Definition at line 393 of file fl_text_input_plugin.cc.

References clear_client(), error, fl_method_call_get_args(), fl_method_call_get_name(), fl_method_call_respond(), fl_method_not_implemented_response_new(), hide(), kClearClientMethod, kHideMethod, kSetClientMethod, kSetEditableSizeAndTransform, kSetEditingStateMethod, kSetMarkedTextRect, kShowMethod, set_client(), set_editable_size_and_transform(), set_editing_state(), set_marked_text_rect(), and show().

Referenced by fl_text_input_plugin_new().

395  {
396  FlTextInputPlugin* self = FL_TEXT_INPUT_PLUGIN(user_data);
397 
398  const gchar* method = fl_method_call_get_name(method_call);
400 
401  g_autoptr(FlMethodResponse) response = nullptr;
402  if (strcmp(method, kSetClientMethod) == 0) {
403  response = set_client(self, args);
404  } else if (strcmp(method, kShowMethod) == 0) {
405  response = show(self);
406  } else if (strcmp(method, kSetEditingStateMethod) == 0) {
407  response = set_editing_state(self, args);
408  } else if (strcmp(method, kClearClientMethod) == 0) {
409  response = clear_client(self);
410  } else if (strcmp(method, kHideMethod) == 0) {
411  response = hide(self);
412  } else if (strcmp(method, kSetEditableSizeAndTransform) == 0) {
413  response = set_editable_size_and_transform(self, args);
414  } else if (strcmp(method, kSetMarkedTextRect) == 0) {
415  response = set_marked_text_rect(self, args);
416  } else {
417  response = FL_METHOD_RESPONSE(fl_method_not_implemented_response_new());
418  }
419 
420  g_autoptr(GError) error = nullptr;
421  if (!fl_method_call_respond(method_call, response, &error)) {
422  g_warning("Failed to send method call response: %s", error->message);
423  }
424 }
static constexpr char kSetMarkedTextRect[]
G_BEGIN_DECLS FlMethodCall * method_call
static constexpr char kSetClientMethod[]
typedefG_BEGIN_DECLS struct _FlValue FlValue
Definition: fl_value.h:39
FlMethodResponse GError ** error
static constexpr char kShowMethod[]
static FlMethodResponse * set_editing_state(FlTextInputPlugin *self, FlValue *args)
static constexpr char kSetEditableSizeAndTransform[]
G_MODULE_EXPORT FlValue * fl_method_call_get_args(FlMethodCall *self)
G_MODULE_EXPORT gboolean fl_method_call_respond(FlMethodCall *self, FlMethodResponse *response, GError **error)
static FlMethodResponse * set_editable_size_and_transform(FlTextInputPlugin *self, FlValue *args)
static FlMethodResponse * hide(FlTextInputPlugin *self)
G_MODULE_EXPORT const gchar * fl_method_call_get_name(FlMethodCall *self)
static constexpr char kSetEditingStateMethod[]
static FlMethodResponse * set_marked_text_rect(FlTextInputPlugin *self, FlValue *args)
G_BEGIN_DECLS FlMethodCall gpointer user_data
static constexpr char kClearClientMethod[]
static FlMethodResponse * clear_client(FlTextInputPlugin *self)
static constexpr char kHideMethod[]
G_MODULE_EXPORT FlMethodNotImplementedResponse * fl_method_not_implemented_response_new()
static FlMethodResponse * set_client(FlTextInputPlugin *self, FlValue *args)
static FlMethodResponse * show(FlTextInputPlugin *self)

◆ perform_action()

static void perform_action ( FlTextInputPlugin *  self)
static

Definition at line 155 of file fl_text_input_plugin.cc.

References fl_method_channel_invoke_method(), fl_value_append_take(), fl_value_new_int(), fl_value_new_list(), fl_value_new_string(), kPerformActionMethod, and perform_action_response_cb().

Referenced by fl_text_input_plugin_filter_keypress().

155  {
156  g_return_if_fail(FL_IS_TEXT_INPUT_PLUGIN(self));
157  g_return_if_fail(self->client_id != 0);
158  g_return_if_fail(self->input_action != nullptr);
159 
160  g_autoptr(FlValue) args = fl_value_new_list();
161  fl_value_append_take(args, fl_value_new_int(self->client_id));
162  fl_value_append_take(args, fl_value_new_string(self->input_action));
163 
165  nullptr, perform_action_response_cb, self);
166 }
G_MODULE_EXPORT FlValue * fl_value_new_list()
Definition: fl_value.cc:310
typedefG_BEGIN_DECLS struct _FlValue FlValue
Definition: fl_value.h:39
static constexpr char kPerformActionMethod[]
G_MODULE_EXPORT void fl_value_append_take(FlValue *self, FlValue *value)
Definition: fl_value.cc:514
G_MODULE_EXPORT FlValue * fl_value_new_int(int64_t value)
Definition: fl_value.cc:233
G_MODULE_EXPORT FlValue * fl_value_new_string(const gchar *value)
Definition: fl_value.cc:247
G_MODULE_EXPORT void fl_method_channel_invoke_method(FlMethodChannel *self, const gchar *method, FlValue *args, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
static void perform_action_response_cb(GObject *object, GAsyncResult *result, gpointer user_data)

◆ perform_action_response_cb()

static void perform_action_response_cb ( GObject *  object,
GAsyncResult *  result,
gpointer  user_data 
)
static

Definition at line 145 of file fl_text_input_plugin.cc.

References error, finish_method(), and kPerformActionMethod.

Referenced by perform_action().

147  {
148  g_autoptr(GError) error = nullptr;
149  if (!finish_method(object, result, &error)) {
150  g_warning("Failed to call %s: %s", kPerformActionMethod, error->message);
151  }
152 }
FlMethodResponse GError ** error
static gboolean finish_method(GObject *object, GAsyncResult *result, GError **error)
static constexpr char kPerformActionMethod[]

◆ set_client()

static FlMethodResponse* set_client ( FlTextInputPlugin *  self,
FlValue args 
)
static

Definition at line 226 of file fl_text_input_plugin.cc.

References fl_method_error_response_new(), fl_method_success_response_new(), fl_value_get_int(), fl_value_get_length(), fl_value_get_list_value(), fl_value_get_string(), fl_value_get_type(), fl_value_lookup_string(), FL_VALUE_TYPE_LIST, FL_VALUE_TYPE_MAP, FL_VALUE_TYPE_STRING, kBadArgumentsError, kInputActionKey, kMultilineInputType, kTextInputTypeKey, kTextInputTypeNameKey, and TRUE.

Referenced by method_call_cb().

226  {
227  if (fl_value_get_type(args) != FL_VALUE_TYPE_LIST ||
228  fl_value_get_length(args) < 2) {
229  return FL_METHOD_RESPONSE(fl_method_error_response_new(
230  kBadArgumentsError, "Expected 2-element list", nullptr));
231  }
232 
233  self->client_id = fl_value_get_int(fl_value_get_list_value(args, 0));
234  FlValue* config_value = fl_value_get_list_value(args, 1);
235  g_free(self->input_action);
236  FlValue* input_action_value =
238  if (fl_value_get_type(input_action_value) == FL_VALUE_TYPE_STRING) {
239  self->input_action = g_strdup(fl_value_get_string(input_action_value));
240  }
241 
242  // Clear the multiline flag, then set it only if the field is multiline.
243  self->input_multiline = FALSE;
244  FlValue* input_type_value =
246  if (fl_value_get_type(input_type_value) == FL_VALUE_TYPE_MAP) {
247  FlValue* input_type_name =
249  if (fl_value_get_type(input_type_name) == FL_VALUE_TYPE_STRING &&
250  g_strcmp0(fl_value_get_string(input_type_name), kMultilineInputType) ==
251  0) {
252  self->input_multiline = TRUE;
253  }
254  }
255 
256  return FL_METHOD_RESPONSE(fl_method_success_response_new(nullptr));
257 }
G_MODULE_EXPORT FlMethodSuccessResponse * fl_method_success_response_new(FlValue *result)
G_MODULE_EXPORT FlValueType fl_value_get_type(FlValue *self)
Definition: fl_value.cc:395
typedefG_BEGIN_DECLS struct _FlValue FlValue
Definition: fl_value.h:39
G_MODULE_EXPORT int64_t fl_value_get_int(FlValue *self)
Definition: fl_value.cc:582
static constexpr char kMultilineInputType[]
G_MODULE_EXPORT FlValue * fl_value_lookup_string(FlValue *self, const gchar *key)
Definition: fl_value.cc:712
static constexpr char kInputActionKey[]
G_MODULE_EXPORT FlValue * fl_value_get_list_value(FlValue *self, size_t index)
Definition: fl_value.cc:677
return TRUE
Definition: fl_view.cc:107
G_MODULE_EXPORT const gchar * fl_value_get_string(FlValue *self)
Definition: fl_value.cc:596
static constexpr char kBadArgumentsError[]
G_MODULE_EXPORT size_t fl_value_get_length(FlValue *self)
Definition: fl_value.cc:631
static constexpr char kTextInputTypeNameKey[]
static constexpr char kTextInputTypeKey[]
G_MODULE_EXPORT FlMethodErrorResponse * fl_method_error_response_new(const gchar *code, const gchar *message, FlValue *details)

◆ set_editable_size_and_transform()

static FlMethodResponse* set_editable_size_and_transform ( FlTextInputPlugin *  self,
FlValue args 
)
static

Definition at line 355 of file fl_text_input_plugin.cc.

References fl_method_success_response_new(), fl_value_get_float(), fl_value_get_length(), fl_value_get_list_value(), fl_value_lookup_string(), kTransform, flutter::transform, and update_im_cursor_position().

Referenced by method_call_cb().

357  {
359  size_t transform_len = fl_value_get_length(transform);
360  g_warn_if_fail(transform_len == 16);
361 
362  for (size_t i = 0; i < transform_len; ++i) {
363  double val = fl_value_get_float(fl_value_get_list_value(transform, i));
364  self->editabletext_transform[i / 4][i % 4] = val;
365  }
367 
368  return FL_METHOD_RESPONSE(fl_method_success_response_new(nullptr));
369 }
G_MODULE_EXPORT FlMethodSuccessResponse * fl_method_success_response_new(FlValue *result)
typedefG_BEGIN_DECLS struct _FlValue FlValue
Definition: fl_value.h:39
G_MODULE_EXPORT double fl_value_get_float(FlValue *self)
Definition: fl_value.cc:589
G_MODULE_EXPORT FlValue * fl_value_lookup_string(FlValue *self, const gchar *key)
Definition: fl_value.cc:712
static void update_im_cursor_position(FlTextInputPlugin *self)
G_MODULE_EXPORT FlValue * fl_value_get_list_value(FlValue *self, size_t index)
Definition: fl_value.cc:677
static constexpr char kTransform[]
G_MODULE_EXPORT size_t fl_value_get_length(FlValue *self)
Definition: fl_value.cc:631

◆ set_editing_state()

static FlMethodResponse* set_editing_state ( FlTextInputPlugin *  self,
FlValue args 
)
static

Definition at line 267 of file fl_text_input_plugin.cc.

References fl_method_success_response_new(), fl_value_get_int(), fl_value_get_string(), fl_value_lookup_string(), kComposingBaseKey, kComposingExtentKey, kSelectionBaseKey, kSelectionExtentKey, and kTextKey.

Referenced by method_call_cb().

268  {
269  const gchar* text =
271  self->text_model->SetText(text);
272 
273  int64_t selection_base =
275  int64_t selection_extent =
277  // Flutter uses -1/-1 for invalid; translate that to 0/0 for the model.
278  if (selection_base == -1 && selection_extent == -1) {
279  selection_base = selection_extent = 0;
280  }
281 
282  self->text_model->SetText(text);
283  self->text_model->SetSelection(TextRange(selection_base, selection_extent));
284 
285  int64_t composing_base =
287  int64_t composing_extent =
289  if (composing_base == -1 && composing_extent == -1) {
290  self->text_model->EndComposing();
291  } else {
292  size_t composing_start = std::min(composing_base, composing_extent);
293  size_t cursor_offset = selection_base - composing_start;
294  self->text_model->SetComposingRange(
295  TextRange(composing_base, composing_extent), cursor_offset);
296  }
297 
298  return FL_METHOD_RESPONSE(fl_method_success_response_new(nullptr));
299 }
G_MODULE_EXPORT FlMethodSuccessResponse * fl_method_success_response_new(FlValue *result)
G_MODULE_EXPORT int64_t fl_value_get_int(FlValue *self)
Definition: fl_value.cc:582
static constexpr char kComposingBaseKey[]
static constexpr char kComposingExtentKey[]
G_MODULE_EXPORT FlValue * fl_value_lookup_string(FlValue *self, const gchar *key)
Definition: fl_value.cc:712
static constexpr char kTextKey[]
static constexpr char kSelectionExtentKey[]
static constexpr char kSelectionBaseKey[]
G_MODULE_EXPORT const gchar * fl_value_get_string(FlValue *self)
Definition: fl_value.cc:596

◆ set_marked_text_rect()

static FlMethodResponse* set_marked_text_rect ( FlTextInputPlugin *  self,
FlValue args 
)
static

Definition at line 377 of file fl_text_input_plugin.cc.

References fl_method_success_response_new(), fl_value_get_float(), fl_value_lookup_string(), and update_im_cursor_position().

Referenced by method_call_cb().

378  {
379  self->composing_rect.x =
381  self->composing_rect.y =
383  self->composing_rect.width =
385  self->composing_rect.height =
388 
389  return FL_METHOD_RESPONSE(fl_method_success_response_new(nullptr));
390 }
G_MODULE_EXPORT FlMethodSuccessResponse * fl_method_success_response_new(FlValue *result)
G_MODULE_EXPORT double fl_value_get_float(FlValue *self)
Definition: fl_value.cc:589
G_MODULE_EXPORT FlValue * fl_value_lookup_string(FlValue *self, const gchar *key)
Definition: fl_value.cc:712
static void update_im_cursor_position(FlTextInputPlugin *self)

◆ show()

static FlMethodResponse* show ( FlTextInputPlugin *  self)
static

Definition at line 260 of file fl_text_input_plugin.cc.

References fl_method_success_response_new().

Referenced by method_call_cb().

260  {
261  gtk_im_context_focus_in(self->im_context);
262 
263  return FL_METHOD_RESPONSE(fl_method_success_response_new(nullptr));
264 }
G_MODULE_EXPORT FlMethodSuccessResponse * fl_method_success_response_new(FlValue *result)

◆ update_editing_state()

static void update_editing_state ( FlTextInputPlugin *  self)
static

Definition at line 106 of file fl_text_input_plugin.cc.

References TextRange::base(), TextRange::extent(), fl_method_channel_invoke_method(), fl_value_append(), fl_value_append_take(), fl_value_new_bool(), fl_value_new_int(), fl_value_new_list(), fl_value_new_map(), fl_value_new_string(), fl_value_set_string_take(), kComposingBaseKey, kComposingExtentKey, kSelectionAffinityKey, kSelectionBaseKey, kSelectionExtentKey, kSelectionIsDirectionalKey, kTextAffinityDownstream, kTextKey, kUpdateEditingStateMethod, update_editing_state_response_cb(), and value.

Referenced by fl_text_input_plugin_filter_keypress(), im_commit_cb(), im_delete_surrounding_cb(), im_preedit_changed_cb(), and im_preedit_end_cb().

106  {
107  g_autoptr(FlValue) args = fl_value_new_list();
108  fl_value_append_take(args, fl_value_new_int(self->client_id));
109  g_autoptr(FlValue) value = fl_value_new_map();
110 
111  TextRange selection = self->text_model->selection();
113  value, kTextKey,
114  fl_value_new_string(self->text_model->GetText().c_str()));
116  fl_value_new_int(selection.base()));
118  fl_value_new_int(selection.extent()));
119 
120  int composing_base = self->text_model->composing()
121  ? self->text_model->composing_range().base()
122  : -1;
123  int composing_extent = self->text_model->composing()
124  ? self->text_model->composing_range().extent()
125  : -1;
127  fl_value_new_int(composing_base));
129  fl_value_new_int(composing_extent));
130 
131  // The following keys are not implemented and set to default values.
135  fl_value_new_bool(FALSE));
136 
137  fl_value_append(args, value);
138 
140  args, nullptr,
142 }
G_MODULE_EXPORT FlValue * fl_value_new_list()
Definition: fl_value.cc:310
size_t base() const
Definition: text_range.h:25
typedefG_BEGIN_DECLS struct _FlValue FlValue
Definition: fl_value.h:39
G_MODULE_EXPORT FlValue * fl_value_new_map()
Definition: fl_value.cc:327
static constexpr char kTextAffinityDownstream[]
G_MODULE_EXPORT FlValue * fl_value_new_bool(bool value)
Definition: fl_value.cc:226
static constexpr char kComposingBaseKey[]
G_MODULE_EXPORT void fl_value_append(FlValue *self, FlValue *value)
Definition: fl_value.cc:506
static constexpr char kSelectionIsDirectionalKey[]
static constexpr char kComposingExtentKey[]
G_MODULE_EXPORT void fl_value_append_take(FlValue *self, FlValue *value)
Definition: fl_value.cc:514
uint8_t value
static constexpr char kSelectionAffinityKey[]
static constexpr char kTextKey[]
static constexpr char kSelectionExtentKey[]
static void update_editing_state_response_cb(GObject *object, GAsyncResult *result, gpointer user_data)
static constexpr char kSelectionBaseKey[]
G_MODULE_EXPORT FlValue * fl_value_new_int(int64_t value)
Definition: fl_value.cc:233
G_MODULE_EXPORT FlValue * fl_value_new_string(const gchar *value)
Definition: fl_value.cc:247
size_t extent() const
Definition: text_range.h:31
G_MODULE_EXPORT void fl_method_channel_invoke_method(FlMethodChannel *self, const gchar *method, FlValue *args, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
G_MODULE_EXPORT void fl_value_set_string_take(FlValue *self, const gchar *key, FlValue *value)
Definition: fl_value.cc:564
static constexpr char kUpdateEditingStateMethod[]

◆ update_editing_state_response_cb()

static void update_editing_state_response_cb ( GObject *  object,
GAsyncResult *  result,
gpointer  user_data 
)
static

Definition at line 95 of file fl_text_input_plugin.cc.

References error, finish_method(), and kUpdateEditingStateMethod.

Referenced by update_editing_state().

97  {
98  g_autoptr(GError) error = nullptr;
99  if (!finish_method(object, result, &error)) {
100  g_warning("Failed to call %s: %s", kUpdateEditingStateMethod,
101  error->message);
102  }
103 }
FlMethodResponse GError ** error
static gboolean finish_method(GObject *object, GAsyncResult *result, GError **error)
static constexpr char kUpdateEditingStateMethod[]

◆ update_im_cursor_position()

static void update_im_cursor_position ( FlTextInputPlugin *  self)
static

Definition at line 323 of file fl_text_input_plugin.cc.

Referenced by set_editable_size_and_transform(), and set_marked_text_rect().

323  {
324  // Skip update if not composing to avoid setting to position 0.
325  if (!self->text_model->composing()) {
326  return;
327  }
328 
329  // Transform the x, y positions of the cursor from local coordinates to
330  // Flutter view coordinates.
331  gint x = self->composing_rect.x * self->editabletext_transform[0][0] +
332  self->composing_rect.y * self->editabletext_transform[1][0] +
333  self->editabletext_transform[3][0] + self->composing_rect.width;
334  gint y = self->composing_rect.x * self->editabletext_transform[0][1] +
335  self->composing_rect.y * self->editabletext_transform[1][1] +
336  self->editabletext_transform[3][1] + self->composing_rect.height;
337 
338  // Transform from Flutter view coordinates to GTK window coordinates.
339  GdkRectangle preedit_rect;
340  gtk_widget_translate_coordinates(
341  GTK_WIDGET(self->view), gtk_widget_get_toplevel(GTK_WIDGET(self->view)),
342  x, y, &preedit_rect.x, &preedit_rect.y);
343 
344  // Set the cursor location in window coordinates so that GTK can position any
345  // system input method windows.
346  gtk_im_context_set_cursor_location(self->im_context, &preedit_rect);
347 }

◆ view_weak_notify_cb()

static void view_weak_notify_cb ( gpointer  user_data,
GObject *  object 
)
static

Definition at line 426 of file fl_text_input_plugin.cc.

Referenced by fl_text_input_plugin_new().

426  {
427  FlTextInputPlugin* self = FL_TEXT_INPUT_PLUGIN(object);
428  self->view = nullptr;
429 }

Variable Documentation

◆ kBadArgumentsError

constexpr char kBadArgumentsError[] = "Bad Arguments"
static

Definition at line 15 of file fl_text_input_plugin.cc.

Referenced by set_client().

◆ kChannelName

constexpr char kChannelName[] = "flutter/textinput"
static

Definition at line 13 of file fl_text_input_plugin.cc.

Referenced by fl_text_input_plugin_new().

◆ kClearClientMethod

constexpr char kClearClientMethod[] = "TextInput.clearClient"
static

Definition at line 20 of file fl_text_input_plugin.cc.

Referenced by method_call_cb().

◆ kClientIdUnset

constexpr int64_t kClientIdUnset = -1
static

◆ kComposingBaseKey

constexpr char kComposingBaseKey[] = "composingBase"
static

Definition at line 37 of file fl_text_input_plugin.cc.

Referenced by set_editing_state(), and update_editing_state().

◆ kComposingExtentKey

constexpr char kComposingExtentKey[] = "composingExtent"
static

Definition at line 38 of file fl_text_input_plugin.cc.

Referenced by set_editing_state(), and update_editing_state().

◆ kHideMethod

constexpr char kHideMethod[] = "TextInput.hide"
static

Definition at line 21 of file fl_text_input_plugin.cc.

Referenced by method_call_cb().

◆ kInputActionKey

constexpr char kInputActionKey[] = "inputAction"
static

Definition at line 29 of file fl_text_input_plugin.cc.

Referenced by set_client().

◆ kMultilineInputType

constexpr char kMultilineInputType[] = "TextInputType.multiline"
static

Definition at line 43 of file fl_text_input_plugin.cc.

Referenced by set_client().

◆ kPerformActionMethod

constexpr char kPerformActionMethod[] = "TextInputClient.performAction"
static

Definition at line 24 of file fl_text_input_plugin.cc.

Referenced by perform_action(), and perform_action_response_cb().

◆ kSelectionAffinityKey

constexpr char kSelectionAffinityKey[] = "selectionAffinity"
static

Definition at line 35 of file fl_text_input_plugin.cc.

Referenced by update_editing_state().

◆ kSelectionBaseKey

constexpr char kSelectionBaseKey[] = "selectionBase"
static

Definition at line 33 of file fl_text_input_plugin.cc.

Referenced by set_editing_state(), and update_editing_state().

◆ kSelectionExtentKey

constexpr char kSelectionExtentKey[] = "selectionExtent"
static

Definition at line 34 of file fl_text_input_plugin.cc.

Referenced by set_editing_state(), and update_editing_state().

◆ kSelectionIsDirectionalKey

constexpr char kSelectionIsDirectionalKey[] = "selectionIsDirectional"
static

Definition at line 36 of file fl_text_input_plugin.cc.

Referenced by update_editing_state().

◆ kSetClientMethod

constexpr char kSetClientMethod[] = "TextInput.setClient"
static

Definition at line 17 of file fl_text_input_plugin.cc.

Referenced by method_call_cb().

◆ kSetEditableSizeAndTransform

constexpr char kSetEditableSizeAndTransform[]
static
Initial value:
=
"TextInput.setEditableSizeAndTransform"

Definition at line 25 of file fl_text_input_plugin.cc.

Referenced by method_call_cb().

◆ kSetEditingStateMethod

constexpr char kSetEditingStateMethod[] = "TextInput.setEditingState"
static

Definition at line 19 of file fl_text_input_plugin.cc.

Referenced by method_call_cb().

◆ kSetMarkedTextRect

constexpr char kSetMarkedTextRect[] = "TextInput.setMarkedTextRect"
static

Definition at line 27 of file fl_text_input_plugin.cc.

Referenced by method_call_cb().

◆ kShowMethod

constexpr char kShowMethod[] = "TextInput.show"
static

Definition at line 18 of file fl_text_input_plugin.cc.

Referenced by method_call_cb().

◆ kTextAffinityDownstream

constexpr char kTextAffinityDownstream[] = "TextAffinity.downstream"
static

Definition at line 42 of file fl_text_input_plugin.cc.

Referenced by update_editing_state().

◆ kTextInputTypeKey

constexpr char kTextInputTypeKey[] = "inputType"
static

Definition at line 30 of file fl_text_input_plugin.cc.

Referenced by set_client().

◆ kTextInputTypeNameKey

constexpr char kTextInputTypeNameKey[] = "name"
static

Definition at line 31 of file fl_text_input_plugin.cc.

Referenced by set_client().

◆ kTextKey

constexpr char kTextKey[] = "text"
static

Definition at line 32 of file fl_text_input_plugin.cc.

Referenced by set_editing_state(), and update_editing_state().

◆ kTransform

constexpr char kTransform[] = "transform"
static

Definition at line 40 of file fl_text_input_plugin.cc.

Referenced by set_editable_size_and_transform().

◆ kUpdateEditingStateMethod

constexpr char kUpdateEditingStateMethod[]
static
Initial value:
=
"TextInputClient.updateEditingState"

Definition at line 22 of file fl_text_input_plugin.cc.

Referenced by update_editing_state(), and update_editing_state_response_cb().