Making Control node focusable by screenreader

Godot Version

4.7 rc3

Question

We’re trying to make a game accessible to screenreaders. The navigation tools of the screenreader use Godot’s node tree, analogous to how they would read a web page.

For nodes like buttons, this works fine.

Containers are normally ignored, but 4.7 adds the property accessibility_region, which can be set to override this. Great!

Our problem is that we have some nodes that are children of a Control instead of a Container. (Why? It’s a grid of hexagons, so they have specific placements. Any container would rearrange them.)

The Control is ignored by the screenreader’s navigation, but doesn’t have accessibility_region.

How can we make this focusable for the screenreader? Is there a different kind of container node we should use?

There are three solutions I can think of, keeping in mind I’ve never tried to implement screen reading in Godot. (Props to you for doing that.)

  1. Make a request for a new feature in Godot Proposals to add this to Control nodes.
  2. You might also check the merged ticket and contact the implementor. From context it sounds like this is a person who uses the feature themselves, and might be able to help you figure out how to use it effectively.
  3. Inherit the Container class and override the fit_child_in_rect() to handle your hexagons.

I’ve not tested it but you can use AccessibilityServer.update_set_role() using Node.get_accessibility_element() to get its RID and AccessibilityRole.ROLE_REGION. You need to do it in the Object._notification() callback when what is NOTIFICATION_ACCESSIBILITY_UPDATE like:

extends Control


func _notification(what: int) -> void:
    if what == NOTIFICATION_ACCESSIBILITY_UPDATE:
        var rid = get_accessibility_element()
        AccessibilityServer.update_set_role(rid, AccessibilityServer.ROLE_REGION)

This is how the Container does it:

I tried dragonforge-dev’s option 3, as it seemed simplest.

I did this by attaching a script to my Control (which is called grid) and then changing the type of gridto Container. Here’s the script:

extends Container

func fit_child_in_rect(Control, Rect2):
	pass

Godot says:

Parser Error: The method "fit_child_in_rect()" overrides a method from native class "Container". This won't be called by the engine and may not work as expected. (Warning treated as error.)

Since it’s treated as an error, it won’t run.

Was this the right way of doing this?

That’s what I suggested, but apparently according to the documentation, you do it for waiting for the notification and doing something: