Skip to content

Commit 117c60e

Browse files
Update Linux embedder to new semantics flags API (flutter#170497)
As changed in flutter#167738.
1 parent 3fee9b9 commit 117c60e

File tree

6 files changed

+153
-113
lines changed

6 files changed

+153
-113
lines changed

engine/src/flutter/shell/platform/linux/fl_accessible_node.cc

Lines changed: 105 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -5,29 +5,6 @@
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.
329
typedef 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

8764
enum { 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].
12185
static 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.
225189
static 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.
367358
static 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

559593
void 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);

engine/src/flutter/shell/platform/linux/fl_accessible_node.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ struct _FlAccessibleNodeClass {
4040
gint y,
4141
gint width,
4242
gint height);
43-
void (*set_flags)(FlAccessibleNode* node, FlutterSemanticsFlag flags);
43+
void (*set_flags)(FlAccessibleNode* node, FlutterSemanticsFlags* flags);
4444
void (*set_actions)(FlAccessibleNode* node, FlutterSemanticsAction actions);
4545
void (*set_value)(FlAccessibleNode* node, const gchar* value);
4646
void (*set_text_selection)(FlAccessibleNode* node, gint base, gint extent);
@@ -122,7 +122,7 @@ void fl_accessible_node_set_extents(FlAccessibleNode* node,
122122
* Sets the flags for this node.
123123
*/
124124
void fl_accessible_node_set_flags(FlAccessibleNode* node,
125-
FlutterSemanticsFlag flags);
125+
FlutterSemanticsFlags* flags);
126126

127127
/**
128128
* fl_accessible_node_set_actions:

engine/src/flutter/shell/platform/linux/fl_accessible_node_test.cc

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -77,10 +77,10 @@ TEST(FlAccessibleNodeTest, SetFlags) {
7777
g_autoptr(FlEngine) engine = fl_engine_new(project);
7878

7979
g_autoptr(FlAccessibleNode) node = fl_accessible_node_new(engine, 123, 0);
80-
fl_accessible_node_set_flags(
81-
node, static_cast<FlutterSemanticsFlag>(kFlutterSemanticsFlagIsEnabled |
82-
kFlutterSemanticsFlagIsFocusable |
83-
kFlutterSemanticsFlagIsFocused));
80+
FlutterSemanticsFlags flags = {};
81+
flags.is_enabled = kFlutterTristateTrue;
82+
flags.is_focused = kFlutterTristateTrue;
83+
fl_accessible_node_set_flags(node, &flags);
8484

8585
AtkStateSet* state = atk_object_ref_state_set(ATK_OBJECT(node));
8686
EXPECT_TRUE(atk_state_set_contains_state(state, ATK_STATE_ENABLED));
@@ -98,30 +98,36 @@ TEST(FlAccessibleNodeTest, GetRole) {
9898

9999
g_autoptr(FlAccessibleNode) node = fl_accessible_node_new(engine, 123, 0);
100100

101-
fl_accessible_node_set_flags(
102-
node, static_cast<FlutterSemanticsFlag>(kFlutterSemanticsFlagIsButton));
101+
FlutterSemanticsFlags flags1 = {};
102+
flags1.is_button = true;
103+
fl_accessible_node_set_flags(node, &flags1);
103104
EXPECT_EQ(atk_object_get_role(ATK_OBJECT(node)), ATK_ROLE_PUSH_BUTTON);
104105

105-
fl_accessible_node_set_flags(node, static_cast<FlutterSemanticsFlag>(
106-
kFlutterSemanticsFlagHasCheckedState));
106+
FlutterSemanticsFlags flags2 = {};
107+
flags2.is_checked = kFlutterCheckStateFalse;
108+
fl_accessible_node_set_flags(node, &flags2);
107109
EXPECT_EQ(atk_object_get_role(ATK_OBJECT(node)), ATK_ROLE_CHECK_BOX);
108110

109-
fl_accessible_node_set_flags(
110-
node, static_cast<FlutterSemanticsFlag>(
111-
kFlutterSemanticsFlagHasCheckedState |
112-
kFlutterSemanticsFlagIsInMutuallyExclusiveGroup));
111+
FlutterSemanticsFlags flags3 = {};
112+
flags3.is_checked = kFlutterCheckStateFalse;
113+
flags3.is_in_mutually_exclusive_group = true;
114+
fl_accessible_node_set_flags(node, &flags3);
113115
EXPECT_EQ(atk_object_get_role(ATK_OBJECT(node)), ATK_ROLE_RADIO_BUTTON);
114116

115-
fl_accessible_node_set_flags(node, static_cast<FlutterSemanticsFlag>(
116-
kFlutterSemanticsFlagHasToggledState));
117+
FlutterSemanticsFlags flags4 = {};
118+
flags4.is_toggled = kFlutterTristateFalse;
119+
fl_accessible_node_set_flags(node, &flags4);
117120
EXPECT_EQ(atk_object_get_role(ATK_OBJECT(node)), ATK_ROLE_TOGGLE_BUTTON);
118121

119-
fl_accessible_node_set_flags(node, kFlutterSemanticsFlagIsTextField);
122+
FlutterSemanticsFlags flags5 = {};
123+
flags5.is_text_field = true;
124+
fl_accessible_node_set_flags(node, &flags5);
120125
EXPECT_EQ(atk_object_get_role(ATK_OBJECT(node)), ATK_ROLE_TEXT);
121126

122-
fl_accessible_node_set_flags(
123-
node, static_cast<FlutterSemanticsFlag>(kFlutterSemanticsFlagIsTextField |
124-
kFlutterSemanticsFlagIsObscured));
127+
FlutterSemanticsFlags flags6 = {};
128+
flags6.is_text_field = true;
129+
flags6.is_obscured = true;
130+
fl_accessible_node_set_flags(node, &flags6);
125131
EXPECT_EQ(atk_object_get_role(ATK_OBJECT(node)), ATK_ROLE_PASSWORD_TEXT);
126132
}
127133

engine/src/flutter/shell/platform/linux/fl_view_accessible.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ static FlAccessibleNode* create_node(FlViewAccessible* self,
3333
return nullptr;
3434
}
3535

36-
if (semantics->flags__deprecated__ & kFlutterSemanticsFlagIsTextField) {
36+
if (semantics->flags2->is_text_field) {
3737
return fl_accessible_text_field_new(engine, self->view_id, semantics->id);
3838
}
3939

@@ -152,7 +152,7 @@ void fl_view_accessible_handle_update_semantics(
152152
FlutterSemanticsNode2* node = update->nodes[i];
153153
FlAccessibleNode* atk_node = get_node(self, node);
154154

155-
fl_accessible_node_set_flags(atk_node, node->flags__deprecated__);
155+
fl_accessible_node_set_flags(atk_node, node->flags2);
156156
fl_accessible_node_set_actions(atk_node, node->actions);
157157
fl_accessible_node_set_name(atk_node, node->label);
158158
fl_accessible_node_set_extents(

0 commit comments

Comments
 (0)