Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
fl_accessible_text_field.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
8
9G_DEFINE_AUTOPTR_CLEANUP_FUNC(PangoContext, g_object_unref)
10// PangoLayout g_autoptr macro weren't added until 1.49.4. Add them manually.
11// https://gitlab.gnome.org/GNOME/pango/-/commit/0b84e14
12#if !PANGO_VERSION_CHECK(1, 49, 4)
13G_DEFINE_AUTOPTR_CLEANUP_FUNC(PangoLayout, g_object_unref)
14#endif
15
16typedef bool (*FlTextBoundaryCallback)(const PangoLogAttr* attr);
17
26
27static void fl_accessible_text_iface_init(AtkTextIface* iface);
28static void fl_accessible_editable_text_iface_init(AtkEditableTextIface* iface);
29
31 FlAccessibleTextField,
32 fl_accessible_text_field,
33 fl_accessible_node_get_type(),
34 G_IMPLEMENT_INTERFACE(ATK_TYPE_TEXT, fl_accessible_text_iface_init)
35 G_IMPLEMENT_INTERFACE(ATK_TYPE_EDITABLE_TEXT,
37
38static gchar* get_substring(FlAccessibleTextField* self,
39 glong start,
40 glong end) {
41 const gchar* value = gtk_entry_buffer_get_text(self->buffer);
42 glong length = g_utf8_strlen(value, -1);
43 if (end == -1) {
44 // g_utf8_substring() accepts -1 since 2.72
45 end = length;
46 }
47 start = CLAMP(start, 0, length);
48 end = CLAMP(end, start, length);
49 return g_utf8_substring(value, start, end);
50}
51
52static PangoContext* get_pango_context(FlAccessibleTextField* self) {
53 PangoFontMap* font_map = pango_cairo_font_map_get_default();
54 PangoContext* context = pango_font_map_create_context(font_map);
55 pango_context_set_base_dir(context,
56 self->text_direction == kFlutterTextDirectionRTL
57 ? PANGO_DIRECTION_RTL
58 : PANGO_DIRECTION_LTR);
59 return context;
60}
61
62static PangoLayout* create_pango_layout(FlAccessibleTextField* self) {
63 g_autoptr(PangoContext) context = get_pango_context(self);
64 PangoLayout* layout = pango_layout_new(context);
65 pango_layout_set_text(layout, gtk_entry_buffer_get_text(self->buffer), -1);
66 return layout;
67}
68
69static gchar* get_string_at_offset(FlAccessibleTextField* self,
70 gint start,
71 gint end,
74 gint* start_offset,
75 gint* end_offset) {
76 g_autoptr(PangoLayout) layout = create_pango_layout(self);
77
78 gint n_attrs = 0;
79 const PangoLogAttr* attrs =
80 pango_layout_get_log_attrs_readonly(layout, &n_attrs);
81
82 start = CLAMP(start, 0, MAX(n_attrs - 1, 0));
83 end = CLAMP(end, 0, MAX(n_attrs - 1, 0));
84
85 while (start > 0 && !is_start(&attrs[start])) {
86 --start;
87 }
88
89 while (end < n_attrs && !is_end(&attrs[end])) {
90 ++end;
91 }
92
93 if (start_offset != nullptr) {
94 *start_offset = start;
95 }
96 if (end_offset != nullptr) {
97 *end_offset = end;
98 }
99
100 return get_substring(self, start, end);
101}
102
103static gchar* get_char_at_offset(FlAccessibleTextField* self,
104 gint offset,
105 gint* start_offset,
106 gint* end_offset) {
108 self, offset, offset + 1,
109 [](const PangoLogAttr* attr) -> bool { return attr->is_char_break; },
110 [](const PangoLogAttr* attr) -> bool { return attr->is_char_break; },
111 start_offset, end_offset);
112}
113
114static gchar* get_word_at_offset(FlAccessibleTextField* self,
115 gint offset,
116 gint* start_offset,
117 gint* end_offset) {
119 self, offset, offset,
120 [](const PangoLogAttr* attr) -> bool { return attr->is_word_start; },
121 [](const PangoLogAttr* attr) -> bool { return attr->is_word_end; },
122 start_offset, end_offset);
123}
124
125static gchar* get_sentence_at_offset(FlAccessibleTextField* self,
126 gint offset,
127 gint* start_offset,
128 gint* end_offset) {
130 self, offset, offset,
131 [](const PangoLogAttr* attr) -> bool { return attr->is_sentence_start; },
132 [](const PangoLogAttr* attr) -> bool { return attr->is_sentence_end; },
133 start_offset, end_offset);
134}
135
136// Returns the line containing @offset, along with its start and end character
137// offsets. The line excludes the trailing line break. Returns nullptr if
138// @offset does not fall within any line.
139static gchar* get_line_at_offset(FlAccessibleTextField* self,
140 gint offset,
141 gint* start_offset,
142 gint* end_offset) {
143 g_autoptr(PangoLayout) layout = create_pango_layout(self);
144 const gchar* text = gtk_entry_buffer_get_text(self->buffer);
145
146 for (GSList* node = pango_layout_get_lines_readonly(layout); node != nullptr;
147 node = node->next) {
148 PangoLayoutLine* line = static_cast<PangoLayoutLine*>(node->data);
149 // PangoLayoutLine uses byte indices, but ATK offsets are character
150 // offsets, so convert before comparing.
151 gint line_start = g_utf8_pointer_to_offset(text, text + line->start_index);
152 gint line_end =
153 g_utf8_pointer_to_offset(text, text + line->start_index + line->length);
154 if (offset >= line_start && offset <= line_end) {
155 if (start_offset != nullptr) {
156 *start_offset = line_start;
157 }
158 if (end_offset != nullptr) {
159 *end_offset = line_end;
160 }
161 return get_substring(self, line_start, line_end);
162 }
163 }
164
165 return nullptr;
166}
167
168// Returns the paragraph containing @offset, along with its start and end
169// character offsets. A paragraph may span multiple wrapped lines and extends
170// from one paragraph start up to the following paragraph start. Returns nullptr
171// if @offset does not fall within any paragraph.
172static gchar* get_paragraph_at_offset(FlAccessibleTextField* self,
173 gint offset,
174 gint* start_offset,
175 gint* end_offset) {
176 g_autoptr(PangoLayout) layout = create_pango_layout(self);
177 const gchar* text = gtk_entry_buffer_get_text(self->buffer);
178
179 PangoLayoutLine* start = nullptr;
180 PangoLayoutLine* end = nullptr;
181 gint n_lines = pango_layout_get_line_count(layout);
182 for (gint i = 0; i < n_lines; ++i) {
183 PangoLayoutLine* line = pango_layout_get_line(layout, i);
184 if (line->is_paragraph_start) {
185 end = line;
186 }
187 if (start != nullptr && end != nullptr) {
188 // PangoLayoutLine uses byte indices, but ATK offsets are character
189 // offsets, so convert before comparing.
190 gint para_start =
191 g_utf8_pointer_to_offset(text, text + start->start_index);
192 gint para_end =
193 g_utf8_pointer_to_offset(text, text + end->start_index + end->length);
194 if (offset >= para_start && offset <= para_end) {
195 if (start_offset != nullptr) {
196 *start_offset = para_start;
197 }
198 if (end_offset != nullptr) {
199 *end_offset = para_end;
200 }
201 return get_substring(self, para_start, para_end);
202 }
203 }
204 if (line->is_paragraph_start) {
205 start = line;
206 }
207 }
208
209 return nullptr;
210}
211
212static void perform_set_text_action(FlAccessibleTextField* self,
213 const char* text) {
215 g_autoptr(FlStandardMessageCodec) codec = fl_standard_message_codec_new();
216 g_autoptr(GBytes) message =
217 fl_message_codec_encode_message(FL_MESSAGE_CODEC(codec), value, nullptr);
218
219 fl_accessible_node_perform_action(FL_ACCESSIBLE_NODE(self),
221}
222
223static void perform_set_selection_action(FlAccessibleTextField* self,
224 gint base,
225 gint extent) {
229
230 g_autoptr(FlStandardMessageCodec) codec = fl_standard_message_codec_new();
231 g_autoptr(GBytes) message =
232 fl_message_codec_encode_message(FL_MESSAGE_CODEC(codec), value, nullptr);
233
235 FL_ACCESSIBLE_NODE(self), kFlutterSemanticsActionSetSelection, message);
236}
237
238// Implements GObject::dispose.
239static void fl_accessible_text_field_dispose(GObject* object) {
240 FlAccessibleTextField* self = FL_ACCESSIBLE_TEXT_FIELD(object);
241
242 g_clear_object(&self->buffer);
243
244 G_OBJECT_CLASS(fl_accessible_text_field_parent_class)->dispose(object);
245}
246
247// Implements FlAccessibleNode::set_value.
248static void fl_accessible_text_field_set_value(FlAccessibleNode* node,
249 const gchar* value) {
250 g_return_if_fail(FL_IS_ACCESSIBLE_TEXT_FIELD(node));
251 FlAccessibleTextField* self = FL_ACCESSIBLE_TEXT_FIELD(node);
252
253 if (g_strcmp0(gtk_entry_buffer_get_text(self->buffer), value) == 0) {
254 return;
255 }
256
257 gtk_entry_buffer_set_text(self->buffer, value, -1);
258}
259
260// Implements FlAccessibleNode::set_text_selection.
261static void fl_accessible_text_field_set_text_selection(FlAccessibleNode* node,
262 gint base,
263 gint extent) {
264 g_return_if_fail(FL_IS_ACCESSIBLE_TEXT_FIELD(node));
265 FlAccessibleTextField* self = FL_ACCESSIBLE_TEXT_FIELD(node);
266
267 gboolean caret_moved = extent != self->selection_extent;
268 gboolean has_selection = base != extent;
269 gboolean had_selection = self->selection_base != self->selection_extent;
270 gboolean selection_changed = (has_selection || had_selection) &&
271 (caret_moved || base != self->selection_base);
272
273 self->selection_base = base;
274 self->selection_extent = extent;
275
276 if (selection_changed) {
277 g_signal_emit_by_name(self, "text-selection-changed", nullptr);
278 }
279
280 if (caret_moved) {
281 g_signal_emit_by_name(self, "text-caret-moved", extent, nullptr);
282 }
283}
284
285// Implements FlAccessibleNode::set_text_direction.
287 FlAccessibleNode* node,
288 FlutterTextDirection direction) {
289 g_return_if_fail(FL_IS_ACCESSIBLE_TEXT_FIELD(node));
290 FlAccessibleTextField* self = FL_ACCESSIBLE_TEXT_FIELD(node);
291
292 self->text_direction = direction;
293}
294
295// Overrides FlAccessibleNode::perform_action.
298 GBytes* data) {
299 FlAccessibleNodeClass* parent_class =
300 FL_ACCESSIBLE_NODE_CLASS(fl_accessible_text_field_parent_class);
301
302 switch (action) {
307 // These actions require a boolean argument that indicates whether the
308 // selection should be extended or collapsed when moving the cursor.
309 g_autoptr(FlValue) extend_selection = fl_value_new_bool(false);
310 g_autoptr(FlStandardMessageCodec) codec = fl_standard_message_codec_new();
312 FL_MESSAGE_CODEC(codec), extend_selection, nullptr);
313 parent_class->perform_action(self, action, message);
314 break;
315 }
316 default:
317 parent_class->perform_action(self, action, data);
318 break;
319 }
320}
321
322// Implements AtkText::get_character_count.
324 g_return_val_if_fail(FL_IS_ACCESSIBLE_TEXT_FIELD(text), 0);
325 FlAccessibleTextField* self = FL_ACCESSIBLE_TEXT_FIELD(text);
326
327 return gtk_entry_buffer_get_length(self->buffer);
328}
329
330// Implements AtkText::get_text.
332 gint start_offset,
333 gint end_offset) {
334 g_return_val_if_fail(FL_IS_ACCESSIBLE_TEXT_FIELD(text), nullptr);
335 FlAccessibleTextField* self = FL_ACCESSIBLE_TEXT_FIELD(text);
336
337 return get_substring(self, start_offset, end_offset);
338}
339
340// Implements AtkText::get_string_at_offset.
342 AtkText* text,
343 gint offset,
344 AtkTextGranularity granularity,
345 gint* start_offset,
346 gint* end_offset) {
347 g_return_val_if_fail(FL_IS_ACCESSIBLE_TEXT_FIELD(text), nullptr);
348 FlAccessibleTextField* self = FL_ACCESSIBLE_TEXT_FIELD(text);
349
350 switch (granularity) {
351 case ATK_TEXT_GRANULARITY_CHAR:
352 return get_char_at_offset(self, offset, start_offset, end_offset);
353 case ATK_TEXT_GRANULARITY_WORD:
354 return get_word_at_offset(self, offset, start_offset, end_offset);
355 case ATK_TEXT_GRANULARITY_SENTENCE:
356 return get_sentence_at_offset(self, offset, start_offset, end_offset);
357 case ATK_TEXT_GRANULARITY_LINE:
358 return get_line_at_offset(self, offset, start_offset, end_offset);
359 case ATK_TEXT_GRANULARITY_PARAGRAPH:
360 return get_paragraph_at_offset(self, offset, start_offset, end_offset);
361 default:
362 return nullptr;
363 }
364}
365
366// Implements AtkText::get_text_at_offset (deprecated but still commonly used).
368 AtkText* text,
369 gint offset,
370 AtkTextBoundary boundary_type,
371 gint* start_offset,
372 gint* end_offset) {
373 switch (boundary_type) {
374 case ATK_TEXT_BOUNDARY_CHAR:
376 text, offset, ATK_TEXT_GRANULARITY_CHAR, start_offset, end_offset);
377 break;
378 case ATK_TEXT_BOUNDARY_WORD_START:
379 case ATK_TEXT_BOUNDARY_WORD_END:
381 text, offset, ATK_TEXT_GRANULARITY_WORD, start_offset, end_offset);
382 break;
383 case ATK_TEXT_BOUNDARY_SENTENCE_START:
384 case ATK_TEXT_BOUNDARY_SENTENCE_END:
386 text, offset, ATK_TEXT_GRANULARITY_SENTENCE, start_offset,
387 end_offset);
388 break;
389 case ATK_TEXT_BOUNDARY_LINE_START:
390 case ATK_TEXT_BOUNDARY_LINE_END:
392 text, offset, ATK_TEXT_GRANULARITY_LINE, start_offset, end_offset);
393 break;
394 default:
395 return nullptr;
396 }
397}
398
399// Implements AtkText::get_caret_offset.
401 g_return_val_if_fail(FL_IS_ACCESSIBLE_TEXT_FIELD(text), -1);
402 FlAccessibleTextField* self = FL_ACCESSIBLE_TEXT_FIELD(text);
403
404 return self->selection_extent;
405}
406
407// Implements AtkText::set_caret_offset.
409 gint offset) {
410 g_return_val_if_fail(FL_IS_ACCESSIBLE_TEXT_FIELD(text), false);
411 FlAccessibleTextField* self = FL_ACCESSIBLE_TEXT_FIELD(text);
412
413 perform_set_selection_action(self, offset, offset);
414 return TRUE;
415}
416
417// Implements AtkText::get_n_selections.
419 g_return_val_if_fail(FL_IS_ACCESSIBLE_TEXT_FIELD(text), 0);
420 FlAccessibleTextField* self = FL_ACCESSIBLE_TEXT_FIELD(text);
421
422 if (self->selection_base == self->selection_extent) {
423 return 0;
424 }
425
426 return 1;
427}
428
429// Implements AtkText::get_selection.
431 gint selection_num,
432 gint* start_offset,
433 gint* end_offset) {
434 g_return_val_if_fail(FL_IS_ACCESSIBLE_TEXT_FIELD(text), nullptr);
435 FlAccessibleTextField* self = FL_ACCESSIBLE_TEXT_FIELD(text);
436
437 if (selection_num != 0 || self->selection_base == self->selection_extent) {
438 return nullptr;
439 }
440
441 gint start = MIN(self->selection_base, self->selection_extent);
442 gint end = MAX(self->selection_base, self->selection_extent);
443
444 if (start_offset != nullptr) {
445 *start_offset = start;
446 }
447 if (end_offset != nullptr) {
448 *end_offset = end;
449 }
450
451 return get_substring(self, start, end);
452}
453
454// Implements AtkText::add_selection.
456 gint start_offset,
457 gint end_offset) {
458 g_return_val_if_fail(FL_IS_ACCESSIBLE_TEXT_FIELD(text), false);
459 FlAccessibleTextField* self = FL_ACCESSIBLE_TEXT_FIELD(text);
460
461 if (self->selection_base != self->selection_extent) {
462 return FALSE;
463 }
464
465 perform_set_selection_action(self, start_offset, end_offset);
466 return TRUE;
467}
468
469// Implements AtkText::remove_selection.
471 gint selection_num) {
472 g_return_val_if_fail(FL_IS_ACCESSIBLE_TEXT_FIELD(text), false);
473 FlAccessibleTextField* self = FL_ACCESSIBLE_TEXT_FIELD(text);
474
475 if (selection_num != 0 || self->selection_base == self->selection_extent) {
476 return FALSE;
477 }
478
479 perform_set_selection_action(self, self->selection_extent,
480 self->selection_extent);
481 return TRUE;
482}
483
484// Implements AtkText::set_selection.
486 gint selection_num,
487 gint start_offset,
488 gint end_offset) {
489 g_return_val_if_fail(FL_IS_ACCESSIBLE_TEXT_FIELD(text), false);
490 FlAccessibleTextField* self = FL_ACCESSIBLE_TEXT_FIELD(text);
491
492 if (selection_num != 0) {
493 return FALSE;
494 }
495
496 perform_set_selection_action(self, start_offset, end_offset);
497 return TRUE;
498}
499
500// Implements AtkEditableText::set_text_contents.
502 AtkEditableText* editable_text,
503 const gchar* string) {
504 g_return_if_fail(FL_IS_ACCESSIBLE_TEXT_FIELD(editable_text));
505 FlAccessibleTextField* self = FL_ACCESSIBLE_TEXT_FIELD(editable_text);
506
508}
509
510// Implements AtkEditableText::insert_text.
511static void fl_accessible_text_field_insert_text(AtkEditableText* editable_text,
512 const gchar* string,
513 gint length,
514 gint* position) {
515 g_return_if_fail(FL_IS_ACCESSIBLE_TEXT_FIELD(editable_text));
516 FlAccessibleTextField* self = FL_ACCESSIBLE_TEXT_FIELD(editable_text);
517
518 *position +=
519 gtk_entry_buffer_insert_text(self->buffer, *position, string, length);
520
521 perform_set_text_action(self, gtk_entry_buffer_get_text(self->buffer));
522 perform_set_selection_action(self, *position, *position);
523}
524
525// Implements AtkEditableText::delete_text.
526static void fl_accessible_node_delete_text(AtkEditableText* editable_text,
527 gint start_pos,
528 gint end_pos) {
529 g_return_if_fail(FL_IS_ACCESSIBLE_TEXT_FIELD(editable_text));
530 FlAccessibleTextField* self = FL_ACCESSIBLE_TEXT_FIELD(editable_text);
531
532 gtk_entry_buffer_delete_text(self->buffer, start_pos, end_pos - start_pos);
533
534 perform_set_text_action(self, gtk_entry_buffer_get_text(self->buffer));
535 perform_set_selection_action(self, start_pos, start_pos);
536}
537
538// Implement AtkEditableText::copy_text.
539static void fl_accessible_text_field_copy_text(AtkEditableText* editable_text,
540 gint start_pos,
541 gint end_pos) {
542 g_return_if_fail(FL_IS_ACCESSIBLE_TEXT_FIELD(editable_text));
543 FlAccessibleTextField* self = FL_ACCESSIBLE_TEXT_FIELD(editable_text);
544
545 perform_set_selection_action(self, start_pos, end_pos);
546
547 fl_accessible_node_perform_action(FL_ACCESSIBLE_NODE(editable_text),
549}
550
551// Implements AtkEditableText::cut_text.
552static void fl_accessible_text_field_cut_text(AtkEditableText* editable_text,
553 gint start_pos,
554 gint end_pos) {
555 g_return_if_fail(FL_IS_ACCESSIBLE_TEXT_FIELD(editable_text));
556 FlAccessibleTextField* self = FL_ACCESSIBLE_TEXT_FIELD(editable_text);
557
558 perform_set_selection_action(self, start_pos, end_pos);
559
560 fl_accessible_node_perform_action(FL_ACCESSIBLE_NODE(editable_text),
562}
563
564// Implements AtkEditableText::paste_text.
565static void fl_accessible_text_field_paste_text(AtkEditableText* editable_text,
566 gint position) {
567 g_return_if_fail(FL_IS_ACCESSIBLE_TEXT_FIELD(editable_text));
568 FlAccessibleTextField* self = FL_ACCESSIBLE_TEXT_FIELD(editable_text);
569
570 perform_set_selection_action(self, position, position);
571
572 fl_accessible_node_perform_action(FL_ACCESSIBLE_NODE(editable_text),
574}
575
577 FlAccessibleTextFieldClass* klass) {
578 G_OBJECT_CLASS(klass)->dispose = fl_accessible_text_field_dispose;
579 FL_ACCESSIBLE_NODE_CLASS(klass)->set_value =
581 FL_ACCESSIBLE_NODE_CLASS(klass)->set_text_selection =
583 FL_ACCESSIBLE_NODE_CLASS(klass)->set_text_direction =
585 FL_ACCESSIBLE_NODE_CLASS(klass)->perform_action =
587}
588
589static void fl_accessible_text_iface_init(AtkTextIface* iface) {
590 iface->get_character_count = fl_accessible_text_field_get_character_count;
591 iface->get_text = fl_accessible_text_field_get_text;
592 iface->get_text_at_offset = fl_accessible_text_field_get_text_at_offset;
593 iface->get_string_at_offset = fl_accessible_text_field_get_string_at_offset;
594
595 iface->get_caret_offset = fl_accessible_text_field_get_caret_offset;
596 iface->set_caret_offset = fl_accessible_text_field_set_caret_offset;
597
598 iface->get_n_selections = fl_accessible_text_field_get_n_selections;
599 iface->get_selection = fl_accessible_text_field_get_selection;
600 iface->add_selection = fl_accessible_text_field_add_selection;
601 iface->remove_selection = fl_accessible_text_field_remove_selection;
602 iface->set_selection = fl_accessible_text_field_set_selection;
603}
604
606 AtkEditableTextIface* iface) {
607 iface->set_text_contents = fl_accessible_text_field_set_text_contents;
608 iface->insert_text = fl_accessible_text_field_insert_text;
609 iface->delete_text = fl_accessible_node_delete_text;
610
611 iface->copy_text = fl_accessible_text_field_copy_text;
612 iface->cut_text = fl_accessible_text_field_cut_text;
613 iface->paste_text = fl_accessible_text_field_paste_text;
614}
615
616static void fl_accessible_text_field_init(FlAccessibleTextField* self) {
617 self->selection_base = -1;
618 self->selection_extent = -1;
619
620 self->buffer = gtk_entry_buffer_new("", 0);
621
622 g_signal_connect_object(
623 self->buffer, "inserted-text",
624 G_CALLBACK(+[](FlAccessibleTextField* self, guint position, gchar* chars,
625 guint n_chars) {
626 g_signal_emit_by_name(self, "text-insert", position, n_chars, chars,
627 nullptr);
628 }),
629 self, G_CONNECT_SWAPPED);
630
631 g_signal_connect_object(self->buffer, "deleted-text",
632 G_CALLBACK(+[](FlAccessibleTextField* self,
633 guint position, guint n_chars) {
634 g_autofree gchar* chars = atk_text_get_text(
635 ATK_TEXT(self), position, position + n_chars);
636 g_signal_emit_by_name(self, "text-remove", position,
637 n_chars, chars, nullptr);
638 }),
639 self, G_CONNECT_SWAPPED);
640}
641
642FlAccessibleNode* fl_accessible_text_field_new(FlEngine* engine,
644 int32_t id) {
645 return FL_ACCESSIBLE_NODE(g_object_new(fl_accessible_text_field_get_type(),
646 "engine", engine, "view-id", view_id,
647 "node-id", id, nullptr));
648}
int32_t value
FlutterSemanticsAction
Definition embedder.h:122
@ kFlutterSemanticsActionMoveCursorForwardByCharacter
Move the cursor forward by one character.
Definition embedder.h:149
@ kFlutterSemanticsActionMoveCursorBackwardByCharacter
Move the cursor backward by one character.
Definition embedder.h:151
@ kFlutterSemanticsActionMoveCursorForwardByWord
Move the cursor forward by one word.
Definition embedder.h:169
@ kFlutterSemanticsActionSetSelection
Set the text selection to the given range.
Definition embedder.h:153
@ kFlutterSemanticsActionPaste
Paste the current content of the clipboard.
Definition embedder.h:159
@ kFlutterSemanticsActionCut
Cut the current selection and place it in the clipboard.
Definition embedder.h:157
@ kFlutterSemanticsActionCopy
Copy the current selection to the clipboard.
Definition embedder.h:155
@ kFlutterSemanticsActionMoveCursorBackwardByWord
Move the cursor backward by one word.
Definition embedder.h:171
@ kFlutterSemanticsActionSetText
Replace the current text in the text field.
Definition embedder.h:173
int64_t FlutterViewId
Definition embedder.h:393
FlutterTextDirection
Definition embedder.h:366
@ kFlutterTextDirectionRTL
Text is read from right to left.
Definition embedder.h:370
FlutterEngine engine
Definition main.cc:84
const char * message
g_autoptr(FlEngine) engine
void fl_accessible_node_perform_action(FlAccessibleNode *self, FlutterSemanticsAction action, GBytes *data)
static void perform_set_selection_action(FlAccessibleTextField *self, gint base, gint extent)
static gint fl_accessible_text_field_get_n_selections(AtkText *text)
static gchar * fl_accessible_text_field_get_string_at_offset(AtkText *text, gint offset, AtkTextGranularity granularity, gint *start_offset, gint *end_offset)
static void fl_accessible_text_field_insert_text(AtkEditableText *editable_text, const gchar *string, gint length, gint *position)
static gchar * fl_accessible_text_field_get_text(AtkText *text, gint start_offset, gint end_offset)
static void fl_accessible_text_field_dispose(GObject *object)
static gchar * fl_accessible_text_field_get_selection(AtkText *text, gint selection_num, gint *start_offset, gint *end_offset)
static void fl_accessible_text_field_paste_text(AtkEditableText *editable_text, gint position)
static gchar * get_line_at_offset(FlAccessibleTextField *self, gint offset, gint *start_offset, gint *end_offset)
static gboolean fl_accessible_text_field_set_selection(AtkText *text, gint selection_num, gint start_offset, gint end_offset)
FlAccessibleNode * fl_accessible_text_field_new(FlEngine *engine, FlutterViewId view_id, int32_t id)
static void fl_accessible_text_field_set_text_contents(AtkEditableText *editable_text, const gchar *string)
static void fl_accessible_text_field_copy_text(AtkEditableText *editable_text, gint start_pos, gint end_pos)
static void fl_accessible_text_field_init(FlAccessibleTextField *self)
static gboolean fl_accessible_text_field_remove_selection(AtkText *text, gint selection_num)
static gchar * get_word_at_offset(FlAccessibleTextField *self, gint offset, gint *start_offset, gint *end_offset)
G_DEFINE_TYPE_WITH_CODE(FlAccessibleTextField, fl_accessible_text_field, fl_accessible_node_get_type(), G_IMPLEMENT_INTERFACE(ATK_TYPE_EDITABLE_TEXT, fl_accessible_editable_text_iface_init)) static gchar *get_substring(FlAccessibleTextField *self
static void fl_accessible_text_field_set_text_direction(FlAccessibleNode *node, FlutterTextDirection direction)
static void fl_accessible_text_field_set_text_selection(FlAccessibleNode *node, gint base, gint extent)
bool(* FlTextBoundaryCallback)(const PangoLogAttr *attr)
static void fl_accessible_text_iface_init(AtkTextIface *iface)
static gchar * fl_accessible_text_field_get_text_at_offset(AtkText *text, gint offset, AtkTextBoundary boundary_type, gint *start_offset, gint *end_offset)
static void fl_accessible_text_field_set_value(FlAccessibleNode *node, const gchar *value)
static void fl_accessible_editable_text_iface_init(AtkEditableTextIface *iface)
static gboolean fl_accessible_text_field_set_caret_offset(AtkText *text, gint offset)
static void fl_accessible_node_delete_text(AtkEditableText *editable_text, gint start_pos, gint end_pos)
static gchar * get_sentence_at_offset(FlAccessibleTextField *self, gint offset, gint *start_offset, gint *end_offset)
static void fl_accessible_text_field_cut_text(AtkEditableText *editable_text, gint start_pos, gint end_pos)
static gchar * get_char_at_offset(FlAccessibleTextField *self, gint offset, gint *start_offset, gint *end_offset)
static PangoContext * get_pango_context(FlAccessibleTextField *self)
static gboolean fl_accessible_text_field_add_selection(AtkText *text, gint start_offset, gint end_offset)
static void perform_set_text_action(FlAccessibleTextField *self, const char *text)
static gchar * get_paragraph_at_offset(FlAccessibleTextField *self, gint offset, gint *start_offset, gint *end_offset)
static gchar * get_string_at_offset(FlAccessibleTextField *self, gint start, gint end, FlTextBoundaryCallback is_start, FlTextBoundaryCallback is_end, gint *start_offset, gint *end_offset)
static void fl_accessible_text_field_class_init(FlAccessibleTextFieldClass *klass)
return g_utf8_substring(value, start, end)
static gint fl_accessible_text_field_get_character_count(AtkText *text)
static gint fl_accessible_text_field_get_caret_offset(AtkText *text)
glong glong end
static PangoLayout * create_pango_layout(FlAccessibleTextField *self)
void fl_accessible_text_field_perform_action(FlAccessibleNode *self, FlutterSemanticsAction action, GBytes *data)
return TRUE
G_MODULE_EXPORT GBytes * fl_message_codec_encode_message(FlMessageCodec *self, FlValue *message, GError **error)
G_MODULE_EXPORT FlStandardMessageCodec * fl_standard_message_codec_new()
G_MODULE_EXPORT FlValue * fl_value_new_map()
Definition fl_value.cc:366
G_MODULE_EXPORT void fl_value_set_string_take(FlValue *self, const gchar *key, FlValue *value)
Definition fl_value.cc:650
G_MODULE_EXPORT FlValue * fl_value_new_string(const gchar *value)
Definition fl_value.cc:276
G_MODULE_EXPORT FlValue * fl_value_new_bool(bool value)
Definition fl_value.cc:255
G_MODULE_EXPORT FlValue * fl_value_new_int(int64_t value)
Definition fl_value.cc:262
typedefG_BEGIN_DECLS struct _FlValue FlValue
Definition fl_value.h:42
G_BEGIN_DECLS FlutterViewId view_id
std::u16string text
std::shared_ptr< ContextGLES > context
FlutterTextDirection text_direction