| Flutter Linux Embedder |

fl_text_input_handler.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "flutter/shell/platform/linux/fl_text_input_handler.h"
6
7 #include <gtk/gtk.h>
8
9 #include "flutter/shell/platform/common/text_editing_delta.h"
10 #include "flutter/shell/platform/common/text_input_model.h"
11 #include "flutter/shell/platform/linux/fl_text_input_channel.h"
12
13 static constexpr char kNewlineInputAction[] = "TextInputAction.newline";
14
15 static constexpr int64_t kClientIdUnset = -1;
16
17 struct _FlTextInputHandler {
18 GObject parent_instance;
19
20 FlTextInputChannel* channel;
21
22 // Client ID provided by Flutter to report events with.
23 int64_t client_id;
24
25 // Input action to perform when enter pressed.
26 gchar* input_action;
27
28 // The type of the input method.
29 FlTextInputType input_type;
30
31 // Whether to enable that the engine sends text input updates to the framework
32 // as TextEditingDeltas or as one TextEditingValue.
33 // For more information on the delta model, see:
34 // https://master-api.flutter.dev/flutter/services/TextInputConfiguration/enableDeltaModel.html
35 gboolean enable_delta_model;
36
37 // Input method.
38 GtkIMContext* im_context;
39
40 GWeakRef view_delegate;
41
42 flutter::TextInputModel* text_model;
43
44 // A 4x4 matrix that maps from `EditableText` local coordinates to the
45 // coordinate system of `PipelineOwner.rootNode`.
46 double editabletext_transform[4][4];
47
48 // The smallest rect, in local coordinates, of the text in the composing
49 // range, or of the caret in the case where there is no current composing
50 // range. This value is updated via `TextInput.setMarkedTextRect` messages
51 // over the text input channel.
52 GdkRectangle composing_rect;
53
54 GCancellable* cancellable;
55 };
56
57 G_DEFINE_TYPE(FlTextInputHandler, fl_text_input_handler, G_TYPE_OBJECT)
58
59 // Called when a response is received from TextInputClient.updateEditingState()
60 static void update_editing_state_response_cb(GObject* object,
61 GAsyncResult* result,
62 gpointer user_data) {
63 g_autoptr(GError) error = nullptr;
64 if (!fl_text_input_channel_update_editing_state_finish(object, result,
65 &error)) {
66 if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
67 g_warning("Failed to update editing state: %s", error->message);
68 }
69 }
70 }
71
72 // Called when a response is received from
73 // TextInputClient.updateEditingStateWithDeltas()
74 static void update_editing_state_with_deltas_response_cb(GObject* object,
75 GAsyncResult* result,
76 gpointer user_data) {
77 g_autoptr(GError) error = nullptr;
78 if (!fl_text_input_channel_update_editing_state_with_deltas_finish(
79 object, result, &error)) {
80 if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
81 g_warning("Failed to update editing state with deltas: %s",
82 error->message);
83 }
84 }
85 }
86
87 // Informs Flutter of text input changes.
88 static void update_editing_state(FlTextInputHandler* self) {
89 int composing_base = -1;
90 int composing_extent = -1;
91 if (!self->text_model->composing_range().collapsed()) {
92 composing_base = self->text_model->composing_range().base();
93 composing_extent = self->text_model->composing_range().extent();
94 }
95 flutter::TextRange selection = self->text_model->selection();
96 fl_text_input_channel_update_editing_state(
97 self->channel, self->client_id, self->text_model->GetText().c_str(),
98 selection.base(), selection.extent(), FL_TEXT_AFFINITY_DOWNSTREAM, FALSE,
99 composing_base, composing_extent, self->cancellable,
100 update_editing_state_response_cb, self);
101 }
102
103 // Informs Flutter of text input changes by passing just the delta.
104 static void update_editing_state_with_delta(FlTextInputHandler* self,
105 flutter::TextEditingDelta* delta) {
106 flutter::TextRange selection = self->text_model->selection();
107 int composing_base = -1;
108 int composing_extent = -1;
109 if (!self->text_model->composing_range().collapsed()) {
110 composing_base = self->text_model->composing_range().base();
111 composing_extent = self->text_model->composing_range().extent();
112 }
113 fl_text_input_channel_update_editing_state_with_deltas(
114 self->channel, self->client_id, delta->old_text().c_str(),
115 delta->delta_text().c_str(), delta->delta_start(), delta->delta_end(),
116 selection.base(), selection.extent(), FL_TEXT_AFFINITY_DOWNSTREAM, FALSE,
117 composing_base, composing_extent, self->cancellable,
118 update_editing_state_with_deltas_response_cb, self);
119 }
120
121 // Called when a response is received from TextInputClient.performAction()
122 static void perform_action_response_cb(GObject* object,
123 GAsyncResult* result,
124 gpointer user_data) {
125 g_autoptr(GError) error = nullptr;
126 if (!fl_text_input_channel_perform_action_finish(object, result, &error)) {
127 if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
128 g_warning("Failed to perform action: %s", error->message);
129 }
130 }
131 }
132
133 // Inform Flutter that the input has been activated.
134 static void perform_action(FlTextInputHandler* self) {
135 g_return_if_fail(FL_IS_TEXT_INPUT_HANDLER(self));
136 g_return_if_fail(self->client_id != 0);
137 g_return_if_fail(self->input_action != nullptr);
138
139 fl_text_input_channel_perform_action(self->channel, self->client_id,
140 self->input_action, self->cancellable,
141 perform_action_response_cb, self);
142 }
143
144 // Signal handler for GtkIMContext::preedit-start
145 static void im_preedit_start_cb(FlTextInputHandler* self) {
146 self->text_model->BeginComposing();
147 }
148
149 // Signal handler for GtkIMContext::preedit-changed
150 static void im_preedit_changed_cb(FlTextInputHandler* self) {
151 std::string text_before_change = self->text_model->GetText();
152 flutter::TextRange composing_before_change =
153 self->text_model->composing_range();
154 g_autofree gchar* buf = nullptr;
155 gint cursor_offset = 0;
156 gtk_im_context_get_preedit_string(self->im_context, &buf, nullptr,
157 &cursor_offset);
158 if (self->text_model->composing()) {
159 cursor_offset += self->text_model->composing_range().start();
160 } else {
161 cursor_offset += self->text_model->selection().start();
162 }
163 self->text_model->UpdateComposingText(buf);
164 self->text_model->SetSelection(flutter::TextRange(cursor_offset));
165
166 if (self->enable_delta_model) {
167 std::string text(buf);
168 flutter::TextEditingDelta delta = flutter::TextEditingDelta(
169 text_before_change, composing_before_change, text);
170 update_editing_state_with_delta(self, &delta);
171 } else {
172 update_editing_state(self);
173 }
174 }
175
176 // Signal handler for GtkIMContext::commit
177 static void im_commit_cb(FlTextInputHandler* self, const gchar* text) {
178 std::string text_before_change = self->text_model->GetText();
179 flutter::TextRange composing_before_change =
180 self->text_model->composing_range();
181 flutter::TextRange selection_before_change = self->text_model->selection();
182 gboolean was_composing = self->text_model->composing();
183
184 self->text_model->AddText(text);
185 if (self->text_model->composing()) {
186 self->text_model->CommitComposing();
187 }
188
189 if (self->enable_delta_model) {
190 flutter::TextRange replace_range =
191 was_composing ? composing_before_change : selection_before_change;
192 std::unique_ptr<flutter::TextEditingDelta> delta =
193 std::make_unique<flutter::TextEditingDelta>(text_before_change,
194 replace_range, text);
195 update_editing_state_with_delta(self, delta.get());
196 } else {
197 update_editing_state(self);
198 }
199 }
200
201 // Signal handler for GtkIMContext::preedit-end
202 static void im_preedit_end_cb(FlTextInputHandler* self) {
203 self->text_model->EndComposing();
204 if (self->enable_delta_model) {
205 flutter::TextEditingDelta delta =
206 flutter::TextEditingDelta(self->text_model->GetText());
207 update_editing_state_with_delta(self, &delta);
208 } else {
209 update_editing_state(self);
210 }
211 }
212
213 // Signal handler for GtkIMContext::retrieve-surrounding
214 static gboolean im_retrieve_surrounding_cb(FlTextInputHandler* self) {
215 auto text = self->text_model->GetText();
216 size_t cursor_offset = self->text_model->GetCursorOffset();
217 gtk_im_context_set_surrounding(self->im_context, text.c_str(), -1,
218 cursor_offset);
219 return TRUE;
220 }
221
222 // Signal handler for GtkIMContext::delete-surrounding
223 static gboolean im_delete_surrounding_cb(FlTextInputHandler* self,
224 gint offset,
225 gint n_chars) {
226 std::string text_before_change = self->text_model->GetText();
227 if (self->text_model->DeleteSurrounding(offset, n_chars)) {
228 if (self->enable_delta_model) {
229 flutter::TextEditingDelta delta = flutter::TextEditingDelta(
230 text_before_change, self->text_model->composing_range(),
231 self->text_model->GetText());
232 update_editing_state_with_delta(self, &delta);
233 } else {
234 update_editing_state(self);
235 }
236 }
237 return TRUE;
238 }
239
240 // Called when the input method client is set up.
241 static void set_client(int64_t client_id,
242 const gchar* input_action,
243 gboolean enable_delta_model,
244 FlTextInputType input_type,
245 gpointer user_data) {
246 FlTextInputHandler* self = FL_TEXT_INPUT_HANDLER(user_data);
247
248 self->client_id = client_id;
249 g_free(self->input_action);
250 self->input_action = g_strdup(input_action);
251 self->enable_delta_model = enable_delta_model;
252 self->input_type = input_type;
253 }
254
255 // Hides the input method.
256 static void hide(gpointer user_data) {
257 FlTextInputHandler* self = FL_TEXT_INPUT_HANDLER(user_data);
258
259 gtk_im_context_focus_out(self->im_context);
260 }
261
262 // Shows the input method.
263 static void show(gpointer user_data) {
264 FlTextInputHandler* self = FL_TEXT_INPUT_HANDLER(user_data);
265
266 if (self->input_type == FL_TEXT_INPUT_TYPE_NONE) {
267 hide(user_data);
268 return;
269 }
270
271 gtk_im_context_focus_in(self->im_context);
272 }
273
274 // Updates the editing state from Flutter.
275 static void set_editing_state(const gchar* text,
276 int64_t selection_base,
277 int64_t selection_extent,
278 int64_t composing_base,
279 int64_t composing_extent,
280 gpointer user_data) {
281 FlTextInputHandler* self = FL_TEXT_INPUT_HANDLER(user_data);
282
283 self->text_model->SetText(text);
284
285 // Flutter uses -1/-1 for invalid; translate that to 0/0 for the model.
286 if (selection_base == -1 && selection_extent == -1) {
287 selection_base = selection_extent = 0;
288 }
289
290 self->text_model->SetText(text);
291 self->text_model->SetSelection(
292 flutter::TextRange(selection_base, selection_extent));
293
294 if (composing_base == -1 && composing_extent == -1) {
295 self->text_model->EndComposing();
296 } else {
297 size_t composing_start = std::min(composing_base, composing_extent);
298 size_t cursor_offset = selection_base - composing_start;
299 self->text_model->SetComposingRange(
300 flutter::TextRange(composing_base, composing_extent), cursor_offset);
301 }
302 }
303
304 // Called when the input method client is complete.
305 static void clear_client(gpointer user_data) {
306 FlTextInputHandler* self = FL_TEXT_INPUT_HANDLER(user_data);
307 self->client_id = kClientIdUnset;
308 }
309
310 // Update the IM cursor position.
311 //
312 // As text is input by the user, the framework sends two streams of updates
313 // over the text input channel: updates to the composing rect (cursor rect
314 // when not in IME composing mode) and updates to the matrix transform from
315 // local coordinates to Flutter root coordinates. This function is called
316 // after each of these updates. It transforms the composing rect to GDK window
317 // coordinates and notifies GTK of the updated cursor position.
318 static void update_im_cursor_position(FlTextInputHandler* self) {
319 g_autoptr(FlTextInputViewDelegate) view_delegate =
320 FL_TEXT_INPUT_VIEW_DELEGATE(g_weak_ref_get(&self->view_delegate));
321 if (view_delegate == nullptr) {
322 return;
323 }
324
325 // Skip update if not composing to avoid setting to position 0.
326 if (!self->text_model->composing()) {
327 return;
328 }
329
330 // Transform the x, y positions of the cursor from local coordinates to
331 // Flutter view coordinates.
332 gint x = self->composing_rect.x * self->editabletext_transform[0][0] +
333 self->composing_rect.y * self->editabletext_transform[1][0] +
334 self->editabletext_transform[3][0] + self->composing_rect.width;
335 gint y = self->composing_rect.x * self->editabletext_transform[0][1] +
336 self->composing_rect.y * self->editabletext_transform[1][1] +
337 self->editabletext_transform[3][1] + self->composing_rect.height;
338
339 // Transform from Flutter view coordinates to GTK window coordinates.
340 GdkRectangle preedit_rect = {};
341 fl_text_input_view_delegate_translate_coordinates(
342 view_delegate, x, y, &preedit_rect.x, &preedit_rect.y);
343
344 // Set the cursor location in window coordinates so that GTK can position
345 // any system input method windows.
346 gtk_im_context_set_cursor_location(self->im_context, &preedit_rect);
347 }
348
349 // Handles updates to the EditableText size and position from the framework.
350 //
351 // On changes to the size or position of the RenderObject underlying the
352 // EditableText, this update may be triggered. It provides an updated size and
353 // transform from the local coordinate system of the EditableText to root
354 // Flutter coordinate system.
355 static void set_editable_size_and_transform(double* transform,
356 gpointer user_data) {
357 FlTextInputHandler* self = FL_TEXT_INPUT_HANDLER(user_data);
358
359 for (size_t i = 0; i < 16; i++) {
360 self->editabletext_transform[i / 4][i % 4] = transform[i];
361 }
362 update_im_cursor_position(self);
363 }
364
365 // Handles updates to the composing rect from the framework.
366 //
367 // On changes to the state of the EditableText in the framework, this update
368 // may be triggered. It provides an updated rect for the composing region in
369 // local coordinates of the EditableText. In the case where there is no
370 // composing region, the cursor rect is sent.
371 static void set_marked_text_rect(double x,
372 double y,
373 double width,
374 double height,
375 gpointer user_data) {
376 FlTextInputHandler* self = FL_TEXT_INPUT_HANDLER(user_data);
377
378 self->composing_rect.x = x;
379 self->composing_rect.y = y;
380 self->composing_rect.width = width;
381 self->composing_rect.height = height;
382 update_im_cursor_position(self);
383 }
384
385 // Disposes of an FlTextInputHandler.
386 static void fl_text_input_handler_dispose(GObject* object) {
387 FlTextInputHandler* self = FL_TEXT_INPUT_HANDLER(object);
388
389 g_cancellable_cancel(self->cancellable);
390
391 g_clear_object(&self->channel);
392 g_clear_pointer(&self->input_action, g_free);
393 g_clear_object(&self->im_context);
394 if (self->text_model != nullptr) {
395 delete self->text_model;
396 self->text_model = nullptr;
397 }
398 g_weak_ref_clear(&self->view_delegate);
399 g_clear_object(&self->cancellable);
400
401 G_OBJECT_CLASS(fl_text_input_handler_parent_class)->dispose(object);
402 }
403
404 // Initializes the FlTextInputHandler class.
405 static void fl_text_input_handler_class_init(FlTextInputHandlerClass* klass) {
406 G_OBJECT_CLASS(klass)->dispose = fl_text_input_handler_dispose;
407 }
408
409 // Initializes an instance of the FlTextInputHandler class.
410 static void fl_text_input_handler_init(FlTextInputHandler* self) {
411 self->client_id = kClientIdUnset;
412 self->input_type = FL_TEXT_INPUT_TYPE_TEXT;
413 self->text_model = new flutter::TextInputModel();
414 self->cancellable = g_cancellable_new();
415 }
416
417 static void init_im_context(FlTextInputHandler* self,
418 GtkIMContext* im_context) {
419 self->im_context = GTK_IM_CONTEXT(g_object_ref(im_context));
420
421 // On Wayland, this call sets up the input method so it can be enabled
422 // immediately when required. Without it, on-screen keyboard's don't come up
423 // the first time a text field is focused.
424 gtk_im_context_focus_out(self->im_context);
425
426 g_signal_connect_object(self->im_context, "preedit-start",
427 G_CALLBACK(im_preedit_start_cb), self,
428 G_CONNECT_SWAPPED);
429 g_signal_connect_object(self->im_context, "preedit-end",
430 G_CALLBACK(im_preedit_end_cb), self,
431 G_CONNECT_SWAPPED);
432 g_signal_connect_object(self->im_context, "preedit-changed",
433 G_CALLBACK(im_preedit_changed_cb), self,
434 G_CONNECT_SWAPPED);
435 g_signal_connect_object(self->im_context, "commit", G_CALLBACK(im_commit_cb),
436 self, G_CONNECT_SWAPPED);
437 g_signal_connect_object(self->im_context, "retrieve-surrounding",
438 G_CALLBACK(im_retrieve_surrounding_cb), self,
439 G_CONNECT_SWAPPED);
440 g_signal_connect_object(self->im_context, "delete-surrounding",
441 G_CALLBACK(im_delete_surrounding_cb), self,
442 G_CONNECT_SWAPPED);
443 }
444
445 static FlTextInputChannelVTable text_input_vtable = {
446 .set_client = set_client,
447 .hide = hide,
448 .show = show,
449 .set_editing_state = set_editing_state,
450 .clear_client = clear_client,
451 .set_editable_size_and_transform = set_editable_size_and_transform,
452 .set_marked_text_rect = set_marked_text_rect,
453 };
454
455 FlTextInputHandler* fl_text_input_handler_new(
456 FlBinaryMessenger* messenger,
457 GtkIMContext* im_context,
458 FlTextInputViewDelegate* view_delegate) {
459 g_return_val_if_fail(FL_IS_BINARY_MESSENGER(messenger), nullptr);
460 g_return_val_if_fail(GTK_IS_IM_CONTEXT(im_context), nullptr);
461 g_return_val_if_fail(FL_IS_TEXT_INPUT_VIEW_DELEGATE(view_delegate), nullptr);
462
463 FlTextInputHandler* self = FL_TEXT_INPUT_HANDLER(
464 g_object_new(fl_text_input_handler_get_type(), nullptr));
465
466 self->channel =
467 fl_text_input_channel_new(messenger, &text_input_vtable, self);
468
469 init_im_context(self, im_context);
470
471 g_weak_ref_init(&self->view_delegate, view_delegate);
472
473 return self;
474 }
475
476 gboolean fl_text_input_handler_filter_keypress(FlTextInputHandler* self,
477 FlKeyEvent* event) {
478 g_return_val_if_fail(FL_IS_TEXT_INPUT_HANDLER(self), FALSE);
479
480 if (self->client_id == kClientIdUnset) {
481 return FALSE;
482 }
483
484 if (gtk_im_context_filter_keypress(
485 self->im_context,
486 reinterpret_cast<GdkEventKey*>(fl_key_event_get_origin(event)))) {
487 return TRUE;
488 }
489
490 std::string text_before_change = self->text_model->GetText();
491 flutter::TextRange selection_before_change = self->text_model->selection();
492 std::string text = self->text_model->GetText();
493
494 // Handle the enter/return key.
495 gboolean do_action = FALSE;
496 // Handle navigation keys.
497 gboolean changed = FALSE;
498 if (fl_key_event_get_is_press(event)) {
499 switch (fl_key_event_get_keyval(event)) {
500 case GDK_KEY_End:
501 case GDK_KEY_KP_End:
502 if (fl_key_event_get_state(event) & GDK_SHIFT_MASK) {
503 changed = self->text_model->SelectToEnd();
504 } else {
505 changed = self->text_model->MoveCursorToEnd();
506 }
507 break;
508 case GDK_KEY_Return:
509 case GDK_KEY_KP_Enter:
510 case GDK_KEY_ISO_Enter:
511 if (self->input_type == FL_TEXT_INPUT_TYPE_MULTILINE &&
512 strcmp(self->input_action, kNewlineInputAction) == 0) {
513 self->text_model->AddCodePoint('\n');
514 text = "\n";
515 changed = TRUE;
516 }
517 do_action = TRUE;
518 break;
519 case GDK_KEY_Home:
520 case GDK_KEY_KP_Home:
521 if (fl_key_event_get_state(event) & GDK_SHIFT_MASK) {
522 changed = self->text_model->SelectToBeginning();
523 } else {
524 changed = self->text_model->MoveCursorToBeginning();
525 }
526 break;
527 case GDK_KEY_BackSpace:
528 case GDK_KEY_Delete:
529 case GDK_KEY_KP_Delete:
530 case GDK_KEY_Left:
531 case GDK_KEY_KP_Left:
532 case GDK_KEY_Right:
533 case GDK_KEY_KP_Right:
534 // Already handled inside the framework in RenderEditable.
535 break;
536 }
537 }
538
539 if (changed) {
540 if (self->enable_delta_model) {
541 flutter::TextEditingDelta delta = flutter::TextEditingDelta(
542 text_before_change, selection_before_change, text);
543 update_editing_state_with_delta(self, &delta);
544 } else {
545 update_editing_state(self);
546 }
547 }
548 if (do_action) {
549 perform_action(self);
550 }
551
552 return changed;
553 }
show
static void show(gpointer user_data)
Definition: fl_text_input_handler.cc:263
fl_text_input_handler_init
static void fl_text_input_handler_init(FlTextInputHandler *self)
Definition: fl_text_input_handler.cc:410
im_delete_surrounding_cb
static gboolean im_delete_surrounding_cb(FlTextInputHandler *self, gint offset, gint n_chars)
Definition: fl_text_input_handler.cc:223
fl_text_input_view_delegate_translate_coordinates
void fl_text_input_view_delegate_translate_coordinates(FlTextInputViewDelegate *self, gint view_x, gint view_y, gint *window_x, gint *window_y)
Definition: fl_text_input_view_delegate.cc:14
set_editable_size_and_transform
static void set_editable_size_and_transform(double *transform, gpointer user_data)
Definition: fl_text_input_handler.cc:355
_FlTextInputHandler::im_context
GtkIMContext * im_context
Definition: fl_text_input_handler.cc:38
FlTextInputType
FlTextInputType
Definition: fl_text_input_channel.h:14
set_editing_state
static void set_editing_state(const gchar *text, int64_t selection_base, int64_t selection_extent, int64_t composing_base, int64_t composing_extent, gpointer user_data)
Definition: fl_text_input_handler.cc:275
fl_text_input_channel_new
FlTextInputChannel * fl_text_input_channel_new(FlBinaryMessenger *messenger, FlTextInputChannelVTable *vtable, gpointer user_data)
Definition: fl_text_input_channel.cc:245
fl_text_input_channel.h
update_editing_state_with_deltas_response_cb
static void update_editing_state_with_deltas_response_cb(GObject *object, GAsyncResult *result, gpointer user_data)
Definition: fl_text_input_handler.cc:74
flutter::TextEditingDelta::delta_start
int delta_start() const
Get the delta_start_ value.
Definition: text_editing_delta.h:42
i
int i
Definition: fl_socket_accessible.cc:18
fl_text_input_handler.h
FL_TEXT_AFFINITY_DOWNSTREAM
@ FL_TEXT_AFFINITY_DOWNSTREAM
Definition: fl_text_input_channel.h:24
perform_action_response_cb
static void perform_action_response_cb(GObject *object, GAsyncResult *result, gpointer user_data)
Definition: fl_text_input_handler.cc:122
fl_text_input_channel_update_editing_state_with_deltas
void fl_text_input_channel_update_editing_state_with_deltas(FlTextInputChannel *self, int64_t client_id, const gchar *old_text, const gchar *delta_text, int64_t delta_start, int64_t delta_end, int64_t selection_base, int64_t selection_extent, FlTextAffinity selection_affinity, gboolean selection_is_directional, int64_t composing_base, int64_t composing_extent, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
Definition: fl_text_input_channel.cc:317
fl_text_input_handler_new
FlTextInputHandler * fl_text_input_handler_new(FlBinaryMessenger *messenger, GtkIMContext *im_context, FlTextInputViewDelegate *view_delegate)
Definition: fl_text_input_handler.cc:455
fl_text_input_handler_class_init
static void fl_text_input_handler_class_init(FlTextInputHandlerClass *klass)
Definition: fl_text_input_handler.cc:405
init_im_context
static void init_im_context(FlTextInputHandler *self, GtkIMContext *im_context)
Definition: fl_text_input_handler.cc:417
_FlTextInputHandler::channel
FlTextInputChannel * channel
Definition: fl_text_input_handler.cc:20
im_preedit_end_cb
static void im_preedit_end_cb(FlTextInputHandler *self)
Definition: fl_text_input_handler.cc:202
fl_key_event_get_origin
GdkEvent * fl_key_event_get_origin(FlKeyEvent *self)
Definition: fl_key_event.cc:109
FL_TEXT_INPUT_TYPE_TEXT
@ FL_TEXT_INPUT_TYPE_TEXT
Definition: fl_text_input_channel.h:15
text_input_model.h
_FlTextInputHandler
Definition: fl_text_input_handler.cc:17
user_data
G_BEGIN_DECLS G_MODULE_EXPORT FlValue gpointer user_data
Definition: fl_event_channel.h:90
im_preedit_changed_cb
static void im_preedit_changed_cb(FlTextInputHandler *self)
Definition: fl_text_input_handler.cc:150
flutter::TextRange
Definition: text_range.h:19
flutter::TextEditingDelta::delta_text
std::string delta_text() const
Definition: text_editing_delta.h:39
kClientIdUnset
static constexpr int64_t kClientIdUnset
Definition: fl_text_input_handler.cc:15
flutter::TextRange::base
size_t base() const
Definition: text_range.h:30
_FlTextInputHandler::enable_delta_model
gboolean enable_delta_model
Definition: fl_text_input_handler.cc:35
fl_key_event_get_keyval
guint fl_key_event_get_keyval(FlKeyEvent *self)
Definition: fl_key_event.cc:94
update_editing_state
static void update_editing_state(FlTextInputHandler *self)
Definition: fl_text_input_handler.cc:88
_FlTextInputHandler::input_action
gchar * input_action
Definition: fl_text_input_handler.cc:26
fl_text_input_handler_filter_keypress
gboolean fl_text_input_handler_filter_keypress(FlTextInputHandler *self, FlKeyEvent *event)
Definition: fl_text_input_handler.cc:476
fl_text_input_channel_update_editing_state
void fl_text_input_channel_update_editing_state(FlTextInputChannel *self, int64_t client_id, const gchar *text, int64_t selection_base, int64_t selection_extent, FlTextAffinity selection_affinity, gboolean selection_is_directional, int64_t composing_base, int64_t composing_extent, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
Definition: fl_text_input_channel.cc:266
flutter::TextEditingDelta::old_text
std::string old_text() const
Definition: text_editing_delta.h:34
im_preedit_start_cb
static void im_preedit_start_cb(FlTextInputHandler *self)
Definition: fl_text_input_handler.cc:145
G_DEFINE_TYPE
G_DEFINE_TYPE(FlBasicMessageChannelResponseHandle, fl_basic_message_channel_response_handle, G_TYPE_OBJECT) static void fl_basic_message_channel_response_handle_dispose(GObject *object)
Definition: fl_basic_message_channel.cc:37
FlTextInputChannelVTable::set_client
void(* set_client)(int64_t client_id, const gchar *input_action, gboolean enable_delta_model, FlTextInputType input_type, gpointer user_data)
Definition: fl_text_input_channel.h:41
FL_TEXT_INPUT_TYPE_MULTILINE
@ FL_TEXT_INPUT_TYPE_MULTILINE
Definition: fl_text_input_channel.h:17
TRUE
return TRUE
Definition: fl_pixel_buffer_texture_test.cc:53
fl_text_input_channel_perform_action_finish
gboolean fl_text_input_channel_perform_action_finish(GObject *object, GAsyncResult *result, GError **error)
Definition: fl_text_input_channel.cc:400
update_im_cursor_position
static void update_im_cursor_position(FlTextInputHandler *self)
Definition: fl_text_input_handler.cc:318
fl_text_input_handler_dispose
static void fl_text_input_handler_dispose(GObject *object)
Definition: fl_text_input_handler.cc:386
text_input_vtable
static FlTextInputChannelVTable text_input_vtable
Definition: fl_text_input_handler.cc:445
fl_text_input_channel_update_editing_state_finish
gboolean fl_text_input_channel_update_editing_state_finish(GObject *object, GAsyncResult *result, GError **error)
Definition: fl_text_input_channel.cc:306
kNewlineInputAction
static constexpr char kNewlineInputAction[]
Definition: fl_text_input_handler.cc:13
FlTextInputChannelVTable
Definition: fl_text_input_channel.h:40
height
const uint8_t uint32_t uint32_t * height
Definition: fl_pixel_buffer_texture_test.cc:39
set_client
static void set_client(int64_t client_id, const gchar *input_action, gboolean enable_delta_model, FlTextInputType input_type, gpointer user_data)
Definition: fl_text_input_handler.cc:241
hide
static void hide(gpointer user_data)
Definition: fl_text_input_handler.cc:256
fl_key_event_get_state
GdkModifierType fl_key_event_get_state(FlKeyEvent *self)
Definition: fl_key_event.cc:99
error
const uint8_t uint32_t uint32_t GError ** error
Definition: fl_pixel_buffer_texture_test.cc:40
set_marked_text_rect
static void set_marked_text_rect(double x, double y, double width, double height, gpointer user_data)
Definition: fl_text_input_handler.cc:371
flutter::TextRange::extent
size_t extent() const
Definition: text_range.h:36
FL_TEXT_INPUT_TYPE_NONE
@ FL_TEXT_INPUT_TYPE_NONE
Definition: fl_text_input_channel.h:19
_FlTextInputHandler::input_type
FlTextInputType input_type
Definition: fl_text_input_handler.cc:29
flutter::TextInputModel
Definition: text_input_model.h:18
_FlTextInputHandler::parent_instance
GObject parent_instance
Definition: fl_text_input_handler.cc:18
text_editing_delta.h
_FlTextInputHandler::cancellable
GCancellable * cancellable
Definition: fl_text_input_handler.cc:54
fl_key_event_get_is_press
gboolean fl_key_event_get_is_press(FlKeyEvent *self)
Definition: fl_key_event.cc:84
_FlTextInputHandler::client_id
int64_t client_id
Definition: fl_text_input_handler.cc:23
_FlTextInputHandler::text_model
flutter::TextInputModel * text_model
Definition: fl_text_input_handler.cc:42
clear_client
static void clear_client(gpointer user_data)
Definition: fl_text_input_handler.cc:305
flutter::TextEditingDelta
A change in the state of an input field.
Definition: text_editing_delta.h:16
perform_action
static void perform_action(FlTextInputHandler *self)
Definition: fl_text_input_handler.cc:134
_FlTextInputHandler::view_delegate
GWeakRef view_delegate
Definition: fl_text_input_handler.cc:40
width
const uint8_t uint32_t * width
Definition: fl_pixel_buffer_texture_test.cc:38
update_editing_state_response_cb
static void update_editing_state_response_cb(GObject *object, GAsyncResult *result, gpointer user_data)
Definition: fl_text_input_handler.cc:60
im_retrieve_surrounding_cb
static gboolean im_retrieve_surrounding_cb(FlTextInputHandler *self)
Definition: fl_text_input_handler.cc:214
im_commit_cb
static void im_commit_cb(FlTextInputHandler *self, const gchar *text)
Definition: fl_text_input_handler.cc:177
fl_text_input_channel_update_editing_state_with_deltas_finish
gboolean fl_text_input_channel_update_editing_state_with_deltas_finish(GObject *object, GAsyncResult *result, GError **error)
Definition: fl_text_input_channel.cc:372
_FlTextInputHandler::composing_rect
GdkRectangle composing_rect
Definition: fl_text_input_handler.cc:52
_FlTextInputHandler::editabletext_transform
double editabletext_transform[4][4]
Definition: fl_text_input_handler.cc:46
flutter::TextEditingDelta::delta_end
int delta_end() const
Get the delta_end_ value.
Definition: text_editing_delta.h:45
fl_text_input_channel_perform_action
void fl_text_input_channel_perform_action(FlTextInputChannel *self, int64_t client_id, const gchar *input_action, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
Definition: fl_text_input_channel.cc:384
update_editing_state_with_delta
static void update_editing_state_with_delta(FlTextInputHandler *self, flutter::TextEditingDelta *delta)
Definition: fl_text_input_handler.cc:104