Skip to content

Commit 2b44f56

Browse files
author
Bianca Marina Stana
committed
Simplified the accessibility hierarchy
1 parent 4b62686 commit 2b44f56

File tree

4 files changed

+38
-149
lines changed

4 files changed

+38
-149
lines changed

Assets/Scripts/Screen Reader/AccessibilityManager.cs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -359,11 +359,7 @@ static void RemoveSubHierarchyForService(AccessibilityService service)
359359

360360
static void CreateSubHierarchyForService(AccessibilityService service)
361361
{
362-
var rootNode = hierarchy.AddNode(service.serviceName);
363-
rootNode.role = AccessibilityRole.Container;
364-
rootNode.isActive = Application.platform == RuntimePlatform.OSXPlayer; // false;
365-
366-
service.hierarchy = new AccessibilitySubHierarchy(hierarchy, rootNode);
362+
service.hierarchy = new AccessibilitySubHierarchy(hierarchy);
367363
}
368364

369365
static void GenerateSubHierarchyForService(Scene scene, AccessibilityService service)

Assets/Scripts/Screen Reader/AccessibilitySubHierarchy.cs

Lines changed: 30 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System.Collections.Generic;
12
using UnityEngine;
23
using UnityEngine.Accessibility;
34

@@ -17,7 +18,7 @@ public struct AccessibilitySubHierarchy
1718
/// <summary>
1819
/// Returns the node used as root for this sub-hierarchy.
1920
/// </summary>
20-
public AccessibilityNode rootNode { get; private set; }
21+
public List<AccessibilityNode> rootNodes { get; private set; }
2122

2223
/// <summary>
2324
/// Returns true if this sub-hierarchy is valid.
@@ -27,39 +28,31 @@ public struct AccessibilitySubHierarchy
2728
/// <summary>
2829
/// Constructs a sub-hierarchy from the specified hierarchy and root node.
2930
/// </summary>
30-
/// <param name="mainHierarchy"></param>
31-
/// <param name="rootNode"></param>
32-
public AccessibilitySubHierarchy(AccessibilityHierarchy mainHierarchy, AccessibilityNode rootNode)
31+
/// <param name="hierarchy"></param>
32+
public AccessibilitySubHierarchy(AccessibilityHierarchy hierarchy)
3333
{
34-
// Assert that the main hierarchy exists.
35-
if (mainHierarchy == null)
36-
{
37-
throw new System.ArgumentNullException(nameof(mainHierarchy), "The main hierarchy cannot be null.");
38-
}
39-
40-
// Assert that the root node belongs to the main hierarchy.
41-
if (rootNode != null && !mainHierarchy.ContainsNode(rootNode))
42-
{
43-
throw new System.ArgumentException("The root node must belong to the main hierarchy.", nameof(rootNode));
44-
}
45-
46-
// Note: if the root element is null then the sub-hierarchy represents the whole hierarchy.
47-
this.mainHierarchy = mainHierarchy;
48-
this.rootNode = rootNode;
34+
mainHierarchy = hierarchy ?? throw new System.ArgumentNullException(nameof(hierarchy), "The main hierarchy cannot be null.");
35+
rootNodes = new List<AccessibilityNode>();
4936
}
5037

5138
/// <summary>
5239
/// Disposes the sub-hierarchy removing the root node from the main hierarchy.
5340
/// </summary>
5441
public void Dispose()
5542
{
56-
if (mainHierarchy != null && rootNode != null && mainHierarchy.ContainsNode(rootNode))
43+
if (mainHierarchy != null)
5744
{
58-
mainHierarchy.RemoveNode(rootNode);
45+
foreach (var rootNode in rootNodes)
46+
{
47+
if (mainHierarchy.ContainsNode(rootNode))
48+
{
49+
mainHierarchy.RemoveNode(rootNode);
50+
}
51+
}
5952
}
6053

6154
mainHierarchy = null;
62-
rootNode = null;
55+
rootNodes?.Clear();
6356
}
6457

6558
/// <summary>
@@ -80,16 +73,16 @@ public bool ContainsNode(AccessibilityNode node)
8073
}
8174

8275
// We know the node is in the main hierarchy, now we need to check if it's part of this sub-hierarchy.
83-
var parentNode = node.parent;
76+
var currentNode = node;
8477

85-
while (parentNode != null)
78+
while (currentNode != null)
8679
{
87-
if (parentNode == rootNode)
80+
if (rootNodes.Contains(currentNode))
8881
{
8982
return true;
9083
}
9184

92-
parentNode = parentNode.parent;
85+
currentNode = currentNode.parent;
9386
}
9487

9588
return false;
@@ -159,9 +152,14 @@ public AccessibilityNode InsertNode(int childIndex, string label = null, Accessi
159152
return null;
160153
}
161154

162-
var actualParent = parent ?? rootNode;
155+
var node = mainHierarchy.InsertNode(childIndex, label, parent);
156+
157+
if (parent == null)
158+
{
159+
rootNodes.Add(node);
160+
}
163161

164-
return mainHierarchy.AddNode(label, actualParent);
162+
return node;
165163
}
166164

167165
/// <summary>
@@ -178,9 +176,7 @@ public bool MoveNode(AccessibilityNode node, AccessibilityNode newParent, int ne
178176
return false;
179177
}
180178

181-
var actualParent = newParent ?? rootNode;
182-
183-
return mainHierarchy.MoveNode(node, actualParent, newChildIndex);
179+
return mainHierarchy.MoveNode(node, newParent, newChildIndex);
184180
}
185181

186182
/// <summary>
@@ -203,12 +199,12 @@ public void RemoveNode(AccessibilityNode node, bool removeChildren = true)
203199
/// </summary>
204200
public void Clear()
205201
{
206-
if (rootNode != null)
202+
if (rootNodes is { Count: > 0 })
207203
{
208204
// Removes from the last to the first to avoid messing up the indices.
209-
for (var i = rootNode.children.Count - 1; i >= 0; i--)
205+
for (var i = rootNodes.Count - 1; i >= 0; i--)
210206
{
211-
mainHierarchy.RemoveNode(rootNode.children[i]);
207+
mainHierarchy.RemoveNode(rootNodes[i]);
212208
}
213209
}
214210
else

Assets/Scripts/Screen Reader/UITk/UITkAccessibilityService.cs

Lines changed: 0 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -27,51 +27,8 @@ public UITkAccessibilityService() : base("UITk", 100)
2727
AssistiveSupport.nodeFocusChanged += OnNodeFocusChanged;
2828
}
2929

30-
bool m_NeedsToRecomputeRootFrames;
31-
32-
public void DirtyRootFrames()
33-
{
34-
m_NeedsToRecomputeRootFrames = true;
35-
}
36-
37-
public void UpdateRootAndPanelFrames()
38-
{
39-
m_NeedsToRecomputeRootFrames = true;
40-
41-
foreach (var accessibilityUpdater in m_AccessibilityUpdaters)
42-
{
43-
accessibilityUpdater.UpdateRootFrame();
44-
}
45-
46-
var serviceRootFrame = Rect.zero;
47-
48-
foreach (var panelNode in hierarchy.rootNode.children)
49-
{
50-
// Calculate the union of all root nodes frames.
51-
if (panelNode.frame.size != Vector2.zero)
52-
{
53-
Encompass(ref serviceRootFrame, panelNode.frame);
54-
}
55-
}
56-
57-
hierarchy.rootNode.frame = serviceRootFrame;
58-
void Encompass(ref Rect a, Rect b)
59-
{
60-
a.xMin = Math.Min(a.xMin, b.xMin);
61-
a.yMin = Math.Min(a.yMin, b.yMin);
62-
a.xMax = Math.Max(a.xMax, b.xMax);
63-
a.yMax = Math.Max(a.yMax, b.yMax);
64-
}
65-
}
66-
6730
public override void Update()
6831
{
69-
if (m_NeedsToRecomputeRootFrames)
70-
{
71-
UpdateRootAndPanelFrames();
72-
m_NeedsToRecomputeRootFrames = false;
73-
}
74-
7532
foreach (var accessibilityUpdater in m_AccessibilityUpdaters)
7633
{
7734
accessibilityUpdater.Update();
@@ -170,11 +127,6 @@ public override void SetUp(Scene scene)
170127
}
171128

172129
var panel = uiDocument.runtimePanel;
173-
var rootAcc = uiDocument.rootVisualElement.GetOrCreateAccessibleProperties();
174-
175-
rootAcc.label = uiDocument.rootVisualElement.name;
176-
rootAcc.active = Application.platform == RuntimePlatform.OSXPlayer; // false;
177-
rootAcc.role = AccessibilityRole.Container;
178130

179131
if (!panels.Contains(panel))
180132
{

Assets/Scripts/Screen Reader/UITk/VisualTreeAccessibilityUpdater.cs

Lines changed: 7 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -34,24 +34,11 @@ enum NotificationType
3434
VisualElement m_VisualTree;
3535
IVisualElementScheduledItem m_UpdateJob;
3636
UITkAccessibilityService m_AccessibilityService;
37-
AccessibilitySubHierarchy m_SubHierarchy;
3837

3938
/// <summary>
4039
/// The sub-hierarchy this updater is managing.
4140
/// </summary>
42-
public AccessibilitySubHierarchy hierarchy
43-
{
44-
get => m_SubHierarchy;
45-
set
46-
{
47-
m_SubHierarchy = value;
48-
49-
if (m_SubHierarchy.isValid && visualTree != null)
50-
{
51-
DirtyRootFrame();
52-
}
53-
}
54-
}
41+
public AccessibilitySubHierarchy hierarchy { get; set; }
5542

5643
/// <summary>
5744
/// The panel of the visual tree being managed.
@@ -102,13 +89,10 @@ public VisualTreeAccessibilityUpdater(IPanel panel, VisualElement visualTree, UI
10289
m_AccessibilityService = service;
10390
visualTree.RegisterCallback<AttachToPanelEvent>(OnAttachmentToPanel);
10491
visualTree.RegisterCallback<GeometryChangedEvent>(OnGeometryChanged);
105-
106-
DirtyRootFrame();
10792
}
10893

10994
void OnGeometryChanged(GeometryChangedEvent evt)
11095
{
111-
DirtyRootFrame();
11296

11397
OnVersionChanged(evt.target as VisualElement, VersionChangeType.Size | VersionChangeType.Transform);
11498
}
@@ -411,19 +395,6 @@ void GetMinMaxY(Vector3[] vector, out float min, out float max)
411395
}
412396
}
413397

414-
void DirtyRootFrame()
415-
{
416-
m_AccessibilityService.DirtyRootFrames();
417-
}
418-
419-
public void UpdateRootFrame()
420-
{
421-
if (hierarchy.isValid)
422-
{
423-
hierarchy.rootNode.frame = GetScreenPosition(visualTree);
424-
}
425-
}
426-
427398
internal void UpdateNode(VisualElementAccessibilityHandler accElement)
428399
{
429400
if (!IsNodeValid(accElement.node))
@@ -503,30 +474,9 @@ public void Update()
503474
Update(visualTree);
504475
}
505476

506-
string GetPanelName(VisualElement ve)
507-
{
508-
// Try to get the name of the panel using reflection.
509-
var panel = ve.panel;
510-
511-
if (panel == null)
512-
{
513-
return null;
514-
}
515-
516-
var panelType = panel.GetType();
517-
var nameProperty = panelType.GetProperty("name");
518-
519-
if (nameProperty != null)
520-
{
521-
return nameProperty.GetValue(panel, null) as string;
522-
}
523-
524-
return null;
525-
}
526-
527477
NotificationType m_Notification = NotificationType.None;
528478

529-
void Update(VisualElement visualTree)
479+
void Update(VisualElement ve)
530480
{
531481
var shouldSendNotification = false;
532482

@@ -538,13 +488,8 @@ void Update(VisualElement visualTree)
538488
{
539489
if (!hierarchy.isValid)
540490
{
541-
var panelName = GetPanelName(visualTree);
542-
var rootNode = m_AccessibilityService.hierarchy.AddNode(string.IsNullOrEmpty(panelName) ?
543-
visualTree.name : panelName);
544-
rootNode.role = AccessibilityRole.Container;
545-
rootNode.isActive = Application.platform == RuntimePlatform.OSXPlayer;
546-
hierarchy = new AccessibilitySubHierarchy(m_AccessibilityService.hierarchy.mainHierarchy, rootNode);
547-
DirtyRootFrame();
491+
hierarchy = new AccessibilitySubHierarchy(m_AccessibilityService.hierarchy.mainHierarchy);
492+
548493
shouldSendNotification = true;
549494
}
550495

@@ -553,7 +498,7 @@ void Update(VisualElement visualTree)
553498

554499
var modalElement = currentModalElement;
555500

556-
UpdateAccessibilityHierarchyRecursively(visualTree, null, false, true);
501+
UpdateAccessibilityHierarchyRecursively(ve, null, false, true);
557502

558503
// If there is a current modal element or if the current model element has changed then update the
559504
// active state of all nodes.
@@ -565,11 +510,11 @@ void Update(VisualElement visualTree)
565510

566511
if (shouldSendNotification || m_Notification.HasFlag(NotificationType.ScreenChanged))
567512
{
568-
visualTree.schedule.Execute(() => AssistiveSupport.notificationDispatcher.SendScreenChanged());
513+
ve.schedule.Execute(() => AssistiveSupport.notificationDispatcher.SendScreenChanged());
569514
}
570515
else if (m_Notification.HasFlag(NotificationType.LayoutChanged))
571516
{
572-
visualTree.schedule.Execute(() => AssistiveSupport.notificationDispatcher.SendLayoutChanged());
517+
ve.schedule.Execute(() => AssistiveSupport.notificationDispatcher.SendLayoutChanged());
573518
}
574519
}
575520

0 commit comments

Comments
 (0)