Base accessibility API.
This commit is contained in:
@ -499,9 +499,11 @@ void PopupMenu::_input_from_window_internal(const Ref<InputEvent> &p_event) {
|
||||
bool match_found = false;
|
||||
for (int i = search_from; i < items.size(); i++) {
|
||||
if (!items[i].separator && !items[i].disabled) {
|
||||
prev_mouse_over = mouse_over;
|
||||
mouse_over = i;
|
||||
emit_signal(SNAME("id_focused"), items[i].id);
|
||||
scroll_to_item(i);
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
set_input_as_handled();
|
||||
match_found = true;
|
||||
@ -513,9 +515,11 @@ void PopupMenu::_input_from_window_internal(const Ref<InputEvent> &p_event) {
|
||||
// If the last item is not selectable, try re-searching from the start.
|
||||
for (int i = 0; i < search_from; i++) {
|
||||
if (!items[i].separator && !items[i].disabled) {
|
||||
prev_mouse_over = mouse_over;
|
||||
mouse_over = i;
|
||||
emit_signal(SNAME("id_focused"), items[i].id);
|
||||
scroll_to_item(i);
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
set_input_as_handled();
|
||||
break;
|
||||
@ -537,9 +541,11 @@ void PopupMenu::_input_from_window_internal(const Ref<InputEvent> &p_event) {
|
||||
bool match_found = false;
|
||||
for (int i = search_from; i >= 0; i--) {
|
||||
if (!items[i].separator && !items[i].disabled) {
|
||||
prev_mouse_over = mouse_over;
|
||||
mouse_over = i;
|
||||
emit_signal(SNAME("id_focused"), items[i].id);
|
||||
scroll_to_item(i);
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
set_input_as_handled();
|
||||
match_found = true;
|
||||
@ -551,9 +557,11 @@ void PopupMenu::_input_from_window_internal(const Ref<InputEvent> &p_event) {
|
||||
// If the first item is not selectable, try re-searching from the end.
|
||||
for (int i = items.size() - 1; i >= search_from; i--) {
|
||||
if (!items[i].separator && !items[i].disabled) {
|
||||
prev_mouse_over = mouse_over;
|
||||
mouse_over = i;
|
||||
emit_signal(SNAME("id_focused"), items[i].id);
|
||||
scroll_to_item(i);
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
set_input_as_handled();
|
||||
break;
|
||||
@ -738,9 +746,11 @@ void PopupMenu::_input_from_window_internal(const Ref<InputEvent> &p_event) {
|
||||
}
|
||||
|
||||
if (items[i].text.findn(search_string) == 0) {
|
||||
prev_mouse_over = mouse_over;
|
||||
mouse_over = i;
|
||||
emit_signal(SNAME("id_focused"), items[i].id);
|
||||
scroll_to_item(i);
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
set_input_as_handled();
|
||||
break;
|
||||
@ -755,6 +765,7 @@ void PopupMenu::_mouse_over_update(const Point2 &p_over) {
|
||||
|
||||
if (id < 0) {
|
||||
mouse_over = -1;
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
return;
|
||||
}
|
||||
@ -766,6 +777,7 @@ void PopupMenu::_mouse_over_update(const Point2 &p_over) {
|
||||
|
||||
if (over != mouse_over) {
|
||||
mouse_over = over;
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
}
|
||||
}
|
||||
@ -1104,8 +1116,105 @@ void PopupMenu::remove_child_notify(Node *p_child) {
|
||||
_menu_changed();
|
||||
}
|
||||
|
||||
void PopupMenu::_accessibility_action_click(const Variant &p_data, int p_idx) {
|
||||
activate_item(p_idx);
|
||||
}
|
||||
|
||||
RID PopupMenu::get_focused_accessibility_element() const {
|
||||
if (mouse_over == -1) {
|
||||
return get_accessibility_element();
|
||||
} else {
|
||||
const Item &item = items[mouse_over];
|
||||
return item.accessibility_item_element;
|
||||
}
|
||||
}
|
||||
|
||||
void PopupMenu::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_EXIT_TREE: {
|
||||
if (system_menu_id != NativeMenu::INVALID_MENU_ID) {
|
||||
unbind_global_menu();
|
||||
}
|
||||
[[fallthrough]];
|
||||
}
|
||||
|
||||
case NOTIFICATION_ACCESSIBILITY_INVALIDATE: {
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
items.write[i].accessibility_item_element = RID();
|
||||
}
|
||||
accessibility_scroll_element = RID();
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_ACCESSIBILITY_UPDATE: {
|
||||
RID ae = get_accessibility_element();
|
||||
ERR_FAIL_COND(ae.is_null());
|
||||
|
||||
if (has_meta("_menu_name")) {
|
||||
DisplayServer::get_singleton()->accessibility_update_set_name(ae, get_meta("_menu_name", get_name()));
|
||||
}
|
||||
DisplayServer::get_singleton()->accessibility_update_set_role(ae, DisplayServer::AccessibilityRole::ROLE_MENU);
|
||||
DisplayServer::get_singleton()->accessibility_update_set_list_item_count(ae, items.size());
|
||||
|
||||
if (accessibility_scroll_element.is_null()) {
|
||||
accessibility_scroll_element = DisplayServer::get_singleton()->accessibility_create_sub_element(ae, DisplayServer::AccessibilityRole::ROLE_CONTAINER);
|
||||
}
|
||||
|
||||
Transform2D scroll_xform;
|
||||
scroll_xform.set_origin(Vector2i(0, -scroll_container->get_v_scroll_bar()->get_value()));
|
||||
DisplayServer::get_singleton()->accessibility_update_set_transform(accessibility_scroll_element, scroll_xform);
|
||||
DisplayServer::get_singleton()->accessibility_update_set_bounds(accessibility_scroll_element, Rect2(0, 0, get_size().x, scroll_container->get_v_scroll_bar()->get_max()));
|
||||
|
||||
float scroll_width = scroll_container->get_v_scroll_bar()->is_visible_in_tree() ? scroll_container->get_v_scroll_bar()->get_size().width : 0;
|
||||
float display_width = control->get_size().width - scroll_width;
|
||||
Point2 ofs;
|
||||
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
const Item &item = items.write[i];
|
||||
|
||||
ofs.y += i > 0 ? theme_cache.v_separation : (float)theme_cache.v_separation / 2;
|
||||
|
||||
Point2 item_ofs = ofs;
|
||||
if (item.accessibility_item_element.is_null()) {
|
||||
item.accessibility_item_element = DisplayServer::get_singleton()->accessibility_create_sub_element(accessibility_scroll_element, DisplayServer::AccessibilityRole::ROLE_MENU_ITEM);
|
||||
item.accessibility_item_dirty = true;
|
||||
}
|
||||
|
||||
item_ofs.x += item.indent * theme_cache.indent;
|
||||
float h = _get_item_height(i);
|
||||
|
||||
if (item.accessibility_item_dirty || i == prev_mouse_over || i == mouse_over) {
|
||||
switch (item.checkable_type) {
|
||||
case Item::CHECKABLE_TYPE_NONE: {
|
||||
DisplayServer::get_singleton()->accessibility_update_set_role(item.accessibility_item_element, DisplayServer::AccessibilityRole::ROLE_MENU_ITEM);
|
||||
} break;
|
||||
case Item::CHECKABLE_TYPE_CHECK_BOX: {
|
||||
DisplayServer::get_singleton()->accessibility_update_set_role(item.accessibility_item_element, DisplayServer::AccessibilityRole::ROLE_MENU_ITEM_CHECK_BOX);
|
||||
DisplayServer::get_singleton()->accessibility_update_set_checked(item.accessibility_item_element, item.checked);
|
||||
} break;
|
||||
case Item::CHECKABLE_TYPE_RADIO_BUTTON: {
|
||||
DisplayServer::get_singleton()->accessibility_update_set_role(item.accessibility_item_element, DisplayServer::AccessibilityRole::ROLE_MENU_ITEM_RADIO);
|
||||
DisplayServer::get_singleton()->accessibility_update_set_checked(item.accessibility_item_element, item.checked);
|
||||
} break;
|
||||
}
|
||||
|
||||
DisplayServer::get_singleton()->accessibility_update_add_action(item.accessibility_item_element, DisplayServer::AccessibilityAction::ACTION_CLICK, callable_mp(this, &PopupMenu::_accessibility_action_click).bind(i));
|
||||
DisplayServer::get_singleton()->accessibility_update_set_list_item_index(item.accessibility_item_element, i);
|
||||
DisplayServer::get_singleton()->accessibility_update_set_list_item_level(item.accessibility_item_element, 0);
|
||||
DisplayServer::get_singleton()->accessibility_update_set_list_item_selected(item.accessibility_item_element, i == mouse_over);
|
||||
DisplayServer::get_singleton()->accessibility_update_set_name(item.accessibility_item_element, item.xl_text);
|
||||
DisplayServer::get_singleton()->accessibility_update_set_flag(item.accessibility_item_element, DisplayServer::AccessibilityFlags::FLAG_DISABLED, item.disabled);
|
||||
DisplayServer::get_singleton()->accessibility_update_set_tooltip(item.accessibility_item_element, item.tooltip);
|
||||
|
||||
DisplayServer::get_singleton()->accessibility_update_set_bounds(item.accessibility_item_element, Rect2(item_ofs, Size2(display_width, h + theme_cache.v_separation)));
|
||||
|
||||
item.accessibility_item_dirty = false;
|
||||
}
|
||||
ofs.y += h;
|
||||
}
|
||||
prev_mouse_over = -1;
|
||||
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_ENTER_TREE: {
|
||||
PopupMenu *pm = Object::cast_to<PopupMenu>(get_parent());
|
||||
if (pm) {
|
||||
@ -1118,12 +1227,6 @@ void PopupMenu::_notification(int p_what) {
|
||||
}
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_EXIT_TREE: {
|
||||
if (system_menu_id != NativeMenu::INVALID_MENU_ID) {
|
||||
unbind_global_menu();
|
||||
}
|
||||
} break;
|
||||
|
||||
case Control::NOTIFICATION_LAYOUT_DIRECTION_CHANGED:
|
||||
case NOTIFICATION_THEME_CHANGED: {
|
||||
panel->add_theme_style_override(SceneStringName(panel), theme_cache.panel_style);
|
||||
@ -1151,7 +1254,9 @@ void PopupMenu::_notification(int p_what) {
|
||||
if (is_global) {
|
||||
nmenu->set_item_text(global_menu, i, item.xl_text);
|
||||
}
|
||||
item.accessibility_item_dirty = true;
|
||||
_shape_item(i);
|
||||
queue_accessibility_update();
|
||||
}
|
||||
|
||||
child_controls_changed();
|
||||
@ -1166,6 +1271,7 @@ void PopupMenu::_notification(int p_what) {
|
||||
case NOTIFICATION_WM_MOUSE_EXIT: {
|
||||
if (mouse_over >= 0 && (!items[mouse_over].submenu || submenu_over != -1)) {
|
||||
mouse_over = -1;
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
}
|
||||
} break;
|
||||
@ -1281,7 +1387,9 @@ void PopupMenu::_notification(int p_what) {
|
||||
case NOTIFICATION_VISIBILITY_CHANGED: {
|
||||
if (!is_visible()) {
|
||||
if (mouse_over >= 0) {
|
||||
prev_mouse_over = mouse_over;
|
||||
mouse_over = -1;
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
}
|
||||
|
||||
@ -1341,6 +1449,7 @@ void PopupMenu::add_item(const String &p_label, int p_id, Key p_accel) {
|
||||
}
|
||||
|
||||
_shape_item(items.size() - 1);
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
|
||||
child_controls_changed();
|
||||
@ -1364,6 +1473,7 @@ void PopupMenu::add_icon_item(const Ref<Texture2D> &p_icon, const String &p_labe
|
||||
}
|
||||
|
||||
_shape_item(items.size() - 1);
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
|
||||
child_controls_changed();
|
||||
@ -1387,6 +1497,7 @@ void PopupMenu::add_check_item(const String &p_label, int p_id, Key p_accel) {
|
||||
}
|
||||
|
||||
_shape_item(items.size() - 1);
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
|
||||
child_controls_changed();
|
||||
@ -1412,6 +1523,7 @@ void PopupMenu::add_icon_check_item(const Ref<Texture2D> &p_icon, const String &
|
||||
}
|
||||
|
||||
_shape_item(items.size() - 1);
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
|
||||
child_controls_changed();
|
||||
@ -1435,6 +1547,7 @@ void PopupMenu::add_radio_check_item(const String &p_label, int p_id, Key p_acce
|
||||
}
|
||||
|
||||
_shape_item(items.size() - 1);
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
|
||||
child_controls_changed();
|
||||
@ -1460,6 +1573,7 @@ void PopupMenu::add_icon_radio_check_item(const Ref<Texture2D> &p_icon, const St
|
||||
}
|
||||
|
||||
_shape_item(items.size() - 1);
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
|
||||
child_controls_changed();
|
||||
@ -1485,6 +1599,7 @@ void PopupMenu::add_multistate_item(const String &p_label, int p_max_states, int
|
||||
}
|
||||
|
||||
_shape_item(items.size() - 1);
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
|
||||
child_controls_changed();
|
||||
@ -1522,6 +1637,7 @@ void PopupMenu::add_shortcut(const Ref<Shortcut> &p_shortcut, int p_id, bool p_g
|
||||
}
|
||||
|
||||
_shape_item(items.size() - 1);
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
|
||||
child_controls_changed();
|
||||
@ -1551,6 +1667,7 @@ void PopupMenu::add_icon_shortcut(const Ref<Texture2D> &p_icon, const Ref<Shortc
|
||||
}
|
||||
|
||||
_shape_item(items.size() - 1);
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
|
||||
child_controls_changed();
|
||||
@ -1580,6 +1697,7 @@ void PopupMenu::add_check_shortcut(const Ref<Shortcut> &p_shortcut, int p_id, bo
|
||||
}
|
||||
|
||||
_shape_item(items.size() - 1);
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
|
||||
child_controls_changed();
|
||||
@ -1611,6 +1729,7 @@ void PopupMenu::add_icon_check_shortcut(const Ref<Texture2D> &p_icon, const Ref<
|
||||
}
|
||||
|
||||
_shape_item(items.size() - 1);
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
|
||||
child_controls_changed();
|
||||
@ -1640,6 +1759,7 @@ void PopupMenu::add_radio_check_shortcut(const Ref<Shortcut> &p_shortcut, int p_
|
||||
}
|
||||
|
||||
_shape_item(items.size() - 1);
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
|
||||
child_controls_changed();
|
||||
@ -1671,6 +1791,7 @@ void PopupMenu::add_icon_radio_check_shortcut(const Ref<Texture2D> &p_icon, cons
|
||||
}
|
||||
|
||||
_shape_item(items.size() - 1);
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
|
||||
child_controls_changed();
|
||||
@ -1697,6 +1818,7 @@ void PopupMenu::add_submenu_node_item(const String &p_label, PopupMenu *p_submen
|
||||
item.text = p_label;
|
||||
item.xl_text = atr(p_label);
|
||||
item.id = p_id == -1 ? items.size() : p_id;
|
||||
item.accessibility_item_dirty = true;
|
||||
item.submenu = p_submenu;
|
||||
item.submenu_name = p_submenu->get_name();
|
||||
items.push_back(item);
|
||||
@ -1710,6 +1832,7 @@ void PopupMenu::add_submenu_node_item(const String &p_label, PopupMenu *p_submen
|
||||
}
|
||||
|
||||
_shape_item(items.size() - 1);
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
|
||||
child_controls_changed();
|
||||
@ -1733,13 +1856,16 @@ void PopupMenu::set_item_text(int p_idx, const String &p_text) {
|
||||
items.write[p_idx].text = p_text;
|
||||
items.write[p_idx].xl_text = _atr(p_idx, p_text);
|
||||
items.write[p_idx].dirty = true;
|
||||
items.write[p_idx].accessibility_item_dirty = true;
|
||||
|
||||
if (global_menu.is_valid()) {
|
||||
NativeMenu::get_singleton()->set_item_text(global_menu, p_idx, items[p_idx].xl_text);
|
||||
}
|
||||
_shape_item(p_idx);
|
||||
|
||||
_shape_item(p_idx);
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
|
||||
child_controls_changed();
|
||||
_menu_changed();
|
||||
}
|
||||
@ -1750,9 +1876,14 @@ void PopupMenu::set_item_text_direction(int p_idx, Control::TextDirection p_text
|
||||
}
|
||||
ERR_FAIL_INDEX(p_idx, items.size());
|
||||
ERR_FAIL_COND((int)p_text_direction < -1 || (int)p_text_direction > 3);
|
||||
|
||||
if (items[p_idx].text_direction != p_text_direction) {
|
||||
items.write[p_idx].text_direction = p_text_direction;
|
||||
items.write[p_idx].dirty = true;
|
||||
items.write[p_idx].accessibility_item_dirty = true;
|
||||
|
||||
_shape_item(p_idx);
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
}
|
||||
}
|
||||
@ -1765,6 +1896,10 @@ void PopupMenu::set_item_language(int p_idx, const String &p_language) {
|
||||
if (items[p_idx].language != p_language) {
|
||||
items.write[p_idx].language = p_language;
|
||||
items.write[p_idx].dirty = true;
|
||||
items.write[p_idx].accessibility_item_dirty = true;
|
||||
|
||||
_shape_item(p_idx);
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
}
|
||||
}
|
||||
@ -1846,11 +1981,13 @@ void PopupMenu::set_item_checked(int p_idx, bool p_checked) {
|
||||
}
|
||||
|
||||
items.write[p_idx].checked = p_checked;
|
||||
items.write[p_idx].accessibility_item_dirty = true;
|
||||
|
||||
if (global_menu.is_valid()) {
|
||||
NativeMenu::get_singleton()->set_item_checked(global_menu, p_idx, p_checked);
|
||||
}
|
||||
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
child_controls_changed();
|
||||
_menu_changed();
|
||||
@ -1889,11 +2026,13 @@ void PopupMenu::set_item_accelerator(int p_idx, Key p_accel) {
|
||||
|
||||
items.write[p_idx].accel = p_accel;
|
||||
items.write[p_idx].dirty = true;
|
||||
items.write[p_idx].accessibility_item_dirty = true;
|
||||
|
||||
if (global_menu.is_valid()) {
|
||||
NativeMenu::get_singleton()->set_item_accelerator(global_menu, p_idx, p_accel);
|
||||
}
|
||||
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
child_controls_changed();
|
||||
_menu_changed();
|
||||
@ -1925,11 +2064,13 @@ void PopupMenu::set_item_disabled(int p_idx, bool p_disabled) {
|
||||
}
|
||||
|
||||
items.write[p_idx].disabled = p_disabled;
|
||||
items.write[p_idx].accessibility_item_dirty = true;
|
||||
|
||||
if (global_menu.is_valid()) {
|
||||
NativeMenu::get_singleton()->set_item_disabled(global_menu, p_idx, p_disabled);
|
||||
}
|
||||
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
child_controls_changed();
|
||||
_menu_changed();
|
||||
@ -1993,11 +2134,13 @@ void PopupMenu::set_item_submenu_node(int p_idx, PopupMenu *p_submenu) {
|
||||
void PopupMenu::toggle_item_checked(int p_idx) {
|
||||
ERR_FAIL_INDEX(p_idx, items.size());
|
||||
items.write[p_idx].checked = !items[p_idx].checked;
|
||||
items.write[p_idx].accessibility_item_dirty = true;
|
||||
|
||||
if (global_menu.is_valid()) {
|
||||
NativeMenu::get_singleton()->set_item_checked(global_menu, p_idx, items[p_idx].checked);
|
||||
}
|
||||
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
child_controls_changed();
|
||||
_menu_changed();
|
||||
@ -2134,6 +2277,9 @@ void PopupMenu::set_item_as_separator(int p_idx, bool p_separator) {
|
||||
}
|
||||
|
||||
items.write[p_idx].separator = p_separator;
|
||||
items.write[p_idx].accessibility_item_dirty = true;
|
||||
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
}
|
||||
|
||||
@ -2154,11 +2300,13 @@ void PopupMenu::set_item_as_checkable(int p_idx, bool p_checkable) {
|
||||
}
|
||||
|
||||
items.write[p_idx].checkable_type = p_checkable ? Item::CHECKABLE_TYPE_CHECK_BOX : Item::CHECKABLE_TYPE_NONE;
|
||||
items.write[p_idx].accessibility_item_dirty = true;
|
||||
|
||||
if (global_menu.is_valid()) {
|
||||
NativeMenu::get_singleton()->set_item_checkable(global_menu, p_idx, p_checkable);
|
||||
}
|
||||
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
_menu_changed();
|
||||
}
|
||||
@ -2175,11 +2323,13 @@ void PopupMenu::set_item_as_radio_checkable(int p_idx, bool p_radio_checkable) {
|
||||
}
|
||||
|
||||
items.write[p_idx].checkable_type = p_radio_checkable ? Item::CHECKABLE_TYPE_RADIO_BUTTON : Item::CHECKABLE_TYPE_NONE;
|
||||
items.write[p_idx].accessibility_item_dirty = true;
|
||||
|
||||
if (global_menu.is_valid()) {
|
||||
NativeMenu::get_singleton()->set_item_radio_checkable(global_menu, p_idx, p_radio_checkable);
|
||||
}
|
||||
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
_menu_changed();
|
||||
}
|
||||
@ -2195,11 +2345,13 @@ void PopupMenu::set_item_tooltip(int p_idx, const String &p_tooltip) {
|
||||
}
|
||||
|
||||
items.write[p_idx].tooltip = p_tooltip;
|
||||
items.write[p_idx].accessibility_item_dirty = true;
|
||||
|
||||
if (global_menu.is_valid()) {
|
||||
NativeMenu::get_singleton()->set_item_tooltip(global_menu, p_idx, p_tooltip);
|
||||
}
|
||||
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
_menu_changed();
|
||||
}
|
||||
@ -2299,11 +2451,13 @@ void PopupMenu::set_item_multistate(int p_idx, int p_state) {
|
||||
}
|
||||
|
||||
items.write[p_idx].state = p_state;
|
||||
items.write[p_idx].accessibility_item_dirty = true;
|
||||
|
||||
if (global_menu.is_valid()) {
|
||||
NativeMenu::get_singleton()->set_item_state(global_menu, p_idx, p_state);
|
||||
}
|
||||
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
_menu_changed();
|
||||
}
|
||||
@ -2348,11 +2502,13 @@ void PopupMenu::toggle_item_multistate(int p_idx) {
|
||||
if (items.write[p_idx].max_states <= items[p_idx].state) {
|
||||
items.write[p_idx].state = 0;
|
||||
}
|
||||
items.write[p_idx].accessibility_item_dirty = true;
|
||||
|
||||
if (global_menu.is_valid()) {
|
||||
NativeMenu::get_singleton()->set_item_state(global_menu, p_idx, items[p_idx].state);
|
||||
}
|
||||
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
_menu_changed();
|
||||
}
|
||||
@ -2386,11 +2542,12 @@ void PopupMenu::set_focused_item(int p_idx) {
|
||||
return;
|
||||
}
|
||||
|
||||
prev_mouse_over = mouse_over;
|
||||
mouse_over = p_idx;
|
||||
if (mouse_over != -1) {
|
||||
scroll_to_item(mouse_over);
|
||||
}
|
||||
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
}
|
||||
|
||||
@ -2412,6 +2569,10 @@ void PopupMenu::set_item_count(int p_count) {
|
||||
if (is_global && prev_size > p_count) {
|
||||
for (int i = prev_size - 1; i >= p_count; i--) {
|
||||
nmenu->remove_item(global_menu, i);
|
||||
if (items[i].accessibility_item_element.is_valid()) {
|
||||
DisplayServer::get_singleton()->accessibility_free_element(items.write[i].accessibility_item_element);
|
||||
items.write[i].accessibility_item_element = RID();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2592,6 +2753,10 @@ void PopupMenu::activate_item(int p_idx) {
|
||||
void PopupMenu::remove_item(int p_idx) {
|
||||
ERR_FAIL_INDEX(p_idx, items.size());
|
||||
|
||||
if (items[p_idx].accessibility_item_element.is_valid()) {
|
||||
DisplayServer::get_singleton()->accessibility_free_element(items.write[p_idx].accessibility_item_element);
|
||||
items.write[p_idx].accessibility_item_element = RID();
|
||||
}
|
||||
if (items[p_idx].shortcut.is_valid()) {
|
||||
_unref_shortcut(items[p_idx].shortcut);
|
||||
}
|
||||
@ -2611,6 +2776,7 @@ void PopupMenu::add_separator(const String &p_text, int p_id) {
|
||||
Item sep;
|
||||
sep.separator = true;
|
||||
sep.id = p_id;
|
||||
sep.accessibility_item_dirty = true;
|
||||
if (!p_text.is_empty()) {
|
||||
sep.text = p_text;
|
||||
sep.xl_text = atr(p_text);
|
||||
@ -2626,7 +2792,11 @@ void PopupMenu::add_separator(const String &p_text, int p_id) {
|
||||
}
|
||||
|
||||
void PopupMenu::clear(bool p_free_submenus) {
|
||||
for (const Item &I : items) {
|
||||
for (Item &I : items) {
|
||||
if (I.accessibility_item_element.is_valid()) {
|
||||
DisplayServer::get_singleton()->accessibility_free_element(I.accessibility_item_element);
|
||||
I.accessibility_item_element = RID();
|
||||
}
|
||||
if (I.shortcut.is_valid()) {
|
||||
_unref_shortcut(I.shortcut);
|
||||
}
|
||||
@ -2650,7 +2820,9 @@ void PopupMenu::clear(bool p_free_submenus) {
|
||||
}
|
||||
items.clear();
|
||||
|
||||
prev_mouse_over = -1;
|
||||
mouse_over = -1;
|
||||
queue_accessibility_update();
|
||||
control->queue_redraw();
|
||||
child_controls_changed();
|
||||
notify_property_list_changed();
|
||||
@ -3032,7 +3204,15 @@ void PopupMenu::popup(const Rect2i &p_bounds) {
|
||||
if (native) {
|
||||
_native_popup(p_bounds != Rect2i() ? p_bounds : Rect2i(get_position(), Size2i()));
|
||||
} else {
|
||||
set_flag(FLAG_NO_FOCUS, !is_embedded());
|
||||
if (is_inside_tree()) {
|
||||
bool ac = get_tree()->is_accessibility_enabled();
|
||||
// Note: Native popup menus need keyboard focus to work with screen reader.
|
||||
set_flag(FLAG_POPUP, !ac);
|
||||
set_flag(FLAG_NO_FOCUS, !is_embedded() && !ac);
|
||||
if (ac) {
|
||||
set_ac_popup();
|
||||
}
|
||||
}
|
||||
|
||||
moved = Vector2();
|
||||
popup_time_msec = OS::get_singleton()->get_ticks_msec();
|
||||
@ -3065,7 +3245,15 @@ void PopupMenu::set_visible(bool p_visible) {
|
||||
_native_popup(Rect2i(get_position(), get_size()));
|
||||
}
|
||||
} else {
|
||||
set_flag(FLAG_NO_FOCUS, !is_embedded());
|
||||
if (is_inside_tree()) {
|
||||
bool ac = get_tree()->is_accessibility_enabled();
|
||||
// Note: Native popup menus need keyboard focus to work with screen reader.
|
||||
set_flag(FLAG_POPUP, !ac);
|
||||
set_flag(FLAG_NO_FOCUS, !is_embedded() && !ac);
|
||||
if (ac) {
|
||||
set_ac_popup();
|
||||
}
|
||||
}
|
||||
|
||||
Popup::set_visible(p_visible);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user