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