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