Flutter Engine
The Flutter Engine
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
5#include "flutter/shell/platform/linux/fl_accessible_text_field.h"
6#include "flutter/shell/platform/linux/public/flutter_linux/fl_standard_message_codec.h"
7#include "flutter/shell/platform/linux/public/flutter_linux/fl_value.h"
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,
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 if (end == -1) {
43 // g_utf8_substring() accepts -1 since 2.72
44 end = g_utf8_strlen(value, -1);
45 }
46 return g_utf8_substring(value, start, end);
47}
48
49static PangoContext* get_pango_context(FlAccessibleTextField* self) {
50 PangoFontMap* font_map = pango_cairo_font_map_get_default();
51 PangoContext* context = pango_font_map_create_context(font_map);
52 pango_context_set_base_dir(context,
53 self->text_direction == kFlutterTextDirectionRTL
54 ? PANGO_DIRECTION_RTL
55 : PANGO_DIRECTION_LTR);
56 return context;
57}
58
59static PangoLayout* create_pango_layout(FlAccessibleTextField* self) {
60 g_autoptr(PangoContext) context = get_pango_context(self);
61 PangoLayout* layout = pango_layout_new(context);
62 pango_layout_set_text(layout, gtk_entry_buffer_get_text(self->buffer), -1);
63 return layout;
64}
65
66static gchar* get_string_at_offset(FlAccessibleTextField* self,
67 gint start,
68 gint end,
71 gint* start_offset,
72 gint* end_offset) {
73 g_autoptr(PangoLayout) layout = create_pango_layout(self);
74
75 gint n_attrs = 0;
76 const PangoLogAttr* attrs =
77 pango_layout_get_log_attrs_readonly(layout, &n_attrs);
78
79 while (start > 0 && !is_start(&attrs[start])) {
80 --start;
81 }
82 if (start_offset != nullptr) {
83 *start_offset = start;
84 }
85
86 while (end < n_attrs && !is_end(&attrs[end])) {
87 ++end;
88 }
89 if (end_offset != nullptr) {
90 *end_offset = end;
91 }
92
93 return get_substring(self, start, end);
94}
95
96static gchar* get_char_at_offset(FlAccessibleTextField* self,
97 gint offset,
98 gint* start_offset,
99 gint* end_offset) {
101 self, offset, offset + 1,
102 [](const PangoLogAttr* attr) -> bool { return attr->is_char_break; },
103 [](const PangoLogAttr* attr) -> bool { return attr->is_char_break; },
104 start_offset, end_offset);
105}
106
107static gchar* get_word_at_offset(FlAccessibleTextField* self,
108 gint offset,
109 gint* start_offset,
110 gint* end_offset) {
113 [](const PangoLogAttr* attr) -> bool { return attr->is_word_start; },
114 [](const PangoLogAttr* attr) -> bool { return attr->is_word_end; },
115 start_offset, end_offset);
116}
117
118static gchar* get_sentence_at_offset(FlAccessibleTextField* self,
119 gint offset,
120 gint* start_offset,
121 gint* end_offset) {
124 [](const PangoLogAttr* attr) -> bool { return attr->is_sentence_start; },
125 [](const PangoLogAttr* attr) -> bool { return attr->is_sentence_end; },
126 start_offset, end_offset);
127}
128
129static gchar* get_line_at_offset(FlAccessibleTextField* self,
130 gint offset,
131 gint* start_offset,
132 gint* end_offset) {
133 g_autoptr(PangoLayout) layout = create_pango_layout(self);
134
135 GSList* lines = pango_layout_get_lines_readonly(layout);
136 while (lines != nullptr) {
137 PangoLayoutLine* line = static_cast<PangoLayoutLine*>(lines->data);
138 if (offset >= line->start_index &&
139 offset <= line->start_index + line->length) {
140 if (start_offset != nullptr) {
141 *start_offset = line->start_index;
142 }
143 if (end_offset != nullptr) {
144 *end_offset = line->start_index + line->length;
145 }
146 return get_substring(self, line->start_index,
147 line->start_index + line->length);
148 }
149 lines = lines->next;
150 }
151
152 return nullptr;
153}
154
155static gchar* get_paragraph_at_offset(FlAccessibleTextField* self,
156 gint offset,
157 gint* start_offset,
158 gint* end_offset) {
159 g_autoptr(PangoLayout) layout = create_pango_layout(self);
160
161 PangoLayoutLine* start = nullptr;
162 PangoLayoutLine* end = nullptr;
163 gint n_lines = pango_layout_get_line_count(layout);
164 for (gint i = 0; i < n_lines; ++i) {
165 PangoLayoutLine* line = pango_layout_get_line(layout, i);
166 if (line->is_paragraph_start) {
167 end = line;
168 }
169 if (start != nullptr && end != nullptr && offset >= start->start_index &&
170 offset <= end->start_index + end->length) {
171 if (start_offset != nullptr) {
172 *start_offset = start->start_index;
173 }
174 if (end_offset != nullptr) {
175 *end_offset = end->start_index + end->length;
176 }
177 return get_substring(self, start->start_index,
178 end->start_index + end->length);
179 }
180 if (line->is_paragraph_start) {
181 start = line;
182 }
183 }
184
185 return nullptr;
186}
187
188static void perform_set_text_action(FlAccessibleTextField* self,
189 const char* text) {
191 g_autoptr(FlStandardMessageCodec) codec = fl_standard_message_codec_new();
192 g_autoptr(GBytes) message =
193 fl_message_codec_encode_message(FL_MESSAGE_CODEC(codec), value, nullptr);
194
195 fl_accessible_node_perform_action(FL_ACCESSIBLE_NODE(self),
197}
198
199static void perform_set_selection_action(FlAccessibleTextField* self,
200 gint base,
201 gint extent) {
202 g_autoptr(FlValue) value = fl_value_new_map();
205
206 g_autoptr(FlStandardMessageCodec) codec = fl_standard_message_codec_new();
207 g_autoptr(GBytes) message =
208 fl_message_codec_encode_message(FL_MESSAGE_CODEC(codec), value, nullptr);
209
211 FL_ACCESSIBLE_NODE(self), kFlutterSemanticsActionSetSelection, message);
212}
213
214// Implements GObject::dispose.
215static void fl_accessible_text_field_dispose(GObject* object) {
216 FlAccessibleTextField* self = FL_ACCESSIBLE_TEXT_FIELD(object);
217
218 g_clear_object(&self->buffer);
219
220 G_OBJECT_CLASS(fl_accessible_text_field_parent_class)->dispose(object);
221}
222
223// Implements FlAccessibleNode::set_value.
224static void fl_accessible_text_field_set_value(FlAccessibleNode* node,
225 const gchar* value) {
226 g_return_if_fail(FL_IS_ACCESSIBLE_TEXT_FIELD(node));
227 FlAccessibleTextField* self = FL_ACCESSIBLE_TEXT_FIELD(node);
228
229 if (g_strcmp0(gtk_entry_buffer_get_text(self->buffer), value) == 0) {
230 return;
231 }
232
233 gtk_entry_buffer_set_text(self->buffer, value, -1);
234}
235
236// Implements FlAccessibleNode::set_text_selection.
237static void fl_accessible_text_field_set_text_selection(FlAccessibleNode* node,
238 gint base,
239 gint extent) {
240 g_return_if_fail(FL_IS_ACCESSIBLE_TEXT_FIELD(node));
241 FlAccessibleTextField* self = FL_ACCESSIBLE_TEXT_FIELD(node);
242
243 gboolean caret_moved = extent != self->selection_extent;
244 gboolean has_selection = base != extent;
245 gboolean had_selection = self->selection_base != self->selection_extent;
246 gboolean selection_changed = (has_selection || had_selection) &&
247 (caret_moved || base != self->selection_base);
248
249 self->selection_base = base;
250 self->selection_extent = extent;
251
252 if (selection_changed) {
253 g_signal_emit_by_name(self, "text-selection-changed", nullptr);
254 }
255
256 if (caret_moved) {
257 g_signal_emit_by_name(self, "text-caret-moved", extent, nullptr);
258 }
259}
260
261// Implements FlAccessibleNode::set_text_direction.
263 FlAccessibleNode* node,
264 FlutterTextDirection direction) {
265 g_return_if_fail(FL_IS_ACCESSIBLE_TEXT_FIELD(node));
266 FlAccessibleTextField* self = FL_ACCESSIBLE_TEXT_FIELD(node);
267
268 self->text_direction = direction;
269}
270
271// Overrides FlAccessibleNode::perform_action.
274 GBytes* data) {
275 FlAccessibleNodeClass* parent_class =
276 FL_ACCESSIBLE_NODE_CLASS(fl_accessible_text_field_parent_class);
277
278 switch (action) {
283 // These actions require a boolean argument that indicates whether the
284 // selection should be extended or collapsed when moving the cursor.
285 g_autoptr(FlValue) extend_selection = fl_value_new_bool(false);
286 g_autoptr(FlStandardMessageCodec) codec = fl_standard_message_codec_new();
287 g_autoptr(GBytes) message = fl_message_codec_encode_message(
288 FL_MESSAGE_CODEC(codec), extend_selection, nullptr);
289 parent_class->perform_action(self, action, message);
290 break;
291 }
292 default:
293 parent_class->perform_action(self, action, data);
294 break;
295 }
296}
297
298// Implements AtkText::get_character_count.
300 g_return_val_if_fail(FL_IS_ACCESSIBLE_TEXT_FIELD(text), 0);
301 FlAccessibleTextField* self = FL_ACCESSIBLE_TEXT_FIELD(text);
302
303 return gtk_entry_buffer_get_length(self->buffer);
304}
305
306// Implements AtkText::get_text.
308 gint start_offset,
309 gint end_offset) {
310 g_return_val_if_fail(FL_IS_ACCESSIBLE_TEXT_FIELD(text), nullptr);
311 FlAccessibleTextField* self = FL_ACCESSIBLE_TEXT_FIELD(text);
312
313 return get_substring(self, start_offset, end_offset);
314}
315
316// Implements AtkText::get_string_at_offset.
318 AtkText* text,
319 gint offset,
320 AtkTextGranularity granularity,
321 gint* start_offset,
322 gint* end_offset) {
323 g_return_val_if_fail(FL_IS_ACCESSIBLE_TEXT_FIELD(text), nullptr);
324 FlAccessibleTextField* self = FL_ACCESSIBLE_TEXT_FIELD(text);
325
326 switch (granularity) {
327 case ATK_TEXT_GRANULARITY_CHAR:
328 return get_char_at_offset(self, offset, start_offset, end_offset);
329 case ATK_TEXT_GRANULARITY_WORD:
330 return get_word_at_offset(self, offset, start_offset, end_offset);
331 case ATK_TEXT_GRANULARITY_SENTENCE:
332 return get_sentence_at_offset(self, offset, start_offset, end_offset);
333 case ATK_TEXT_GRANULARITY_LINE:
334 return get_line_at_offset(self, offset, start_offset, end_offset);
335 case ATK_TEXT_GRANULARITY_PARAGRAPH:
336 return get_paragraph_at_offset(self, offset, start_offset, end_offset);
337 default:
338 return nullptr;
339 }
340}
341
342// Implements AtkText::get_text_at_offset (deprecated but still commonly used).
344 AtkText* text,
345 gint offset,
346 AtkTextBoundary boundary_type,
347 gint* start_offset,
348 gint* end_offset) {
349 switch (boundary_type) {
350 case ATK_TEXT_BOUNDARY_CHAR:
352 text, offset, ATK_TEXT_GRANULARITY_CHAR, start_offset, end_offset);
353 break;
354 case ATK_TEXT_BOUNDARY_WORD_START:
355 case ATK_TEXT_BOUNDARY_WORD_END:
357 text, offset, ATK_TEXT_GRANULARITY_WORD, start_offset, end_offset);
358 break;
359 case ATK_TEXT_BOUNDARY_SENTENCE_START:
360 case ATK_TEXT_BOUNDARY_SENTENCE_END:
362 text, offset, ATK_TEXT_GRANULARITY_SENTENCE, start_offset,
363 end_offset);
364 break;
365 case ATK_TEXT_BOUNDARY_LINE_START:
366 case ATK_TEXT_BOUNDARY_LINE_END:
368 text, offset, ATK_TEXT_GRANULARITY_LINE, start_offset, end_offset);
369 break;
370 default:
371 return nullptr;
372 }
373}
374
375// Implements AtkText::get_caret_offset.
377 g_return_val_if_fail(FL_IS_ACCESSIBLE_TEXT_FIELD(text), -1);
378 FlAccessibleTextField* self = FL_ACCESSIBLE_TEXT_FIELD(text);
379
380 return self->selection_extent;
381}
382
383// Implements AtkText::set_caret_offset.
385 gint offset) {
386 g_return_val_if_fail(FL_IS_ACCESSIBLE_TEXT_FIELD(text), false);
387 FlAccessibleTextField* self = FL_ACCESSIBLE_TEXT_FIELD(text);
388
390 return true;
391}
392
393// Implements AtkText::get_n_selections.
395 g_return_val_if_fail(FL_IS_ACCESSIBLE_TEXT_FIELD(text), 0);
396 FlAccessibleTextField* self = FL_ACCESSIBLE_TEXT_FIELD(text);
397
398 if (self->selection_base == self->selection_extent) {
399 return 0;
400 }
401
402 return 1;
403}
404
405// Implements AtkText::get_selection.
407 gint selection_num,
408 gint* start_offset,
409 gint* end_offset) {
410 g_return_val_if_fail(FL_IS_ACCESSIBLE_TEXT_FIELD(text), nullptr);
411 FlAccessibleTextField* self = FL_ACCESSIBLE_TEXT_FIELD(text);
412
413 if (selection_num != 0 || self->selection_base == self->selection_extent) {
414 return nullptr;
415 }
416
417 gint start = MIN(self->selection_base, self->selection_extent);
418 gint end = MAX(self->selection_base, self->selection_extent);
419
420 if (start_offset != nullptr) {
421 *start_offset = start;
422 }
423 if (end_offset != nullptr) {
424 *end_offset = end;
425 }
426
427 return get_substring(self, start, end);
428}
429
430// Implements AtkText::add_selection.
432 gint start_offset,
433 gint end_offset) {
434 g_return_val_if_fail(FL_IS_ACCESSIBLE_TEXT_FIELD(text), false);
435 FlAccessibleTextField* self = FL_ACCESSIBLE_TEXT_FIELD(text);
436
437 if (self->selection_base != self->selection_extent) {
438 return false;
439 }
440
441 perform_set_selection_action(self, start_offset, end_offset);
442 return true;
443}
444
445// Implements AtkText::remove_selection.
447 gint selection_num) {
448 g_return_val_if_fail(FL_IS_ACCESSIBLE_TEXT_FIELD(text), false);
449 FlAccessibleTextField* self = FL_ACCESSIBLE_TEXT_FIELD(text);
450
451 if (selection_num != 0 || self->selection_base == self->selection_extent) {
452 return false;
453 }
454
455 perform_set_selection_action(self, self->selection_extent,
456 self->selection_extent);
457 return true;
458}
459
460// Implements AtkText::set_selection.
462 gint selection_num,
463 gint start_offset,
464 gint end_offset) {
465 g_return_val_if_fail(FL_IS_ACCESSIBLE_TEXT_FIELD(text), false);
466 FlAccessibleTextField* self = FL_ACCESSIBLE_TEXT_FIELD(text);
467
468 if (selection_num != 0) {
469 return false;
470 }
471
472 perform_set_selection_action(self, start_offset, end_offset);
473 return true;
474}
475
476// Implements AtkEditableText::set_text_contents.
478 AtkEditableText* editable_text,
479 const gchar* string) {
480 g_return_if_fail(FL_IS_ACCESSIBLE_TEXT_FIELD(editable_text));
481 FlAccessibleTextField* self = FL_ACCESSIBLE_TEXT_FIELD(editable_text);
482
484}
485
486// Implements AtkEditableText::insert_text.
487static void fl_accessible_text_field_insert_text(AtkEditableText* editable_text,
488 const gchar* string,
489 gint length,
490 gint* position) {
491 g_return_if_fail(FL_IS_ACCESSIBLE_TEXT_FIELD(editable_text));
492 FlAccessibleTextField* self = FL_ACCESSIBLE_TEXT_FIELD(editable_text);
493
494 *position +=
495 gtk_entry_buffer_insert_text(self->buffer, *position, string, length);
496
497 perform_set_text_action(self, gtk_entry_buffer_get_text(self->buffer));
498 perform_set_selection_action(self, *position, *position);
499}
500
501// Implements AtkEditableText::delete_text.
502static void fl_accessible_node_delete_text(AtkEditableText* editable_text,
503 gint start_pos,
504 gint end_pos) {
505 g_return_if_fail(FL_IS_ACCESSIBLE_TEXT_FIELD(editable_text));
506 FlAccessibleTextField* self = FL_ACCESSIBLE_TEXT_FIELD(editable_text);
507
508 gtk_entry_buffer_delete_text(self->buffer, start_pos, end_pos - start_pos);
509
510 perform_set_text_action(self, gtk_entry_buffer_get_text(self->buffer));
511 perform_set_selection_action(self, start_pos, start_pos);
512}
513
514// Implement AtkEditableText::copy_text.
515static void fl_accessible_text_field_copy_text(AtkEditableText* editable_text,
516 gint start_pos,
517 gint end_pos) {
518 g_return_if_fail(FL_IS_ACCESSIBLE_TEXT_FIELD(editable_text));
519 FlAccessibleTextField* self = FL_ACCESSIBLE_TEXT_FIELD(editable_text);
520
521 perform_set_selection_action(self, start_pos, end_pos);
522
523 fl_accessible_node_perform_action(FL_ACCESSIBLE_NODE(editable_text),
525}
526
527// Implements AtkEditableText::cut_text.
528static void fl_accessible_text_field_cut_text(AtkEditableText* editable_text,
529 gint start_pos,
530 gint end_pos) {
531 g_return_if_fail(FL_IS_ACCESSIBLE_TEXT_FIELD(editable_text));
532 FlAccessibleTextField* self = FL_ACCESSIBLE_TEXT_FIELD(editable_text);
533
534 perform_set_selection_action(self, start_pos, end_pos);
535
536 fl_accessible_node_perform_action(FL_ACCESSIBLE_NODE(editable_text),
538}
539
540// Implements AtkEditableText::paste_text.
541static void fl_accessible_text_field_paste_text(AtkEditableText* editable_text,
542 gint position) {
543 g_return_if_fail(FL_IS_ACCESSIBLE_TEXT_FIELD(editable_text));
544 FlAccessibleTextField* self = FL_ACCESSIBLE_TEXT_FIELD(editable_text);
545
546 perform_set_selection_action(self, position, position);
547
548 fl_accessible_node_perform_action(FL_ACCESSIBLE_NODE(editable_text),
550}
551
553 FlAccessibleTextFieldClass* klass) {
554 G_OBJECT_CLASS(klass)->dispose = fl_accessible_text_field_dispose;
555 FL_ACCESSIBLE_NODE_CLASS(klass)->set_value =
557 FL_ACCESSIBLE_NODE_CLASS(klass)->set_text_selection =
559 FL_ACCESSIBLE_NODE_CLASS(klass)->set_text_direction =
561 FL_ACCESSIBLE_NODE_CLASS(klass)->perform_action =
563}
564
565static void fl_accessible_text_iface_init(AtkTextIface* iface) {
566 iface->get_character_count = fl_accessible_text_field_get_character_count;
567 iface->get_text = fl_accessible_text_field_get_text;
568 iface->get_text_at_offset = fl_accessible_text_field_get_text_at_offset;
569 iface->get_string_at_offset = fl_accessible_text_field_get_string_at_offset;
570
571 iface->get_caret_offset = fl_accessible_text_field_get_caret_offset;
572 iface->set_caret_offset = fl_accessible_text_field_set_caret_offset;
573
574 iface->get_n_selections = fl_accessible_text_field_get_n_selections;
575 iface->get_selection = fl_accessible_text_field_get_selection;
576 iface->add_selection = fl_accessible_text_field_add_selection;
577 iface->remove_selection = fl_accessible_text_field_remove_selection;
578 iface->set_selection = fl_accessible_text_field_set_selection;
579}
580
582 AtkEditableTextIface* iface) {
583 iface->set_text_contents = fl_accessible_text_field_set_text_contents;
584 iface->insert_text = fl_accessible_text_field_insert_text;
585 iface->delete_text = fl_accessible_node_delete_text;
586
587 iface->copy_text = fl_accessible_text_field_copy_text;
588 iface->cut_text = fl_accessible_text_field_cut_text;
589 iface->paste_text = fl_accessible_text_field_paste_text;
590}
591
592static void fl_accessible_text_field_init(FlAccessibleTextField* self) {
593 self->selection_base = -1;
594 self->selection_extent = -1;
595
596 self->buffer = gtk_entry_buffer_new("", 0);
597
598 g_signal_connect_object(
599 self->buffer, "inserted-text",
600 G_CALLBACK(+[](FlAccessibleTextField* self, guint position, gchar* chars,
601 guint n_chars) {
602 g_signal_emit_by_name(self, "text-insert", position, n_chars, chars,
603 nullptr);
604 }),
605 self, G_CONNECT_SWAPPED);
606
607 g_signal_connect_object(self->buffer, "deleted-text",
608 G_CALLBACK(+[](FlAccessibleTextField* self,
609 guint position, guint n_chars) {
610 g_autofree gchar* chars = atk_text_get_text(
611 ATK_TEXT(self), position, position + n_chars);
612 g_signal_emit_by_name(self, "text-remove", position,
613 n_chars, chars, nullptr);
614 }),
615 self, G_CONNECT_SWAPPED);
616}
617
618FlAccessibleNode* fl_accessible_text_field_new(FlEngine* engine, int32_t id) {
619 return FL_ACCESSIBLE_NODE(g_object_new(fl_accessible_text_field_get_type(),
620 "engine", engine, "id", id, nullptr));
621}
FlutterSemanticsAction
Definition embedder.h:113
@ kFlutterSemanticsActionMoveCursorForwardByCharacter
Move the cursor forward by one character.
Definition embedder.h:140
@ kFlutterSemanticsActionMoveCursorBackwardByCharacter
Move the cursor backward by one character.
Definition embedder.h:142
@ kFlutterSemanticsActionMoveCursorForwardByWord
Move the cursor forward by one word.
Definition embedder.h:160
@ kFlutterSemanticsActionSetSelection
Set the text selection to the given range.
Definition embedder.h:144
@ kFlutterSemanticsActionPaste
Paste the current content of the clipboard.
Definition embedder.h:150
@ kFlutterSemanticsActionCut
Cut the current selection and place it in the clipboard.
Definition embedder.h:148
@ kFlutterSemanticsActionCopy
Copy the current selection to the clipboard.
Definition embedder.h:146
@ kFlutterSemanticsActionMoveCursorBackwardByWord
Move the cursor backward by one word.
Definition embedder.h:162
@ kFlutterSemanticsActionSetText
Replace the current text in the text field.
Definition embedder.h:164
FlutterTextDirection
Definition embedder.h:246
@ kFlutterTextDirectionRTL
Text is read from right to left.
Definition embedder.h:250
FlutterEngine engine
Definition main.cc:68
void fl_accessible_node_perform_action(FlAccessibleNode *self, FlutterSemanticsAction action, GBytes *data)
#define FL_TYPE_ACCESSIBLE_NODE
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)
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)
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)
glong glong end
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)
G_DEFINE_TYPE_WITH_CODE(FlAccessibleTextField, fl_accessible_text_field, FL_TYPE_ACCESSIBLE_NODE, G_IMPLEMENT_INTERFACE(ATK_TYPE_EDITABLE_TEXT, fl_accessible_editable_text_iface_init)) static gchar *get_substring(FlAccessibleTextField *self
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)
FlAccessibleNode * fl_accessible_text_field_new(FlEngine *engine, int32_t id)
static PangoLayout * create_pango_layout(FlAccessibleTextField *self)
void fl_accessible_text_field_perform_action(FlAccessibleNode *self, FlutterSemanticsAction action, GBytes *data)
G_MODULE_EXPORT GBytes * fl_message_codec_encode_message(FlMessageCodec *self, FlValue *message, GError **error)
uint8_t value
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
size_t length
std::u16string text
Win32Message message
Point offset
FlutterTextDirection text_direction