Skip to content

Commit f885b8a

Browse files
committed
Editor: Improve accessibility for Editor and Project Settings
- Add accessibility names to EditorSpinSlider, inspector scrollbar, and settings categories tree - Propagate property labels to focusable controls in EditorProperty::set_label - Eliminate duplicate tab stops by setting EditorProperty to FOCUS_NONE when it has focusable children - Fix EditorSettingsPropertyWrapper to pass label and set proper focus mode - Skip setting empty 'Property:' accessibility names
1 parent 4036e90 commit f885b8a

File tree

4 files changed

+61
-3
lines changed

4 files changed

+61
-3
lines changed

editor/gui/editor_spin_slider.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,32 @@ void EditorSpinSlider::_draw_spin_slider() {
461461

462462
void EditorSpinSlider::_notification(int p_what) {
463463
switch (p_what) {
464+
case NOTIFICATION_ACCESSIBILITY_UPDATE: {
465+
RID ae = get_accessibility_element();
466+
ERR_FAIL_COND(ae.is_null());
467+
468+
DisplayServer::get_singleton()->accessibility_update_set_role(ae, DisplayServer::AccessibilityRole::ROLE_SPIN_BUTTON);
469+
// Use accessibility_name if set, otherwise fall back to label property.
470+
String name = get_accessibility_name();
471+
if (name.is_empty()) {
472+
name = label;
473+
}
474+
DisplayServer::get_singleton()->accessibility_update_set_name(ae, name);
475+
DisplayServer::get_singleton()->accessibility_update_set_description(ae, get_accessibility_description());
476+
DisplayServer::get_singleton()->accessibility_update_set_num_value(ae, get_value());
477+
DisplayServer::get_singleton()->accessibility_update_set_num_range(ae, get_min(), get_max());
478+
if (get_step() > 0) {
479+
DisplayServer::get_singleton()->accessibility_update_set_num_step(ae, get_step());
480+
} else {
481+
DisplayServer::get_singleton()->accessibility_update_set_num_step(ae, 1);
482+
}
483+
484+
// Propagate accessibility name to internal LineEdit.
485+
if (value_input && !name.is_empty()) {
486+
value_input->set_accessibility_name(name);
487+
}
488+
} break;
489+
464490
case NOTIFICATION_ENTER_TREE: {
465491
grabbing_spinner_speed = editing_integer ? EDITOR_GET("interface/inspector/integer_drag_speed") : EDITOR_GET("interface/inspector/float_drag_speed");
466492
_update_value_input_stylebox();

editor/inspector/editor_inspector.cpp

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -289,8 +289,10 @@ void EditorProperty::_notification(int p_what) {
289289

290290
DisplayServer::get_singleton()->accessibility_update_set_role(ae, DisplayServer::AccessibilityRole::ROLE_BUTTON);
291291

292-
DisplayServer::get_singleton()->accessibility_update_set_name(ae, vformat(TTR("Property: %s"), label));
293-
DisplayServer::get_singleton()->accessibility_update_set_value(ae, vformat(TTR("Property: %s"), label));
292+
if (!label.is_empty()) {
293+
DisplayServer::get_singleton()->accessibility_update_set_name(ae, vformat(TTR("Property: %s"), label));
294+
DisplayServer::get_singleton()->accessibility_update_set_value(ae, vformat(TTR("Property: %s"), label));
295+
}
294296

295297
DisplayServer::get_singleton()->accessibility_update_set_popup_type(ae, DisplayServer::AccessibilityPopupType::POPUP_MENU);
296298
DisplayServer::get_singleton()->accessibility_update_add_action(ae, DisplayServer::AccessibilityAction::ACTION_SHOW_CONTEXT_MENU, callable_mp(this, &EditorProperty::_accessibility_action_menu));
@@ -715,6 +717,23 @@ void EditorProperty::_notification(int p_what) {
715717
void EditorProperty::set_label(const String &p_label) {
716718
label = p_label;
717719
queue_redraw();
720+
721+
// Propagate label to focusable child controls for accessibility.
722+
// Also propagate to child EditorProperty nodes (e.g., wrapper -> inner property).
723+
if (!label.is_empty()) {
724+
for (Control *focusable : focusables) {
725+
focusable->set_accessibility_name(label);
726+
}
727+
// Propagate to child EditorProperty focusables.
728+
for (int i = 0; i < get_child_count(); i++) {
729+
EditorProperty *child_ep = Object::cast_to<EditorProperty>(get_child(i));
730+
if (child_ep && child_ep->get_label().is_empty()) {
731+
for (Control *focusable : child_ep->focusables) {
732+
focusable->set_accessibility_name(label);
733+
}
734+
}
735+
}
736+
}
718737
}
719738

720739
String EditorProperty::get_label() const {
@@ -978,6 +997,12 @@ void EditorProperty::_focusable_focused(int p_index) {
978997
void EditorProperty::add_focusable(Control *p_control) {
979998
p_control->connect(SceneStringName(focus_entered), callable_mp(this, &EditorProperty::_focusable_focused).bind(focusables.size()));
980999
focusables.push_back(p_control);
1000+
1001+
// If property has focusable children, make the property itself not focusable
1002+
// to avoid duplicate tab stops.
1003+
if (get_focus_mode() != FOCUS_NONE) {
1004+
set_focus_mode(FOCUS_NONE);
1005+
}
9811006
}
9821007

9831008
void EditorProperty::grab_focus(int p_focusable) {
@@ -5950,6 +5975,7 @@ EditorInspector::EditorInspector() {
59505975
property_focusable = -1;
59515976

59525977
get_v_scroll_bar()->connect(SceneStringName(value_changed), callable_mp(this, &EditorInspector::_vscroll_changed));
5978+
get_v_scroll_bar()->set_accessibility_name(TTRC("Properties"));
59535979
update_scroll_request = -1;
59545980
if (EditorSettings::get_singleton()) {
59555981
refresh_countdown = float(EDITOR_GET("docks/property_editor/auto_refresh_interval"));

editor/inspector/editor_sectioned_inspector.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,7 @@ SectionedInspector::SectionedInspector() :
367367
sections->set_v_size_flags(SIZE_EXPAND_FILL);
368368
sections->set_hide_root(true);
369369
sections->set_theme_type_variation("TreeSecondary");
370+
sections->set_accessibility_name(TTRC("Categories"));
370371

371372
left_vb->add_child(sections, true);
372373

editor/settings/editor_settings_dialog.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1141,6 +1141,9 @@ void EditorSettingsPropertyWrapper::setup(const String &p_property, EditorProper
11411141
editor_property = p_editor_property;
11421142
add_child(editor_property);
11431143

1144+
// Wrapper is not focusable - focus goes directly to the actual control.
1145+
set_focus_mode(FOCUS_NONE);
1146+
11441147
_update_override();
11451148

11461149
connect(SNAME("property_overridden"), callable_mp(this, &EditorSettingsPropertyWrapper::_create_override));
@@ -1169,7 +1172,9 @@ bool EditorSettingsInspectorPlugin::parse_property(Object *p_object, const Varia
11691172
real_property->set_name_split_ratio(0.0);
11701173
editor->setup(property, real_property, p_hint, p_hint_text, p_usage);
11711174

1172-
add_property_editor(p_path, editor);
1175+
// Generate label from property path for accessibility.
1176+
String label = EditorPropertyNameProcessor::get_singleton()->process_name(p_path, EditorPropertyNameProcessor::STYLE_CAPITALIZED, property, "");
1177+
add_property_editor(p_path, editor, false, label);
11731178
current_object = nullptr;
11741179
return true;
11751180
}

0 commit comments

Comments
 (0)