Flutter Linux Embedder
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 
9 G_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)
13 G_DEFINE_AUTOPTR_CLEANUP_FUNC(PangoLayout, g_object_unref)
14 #endif
15 
16 typedef bool (*FlTextBoundaryCallback)(const PangoLogAttr* attr);
17 
19  FlAccessibleNode parent_instance;
20 
23  GtkEntryBuffer* buffer;
24  FlutterTextDirection text_direction;
25 };
26 
27 static void fl_accessible_text_iface_init(AtkTextIface* iface);
28 static 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 
38 static 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 
49 static 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 
59 static 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 
66 static gchar* get_string_at_offset(FlAccessibleTextField* self,
67  gint start,
68  gint end,
69  FlTextBoundaryCallback is_start,
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 
96 static gchar* get_char_at_offset(FlAccessibleTextField* self,
97  gint offset,
98  gint* start_offset,
99  gint* end_offset) {
100  return get_string_at_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 
107 static gchar* get_word_at_offset(FlAccessibleTextField* self,
108  gint offset,
109  gint* start_offset,
110  gint* end_offset) {
111  return get_string_at_offset(
112  self, offset, 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 
118 static gchar* get_sentence_at_offset(FlAccessibleTextField* self,
119  gint offset,
120  gint* start_offset,
121  gint* end_offset) {
122  return get_string_at_offset(
123  self, offset, 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 
129 static 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 
155 static 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 
188 static void perform_set_text_action(FlAccessibleTextField* self,
189  const char* text) {
190  g_autoptr(FlValue) value = fl_value_new_string(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),
196  kFlutterSemanticsActionSetText, message);
197 }
198 
199 static void perform_set_selection_action(FlAccessibleTextField* self,
200  gint base,
201  gint extent) {
202  g_autoptr(FlValue) value = fl_value_new_map();
204  fl_value_set_string_take(value, "extent", fl_value_new_int(extent));
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.
215 static 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.
224 static 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.
237 static 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.
272 void fl_accessible_text_field_perform_action(FlAccessibleNode* self,
273  FlutterSemanticsAction action,
274  GBytes* data) {
275  FlAccessibleNodeClass* parent_class =
276  FL_ACCESSIBLE_NODE_CLASS(fl_accessible_text_field_parent_class);
277 
278  switch (action) {
279  case kFlutterSemanticsActionMoveCursorForwardByCharacter:
280  case kFlutterSemanticsActionMoveCursorBackwardByCharacter:
281  case kFlutterSemanticsActionMoveCursorForwardByWord:
282  case kFlutterSemanticsActionMoveCursorBackwardByWord: {
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.
307 static gchar* fl_accessible_text_field_get_text(AtkText* 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.
376 static gint fl_accessible_text_field_get_caret_offset(AtkText* text) {
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.
384 static gboolean fl_accessible_text_field_set_caret_offset(AtkText* text,
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 
389  perform_set_selection_action(self, offset, offset);
390  return TRUE;
391 }
392 
393 // Implements AtkText::get_n_selections.
394 static gint fl_accessible_text_field_get_n_selections(AtkText* text) {
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.
406 static gchar* fl_accessible_text_field_get_selection(AtkText* text,
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.
431 static gboolean fl_accessible_text_field_add_selection(AtkText* text,
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.
446 static gboolean fl_accessible_text_field_remove_selection(AtkText* text,
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.
461 static gboolean fl_accessible_text_field_set_selection(AtkText* text,
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 
483  perform_set_text_action(self, string);
484 }
485 
486 // Implements AtkEditableText::insert_text.
487 static 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.
502 static 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.
515 static 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),
524  kFlutterSemanticsActionCopy, nullptr);
525 }
526 
527 // Implements AtkEditableText::cut_text.
528 static 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),
537  kFlutterSemanticsActionCut, nullptr);
538 }
539 
540 // Implements AtkEditableText::paste_text.
541 static 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),
549  kFlutterSemanticsActionPaste, nullptr);
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 
565 static 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 
592 static 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 
618 FlAccessibleNode* 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 }
fl_accessible_text_field_get_text
static gchar * fl_accessible_text_field_get_text(AtkText *text, gint start_offset, gint end_offset)
Definition: fl_accessible_text_field.cc:307
perform_set_text_action
static void perform_set_text_action(FlAccessibleTextField *self, const char *text)
Definition: fl_accessible_text_field.cc:188
fl_accessible_text_field_set_text_direction
static void fl_accessible_text_field_set_text_direction(FlAccessibleNode *node, FlutterTextDirection direction)
Definition: fl_accessible_text_field.cc:262
fl_accessible_text_field_get_n_selections
static gint fl_accessible_text_field_get_n_selections(AtkText *text)
Definition: fl_accessible_text_field.cc:394
fl_standard_message_codec_new
G_MODULE_EXPORT FlStandardMessageCodec * fl_standard_message_codec_new()
Definition: fl_standard_message_codec.cc:637
fl_accessible_text_field_set_text_selection
static void fl_accessible_text_field_set_text_selection(FlAccessibleNode *node, gint base, gint extent)
Definition: fl_accessible_text_field.cc:237
fl_accessible_text_field_perform_action
void fl_accessible_text_field_perform_action(FlAccessibleNode *self, FlutterSemanticsAction action, GBytes *data)
Definition: fl_accessible_text_field.cc:272
fl_value_set_string_take
G_MODULE_EXPORT void fl_value_set_string_take(FlValue *self, const gchar *key, FlValue *value)
Definition: fl_value.cc:650
get_line_at_offset
static gchar * get_line_at_offset(FlAccessibleTextField *self, gint offset, gint *start_offset, gint *end_offset)
Definition: fl_accessible_text_field.cc:129
fl_accessible_text_field_get_selection
static gchar * fl_accessible_text_field_get_selection(AtkText *text, gint selection_num, gint *start_offset, gint *end_offset)
Definition: fl_accessible_text_field.cc:406
fl_accessible_text_field_new
FlAccessibleNode * fl_accessible_text_field_new(FlEngine *engine, int32_t id)
Definition: fl_accessible_text_field.cc:618
fl_accessible_text_field_remove_selection
static gboolean fl_accessible_text_field_remove_selection(AtkText *text, gint selection_num)
Definition: fl_accessible_text_field.cc:446
i
int i
Definition: fl_socket_accessible.cc:18
g_utf8_substring
return g_utf8_substring(value, start, end)
FL_TYPE_ACCESSIBLE_NODE
#define FL_TYPE_ACCESSIBLE_NODE
Definition: fl_accessible_node.h:22
fl_value_new_bool
G_MODULE_EXPORT FlValue * fl_value_new_bool(bool value)
Definition: fl_value.cc:255
FlValue
typedefG_BEGIN_DECLS struct _FlValue FlValue
Definition: fl_value.h:42
_FlAccessibleTextField::text_direction
FlutterTextDirection text_direction
Definition: fl_accessible_text_field.cc:24
fl_value_new_int
G_MODULE_EXPORT FlValue * fl_value_new_int(int64_t value)
Definition: fl_value.cc:262
get_string_at_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)
Definition: fl_accessible_text_field.cc:66
fl_accessible_text_field_get_caret_offset
static gint fl_accessible_text_field_get_caret_offset(AtkText *text)
Definition: fl_accessible_text_field.cc:376
_FlAccessibleTextField
Definition: fl_accessible_text_field.cc:18
fl_accessible_text_field_get_character_count
static gint fl_accessible_text_field_get_character_count(AtkText *text)
Definition: fl_accessible_text_field.cc:299
fl_accessible_text_field_get_text_at_offset
static gchar * fl_accessible_text_field_get_text_at_offset(AtkText *text, gint offset, AtkTextBoundary boundary_type, gint *start_offset, gint *end_offset)
Definition: fl_accessible_text_field.cc:343
fl_accessible_node_perform_action
void fl_accessible_node_perform_action(FlAccessibleNode *self, FlutterSemanticsAction action, GBytes *data)
Definition: fl_accessible_node.cc:580
fl_value_new_map
G_MODULE_EXPORT FlValue * fl_value_new_map()
Definition: fl_value.cc:366
fl_accessible_text_field_get_string_at_offset
static gchar * fl_accessible_text_field_get_string_at_offset(AtkText *text, gint offset, AtkTextGranularity granularity, gint *start_offset, gint *end_offset)
Definition: fl_accessible_text_field.cc:317
get_sentence_at_offset
static gchar * get_sentence_at_offset(FlAccessibleTextField *self, gint offset, gint *start_offset, gint *end_offset)
Definition: fl_accessible_text_field.cc:118
fl_accessible_text_field_copy_text
static void fl_accessible_text_field_copy_text(AtkEditableText *editable_text, gint start_pos, gint end_pos)
Definition: fl_accessible_text_field.cc:515
fl_accessible_text_field_add_selection
static gboolean fl_accessible_text_field_add_selection(AtkText *text, gint start_offset, gint end_offset)
Definition: fl_accessible_text_field.cc:431
fl_accessible_text_iface_init
static void fl_accessible_text_iface_init(AtkTextIface *iface)
Definition: fl_accessible_text_field.cc:565
fl_accessible_text_field_set_text_contents
static void fl_accessible_text_field_set_text_contents(AtkEditableText *editable_text, const gchar *string)
Definition: fl_accessible_text_field.cc:477
TRUE
return TRUE
Definition: fl_pixel_buffer_texture_test.cc:53
start
glong start
Definition: fl_accessible_text_field.cc:39
FlTextBoundaryCallback
bool(* FlTextBoundaryCallback)(const PangoLogAttr *attr)
Definition: fl_accessible_text_field.cc:16
end
glong glong end
Definition: fl_accessible_text_field.cc:40
perform_set_selection_action
static void perform_set_selection_action(FlAccessibleTextField *self, gint base, gint extent)
Definition: fl_accessible_text_field.cc:199
fl_accessible_text_field_init
static void fl_accessible_text_field_init(FlAccessibleTextField *self)
Definition: fl_accessible_text_field.cc:592
get_word_at_offset
static gchar * get_word_at_offset(FlAccessibleTextField *self, gint offset, gint *start_offset, gint *end_offset)
Definition: fl_accessible_text_field.cc:107
fl_accessible_text_field_set_selection
static gboolean fl_accessible_text_field_set_selection(AtkText *text, gint selection_num, gint start_offset, gint end_offset)
Definition: fl_accessible_text_field.cc:461
create_pango_layout
static PangoLayout * create_pango_layout(FlAccessibleTextField *self)
Definition: fl_accessible_text_field.cc:59
fl_accessible_text_field_set_value
static void fl_accessible_text_field_set_value(FlAccessibleNode *node, const gchar *value)
Definition: fl_accessible_text_field.cc:224
fl_accessible_editable_text_iface_init
static void fl_accessible_editable_text_iface_init(AtkEditableTextIface *iface)
Definition: fl_accessible_text_field.cc:581
fl_accessible_text_field.h
fl_value.h
get_char_at_offset
static gchar * get_char_at_offset(FlAccessibleTextField *self, gint offset, gint *start_offset, gint *end_offset)
Definition: fl_accessible_text_field.cc:96
_FlAccessibleTextField::selection_extent
gint selection_extent
Definition: fl_accessible_text_field.cc:22
_FlAccessibleTextField::parent_instance
FlAccessibleNode parent_instance
Definition: fl_accessible_text_field.cc:19
fl_accessible_text_field_paste_text
static void fl_accessible_text_field_paste_text(AtkEditableText *editable_text, gint position)
Definition: fl_accessible_text_field.cc:541
fl_message_codec_encode_message
G_MODULE_EXPORT GBytes * fl_message_codec_encode_message(FlMessageCodec *self, FlValue *message, GError **error)
Definition: fl_message_codec.cc:17
_FlAccessibleTextField::buffer
GtkEntryBuffer * buffer
Definition: fl_accessible_text_field.cc:23
fl_accessible_text_field_cut_text
static void fl_accessible_text_field_cut_text(AtkEditableText *editable_text, gint start_pos, gint end_pos)
Definition: fl_accessible_text_field.cc:528
fl_accessible_text_field_set_caret_offset
static gboolean fl_accessible_text_field_set_caret_offset(AtkText *text, gint offset)
Definition: fl_accessible_text_field.cc:384
get_paragraph_at_offset
static gchar * get_paragraph_at_offset(FlAccessibleTextField *self, gint offset, gint *start_offset, gint *end_offset)
Definition: fl_accessible_text_field.cc:155
fl_standard_message_codec.h
fl_accessible_text_field_insert_text
static void fl_accessible_text_field_insert_text(AtkEditableText *editable_text, const gchar *string, gint length, gint *position)
Definition: fl_accessible_text_field.cc:487
G_DEFINE_TYPE_WITH_CODE
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
fl_accessible_text_field_dispose
static void fl_accessible_text_field_dispose(GObject *object)
Definition: fl_accessible_text_field.cc:215
_FlAccessibleTextField::selection_base
gint selection_base
Definition: fl_accessible_text_field.cc:21
value
uint8_t value
Definition: fl_standard_message_codec.cc:36
length
size_t length
Definition: fl_standard_message_codec_test.cc:1113
get_pango_context
static PangoContext * get_pango_context(FlAccessibleTextField *self)
Definition: fl_accessible_text_field.cc:49
fl_value_new_string
G_MODULE_EXPORT FlValue * fl_value_new_string(const gchar *value)
Definition: fl_value.cc:276
fl_accessible_text_field_class_init
static void fl_accessible_text_field_class_init(FlAccessibleTextFieldClass *klass)
Definition: fl_accessible_text_field.cc:552
fl_accessible_node_delete_text
static void fl_accessible_node_delete_text(AtkEditableText *editable_text, gint start_pos, gint end_pos)
Definition: fl_accessible_text_field.cc:502