55#include " flutter/shell/platform/linux/fl_accessible_node.h"
66#include " flutter/shell/platform/linux/fl_engine_private.h"
77
8- // Maps Flutter semantics flags to ATK flags.
9- static struct {
10- AtkStateType state;
11- FlutterSemanticsFlag flag;
12- gboolean invert;
13- } flag_mapping[] = {
14- {ATK_STATE_SHOWING, kFlutterSemanticsFlagIsObscured , TRUE },
15- {ATK_STATE_VISIBLE, kFlutterSemanticsFlagIsHidden , TRUE },
16- {ATK_STATE_CHECKABLE, kFlutterSemanticsFlagHasCheckedState , FALSE },
17- {ATK_STATE_FOCUSABLE, kFlutterSemanticsFlagIsFocusable , FALSE },
18- {ATK_STATE_FOCUSED, kFlutterSemanticsFlagIsFocused , FALSE },
19- {ATK_STATE_CHECKED,
20- static_cast <FlutterSemanticsFlag>(kFlutterSemanticsFlagIsChecked |
21- kFlutterSemanticsFlagIsToggled ),
22- FALSE },
23- {ATK_STATE_SELECTED, kFlutterSemanticsFlagIsSelected , FALSE },
24- {ATK_STATE_ENABLED, kFlutterSemanticsFlagIsEnabled , FALSE },
25- {ATK_STATE_SENSITIVE, kFlutterSemanticsFlagIsEnabled , FALSE },
26- {ATK_STATE_READ_ONLY, kFlutterSemanticsFlagIsReadOnly , FALSE },
27- {ATK_STATE_EDITABLE, kFlutterSemanticsFlagIsTextField , FALSE },
28- {ATK_STATE_INVALID, static_cast <FlutterSemanticsFlag>(0 ), FALSE },
29- };
30-
318// Maps Flutter semantics actions to ATK actions.
329typedef struct {
3310 FlutterSemanticsAction action;
@@ -81,7 +58,7 @@ struct FlAccessibleNodePrivate {
8158 GPtrArray* actions;
8259 gsize actions_length;
8360 GPtrArray* children;
84- FlutterSemanticsFlag flags;
61+ FlutterSemanticsFlags flags;
8562};
8663
8764enum { PROP_0, PROP_ENGINE, PROP_VIEW_ID, PROP_ID, PROP_LAST };
@@ -104,19 +81,6 @@ G_DEFINE_TYPE_WITH_CODE(
10481 G_IMPLEMENT_INTERFACE(ATK_TYPE_ACTION,
10582 fl_accessible_node_action_interface_init))
10683
107- // Returns TRUE if [flag] has changed between [old_flags] and [flags].
108- static gboolean flag_is_changed(FlutterSemanticsFlag old_flags,
109- FlutterSemanticsFlag flags,
110- FlutterSemanticsFlag flag) {
111- return (old_flags & flag) != (flags & flag);
112- }
113-
114- // Returns TRUE if [flag] is set in [flags].
115- static gboolean has_flag (FlutterSemanticsFlag flags,
116- FlutterSemanticsFlag flag) {
117- return (flags & flag) != 0 ;
118- }
119-
12084// Returns TRUE if [action] is set in [actions].
12185static gboolean has_action(FlutterSemanticsAction actions,
12286 FlutterSemanticsAction action) {
@@ -224,36 +188,35 @@ static AtkObject* fl_accessible_node_ref_child(AtkObject* accessible, gint i) {
224188// Implements AtkObject::get_role.
225189static AtkRole fl_accessible_node_get_role (AtkObject* accessible) {
226190 FlAccessibleNodePrivate* priv = FL_ACCESSIBLE_NODE_GET_PRIVATE (accessible);
227- if (( priv->flags & kFlutterSemanticsFlagIsButton ) != 0 ) {
191+ if (priv->flags . is_button ) {
228192 return ATK_ROLE_PUSH_BUTTON;
229193 }
230- if (( priv->flags & kFlutterSemanticsFlagIsInMutuallyExclusiveGroup ) != 0 &&
231- ( priv->flags & kFlutterSemanticsFlagHasCheckedState ) != 0 ) {
194+ if (priv->flags . is_in_mutually_exclusive_group &&
195+ priv->flags . is_checked != kFlutterCheckStateNone ) {
232196 return ATK_ROLE_RADIO_BUTTON;
233197 }
234- if (( priv->flags & kFlutterSemanticsFlagHasCheckedState ) != 0 ) {
198+ if (priv->flags . is_checked != kFlutterCheckStateNone ) {
235199 return ATK_ROLE_CHECK_BOX;
236200 }
237- if (( priv->flags & kFlutterSemanticsFlagHasToggledState ) != 0 ) {
201+ if (priv->flags . is_toggled != kFlutterTristateNone ) {
238202 return ATK_ROLE_TOGGLE_BUTTON;
239203 }
240- if (( priv->flags & kFlutterSemanticsFlagIsSlider ) != 0 ) {
204+ if (priv->flags . is_slider ) {
241205 return ATK_ROLE_SLIDER;
242206 }
243- if ((priv->flags & kFlutterSemanticsFlagIsTextField ) != 0 &&
244- (priv->flags & kFlutterSemanticsFlagIsObscured ) != 0 ) {
207+ if (priv->flags .is_text_field && priv->flags .is_obscured ) {
245208 return ATK_ROLE_PASSWORD_TEXT;
246209 }
247- if (( priv->flags & kFlutterSemanticsFlagIsTextField ) != 0 ) {
210+ if (priv->flags . is_text_field ) {
248211 return ATK_ROLE_TEXT;
249212 }
250- if (( priv->flags & kFlutterSemanticsFlagIsHeader ) != 0 ) {
213+ if (priv->flags . is_header ) {
251214 return ATK_ROLE_HEADER;
252215 }
253- if (( priv->flags & kFlutterSemanticsFlagIsLink ) != 0 ) {
216+ if (priv->flags . is_link ) {
254217 return ATK_ROLE_LINK;
255218 }
256- if (( priv->flags & kFlutterSemanticsFlagIsImage ) != 0 ) {
219+ if (priv->flags . is_image ) {
257220 return ATK_ROLE_IMAGE;
258221 }
259222
@@ -266,14 +229,36 @@ static AtkStateSet* fl_accessible_node_ref_state_set(AtkObject* accessible) {
266229
267230 AtkStateSet* state_set = atk_state_set_new ();
268231
269- for (int i = 0 ; flag_mapping[i].state != ATK_STATE_INVALID; i++) {
270- gboolean enabled = has_flag (priv->flags , flag_mapping[i].flag );
271- if (flag_mapping[i].invert ) {
272- enabled = !enabled;
273- }
274- if (enabled) {
275- atk_state_set_add_state (state_set, flag_mapping[i].state );
276- }
232+ if (!priv->flags .is_obscured ) {
233+ atk_state_set_add_state (state_set, ATK_STATE_SHOWING);
234+ }
235+ if (!priv->flags .is_hidden ) {
236+ atk_state_set_add_state (state_set, ATK_STATE_VISIBLE);
237+ }
238+ if (priv->flags .is_checked != kFlutterCheckStateNone ) {
239+ atk_state_set_add_state (state_set, ATK_STATE_CHECKABLE);
240+ }
241+ if (priv->flags .is_focused != kFlutterTristateNone ) {
242+ atk_state_set_add_state (state_set, ATK_STATE_FOCUSABLE);
243+ }
244+ if (priv->flags .is_focused == kFlutterTristateTrue ) {
245+ atk_state_set_add_state (state_set, ATK_STATE_FOCUSED);
246+ }
247+ if (priv->flags .is_checked || priv->flags .is_toggled ) {
248+ atk_state_set_add_state (state_set, ATK_STATE_CHECKED);
249+ }
250+ if (priv->flags .is_selected ) {
251+ atk_state_set_add_state (state_set, ATK_STATE_SELECTED);
252+ }
253+ if (priv->flags .is_enabled == kFlutterTristateTrue ) {
254+ atk_state_set_add_state (state_set, ATK_STATE_ENABLED);
255+ atk_state_set_add_state (state_set, ATK_STATE_SENSITIVE);
256+ }
257+ if (priv->flags .is_read_only ) {
258+ atk_state_set_add_state (state_set, ATK_STATE_READ_ONLY);
259+ }
260+ if (priv->flags .is_text_field ) {
261+ atk_state_set_add_state (state_set, ATK_STATE_EDITABLE);
277262 }
278263
279264 return state_set;
@@ -363,24 +348,73 @@ static void fl_accessible_node_set_extents_impl(FlAccessibleNode* self,
363348 priv->height = height;
364349}
365350
351+ // Check two boolean flags are different, in a way that handles true values
352+ // being different (e.g. 1 and 2).
353+ static bool flag_changed (bool old_flag, bool new_flag) {
354+ return !old_flag != !new_flag;
355+ }
356+
366357// Implements FlAccessibleNode::set_flags.
367358static void fl_accessible_node_set_flags_impl (FlAccessibleNode* self,
368- FlutterSemanticsFlag flags) {
359+ FlutterSemanticsFlags* flags) {
369360 FlAccessibleNodePrivate* priv = FL_ACCESSIBLE_NODE_GET_PRIVATE (self);
370361
371- FlutterSemanticsFlag old_flags = priv->flags ;
372- priv->flags = flags;
373-
374- for (int i = 0 ; flag_mapping[i].state != ATK_STATE_INVALID; i++) {
375- if (flag_is_changed (old_flags, flags, flag_mapping[i].flag )) {
376- gboolean enabled = has_flag (flags, flag_mapping[i].flag );
377- if (flag_mapping[i].invert ) {
378- enabled = !enabled;
379- }
362+ FlutterSemanticsFlags old_flags = priv->flags ;
363+ priv->flags = *flags;
380364
381- atk_object_notify_state_change (ATK_OBJECT (self), flag_mapping[i].state ,
382- enabled);
383- }
365+ if (flag_changed (old_flags.is_obscured , flags->is_obscured )) {
366+ atk_object_notify_state_change (ATK_OBJECT (self), ATK_STATE_SHOWING,
367+ !flags->is_obscured );
368+ }
369+ if (flag_changed (old_flags.is_hidden , flags->is_hidden )) {
370+ atk_object_notify_state_change (ATK_OBJECT (self), ATK_STATE_VISIBLE,
371+ !flags->is_hidden );
372+ }
373+ bool was_checkable = old_flags.is_checked != kFlutterCheckStateNone ;
374+ bool is_checkable = flags->is_checked != kFlutterCheckStateNone ;
375+ if (flag_changed (was_checkable, is_checkable)) {
376+ atk_object_notify_state_change (ATK_OBJECT (self), ATK_STATE_CHECKABLE,
377+ is_checkable);
378+ }
379+ if (flag_changed (old_flags.is_focused , flags->is_focused )) {
380+ atk_object_notify_state_change (ATK_OBJECT (self), ATK_STATE_FOCUSABLE,
381+ flags->is_focused != kFlutterTristateNone );
382+ }
383+ if (flag_changed (old_flags.is_focused , flags->is_focused )) {
384+ atk_object_notify_state_change (ATK_OBJECT (self), ATK_STATE_FOCUSED,
385+ flags->is_focused == kFlutterTristateTrue );
386+ }
387+ bool old_is_checked = old_flags.is_checked || old_flags.is_toggled ;
388+ bool is_checked = flags->is_checked || flags->is_toggled ;
389+ if (flag_changed (old_is_checked, is_checked)) {
390+ atk_object_notify_state_change (ATK_OBJECT (self), ATK_STATE_CHECKED,
391+ is_checked);
392+ }
393+ if (flag_changed (old_flags.is_selected , flags->is_selected )) {
394+ atk_object_notify_state_change (ATK_OBJECT (self), ATK_STATE_SELECTED,
395+ flags->is_selected );
396+ }
397+ if (flag_changed (old_flags.is_enabled , flags->is_enabled )) {
398+ atk_object_notify_state_change (ATK_OBJECT (self), ATK_STATE_ENABLED,
399+ flags->is_enabled );
400+ atk_object_notify_state_change (ATK_OBJECT (self), ATK_STATE_SENSITIVE,
401+ flags->is_enabled );
402+ }
403+ if (flag_changed (old_flags.is_enabled , flags->is_enabled )) {
404+ atk_object_notify_state_change (ATK_OBJECT (self), ATK_STATE_ENABLED,
405+ flags->is_enabled );
406+ }
407+ if (flag_changed (old_flags.is_enabled , flags->is_enabled )) {
408+ atk_object_notify_state_change (ATK_OBJECT (self), ATK_STATE_ENABLED,
409+ flags->is_enabled );
410+ }
411+ if (flag_changed (old_flags.is_read_only , flags->is_read_only )) {
412+ atk_object_notify_state_change (ATK_OBJECT (self), ATK_STATE_READ_ONLY,
413+ flags->is_read_only );
414+ }
415+ if (flag_changed (old_flags.is_text_field , flags->is_text_field )) {
416+ atk_object_notify_state_change (ATK_OBJECT (self), ATK_STATE_EDITABLE,
417+ flags->is_text_field );
384418 }
385419}
386420
@@ -557,7 +591,7 @@ void fl_accessible_node_set_extents(FlAccessibleNode* self,
557591}
558592
559593void fl_accessible_node_set_flags (FlAccessibleNode* self,
560- FlutterSemanticsFlag flags) {
594+ FlutterSemanticsFlags* flags) {
561595 g_return_if_fail (FL_IS_ACCESSIBLE_NODE (self));
562596
563597 return FL_ACCESSIBLE_NODE_GET_CLASS (self)->set_flags (self, flags);
0 commit comments