diff --git a/Assets/Scripts/Screen Reader/AccessibilityManager.cs b/Assets/Scripts/Screen Reader/AccessibilityManager.cs index 4958891..fa82962 100644 --- a/Assets/Scripts/Screen Reader/AccessibilityManager.cs +++ b/Assets/Scripts/Screen Reader/AccessibilityManager.cs @@ -359,11 +359,7 @@ static void RemoveSubHierarchyForService(AccessibilityService service) static void CreateSubHierarchyForService(AccessibilityService service) { - var rootNode = hierarchy.AddNode(service.serviceName); - rootNode.role = AccessibilityRole.Container; - rootNode.isActive = Application.platform == RuntimePlatform.OSXPlayer; // false; - - service.hierarchy = new AccessibilitySubHierarchy(hierarchy, rootNode); + service.hierarchy = new AccessibilitySubHierarchy(hierarchy); } static void GenerateSubHierarchyForService(Scene scene, AccessibilityService service) diff --git a/Assets/Scripts/Screen Reader/AccessibilitySubHierarchy.cs b/Assets/Scripts/Screen Reader/AccessibilitySubHierarchy.cs index f82c4d6..e21ca25 100644 --- a/Assets/Scripts/Screen Reader/AccessibilitySubHierarchy.cs +++ b/Assets/Scripts/Screen Reader/AccessibilitySubHierarchy.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; using UnityEngine; using UnityEngine.Accessibility; @@ -17,7 +18,7 @@ public struct AccessibilitySubHierarchy /// /// Returns the node used as root for this sub-hierarchy. /// - public AccessibilityNode rootNode { get; private set; } + public List rootNodes { get; private set; } /// /// Returns true if this sub-hierarchy is valid. @@ -27,25 +28,11 @@ public struct AccessibilitySubHierarchy /// /// Constructs a sub-hierarchy from the specified hierarchy and root node. /// - /// - /// - public AccessibilitySubHierarchy(AccessibilityHierarchy mainHierarchy, AccessibilityNode rootNode) + /// + public AccessibilitySubHierarchy(AccessibilityHierarchy hierarchy) { - // Assert that the main hierarchy exists. - if (mainHierarchy == null) - { - throw new System.ArgumentNullException(nameof(mainHierarchy), "The main hierarchy cannot be null."); - } - - // Assert that the root node belongs to the main hierarchy. - if (rootNode != null && !mainHierarchy.ContainsNode(rootNode)) - { - throw new System.ArgumentException("The root node must belong to the main hierarchy.", nameof(rootNode)); - } - - // Note: if the root element is null then the sub-hierarchy represents the whole hierarchy. - this.mainHierarchy = mainHierarchy; - this.rootNode = rootNode; + mainHierarchy = hierarchy ?? throw new System.ArgumentNullException(nameof(hierarchy), "The main hierarchy cannot be null."); + rootNodes = new List(); } /// @@ -53,13 +40,19 @@ public AccessibilitySubHierarchy(AccessibilityHierarchy mainHierarchy, Accessibi /// public void Dispose() { - if (mainHierarchy != null && rootNode != null && mainHierarchy.ContainsNode(rootNode)) + if (mainHierarchy != null) { - mainHierarchy.RemoveNode(rootNode); + foreach (var rootNode in rootNodes) + { + if (mainHierarchy.ContainsNode(rootNode)) + { + mainHierarchy.RemoveNode(rootNode); + } + } } mainHierarchy = null; - rootNode = null; + rootNodes?.Clear(); } /// @@ -80,16 +73,16 @@ public bool ContainsNode(AccessibilityNode node) } // We know the node is in the main hierarchy, now we need to check if it's part of this sub-hierarchy. - var parentNode = node.parent; + var currentNode = node; - while (parentNode != null) + while (currentNode != null) { - if (parentNode == rootNode) + if (rootNodes.Contains(currentNode)) { return true; } - parentNode = parentNode.parent; + currentNode = currentNode.parent; } return false; @@ -159,9 +152,14 @@ public AccessibilityNode InsertNode(int childIndex, string label = null, Accessi return null; } - var actualParent = parent ?? rootNode; + var node = mainHierarchy.InsertNode(childIndex, label, parent); + + if (parent == null) + { + rootNodes.Add(node); + } - return mainHierarchy.AddNode(label, actualParent); + return node; } /// @@ -178,9 +176,7 @@ public bool MoveNode(AccessibilityNode node, AccessibilityNode newParent, int ne return false; } - var actualParent = newParent ?? rootNode; - - return mainHierarchy.MoveNode(node, actualParent, newChildIndex); + return mainHierarchy.MoveNode(node, newParent, newChildIndex); } /// @@ -203,12 +199,12 @@ public void RemoveNode(AccessibilityNode node, bool removeChildren = true) /// public void Clear() { - if (rootNode != null) + if (rootNodes is { Count: > 0 }) { // Removes from the last to the first to avoid messing up the indices. - for (var i = rootNode.children.Count - 1; i >= 0; i--) + for (var i = rootNodes.Count - 1; i >= 0; i--) { - mainHierarchy.RemoveNode(rootNode.children[i]); + mainHierarchy.RemoveNode(rootNodes[i]); } } else diff --git a/Assets/Scripts/Screen Reader/UITk/UITkAccessibilityService.cs b/Assets/Scripts/Screen Reader/UITk/UITkAccessibilityService.cs index e464448..5a159a7 100644 --- a/Assets/Scripts/Screen Reader/UITk/UITkAccessibilityService.cs +++ b/Assets/Scripts/Screen Reader/UITk/UITkAccessibilityService.cs @@ -27,51 +27,8 @@ public UITkAccessibilityService() : base("UITk", 100) AssistiveSupport.nodeFocusChanged += OnNodeFocusChanged; } - bool m_NeedsToRecomputeRootFrames; - - public void DirtyRootFrames() - { - m_NeedsToRecomputeRootFrames = true; - } - - public void UpdateRootAndPanelFrames() - { - m_NeedsToRecomputeRootFrames = true; - - foreach (var accessibilityUpdater in m_AccessibilityUpdaters) - { - accessibilityUpdater.UpdateRootFrame(); - } - - var serviceRootFrame = Rect.zero; - - foreach (var panelNode in hierarchy.rootNode.children) - { - // Calculate the union of all root nodes frames. - if (panelNode.frame.size != Vector2.zero) - { - Encompass(ref serviceRootFrame, panelNode.frame); - } - } - - hierarchy.rootNode.frame = serviceRootFrame; - void Encompass(ref Rect a, Rect b) - { - a.xMin = Math.Min(a.xMin, b.xMin); - a.yMin = Math.Min(a.yMin, b.yMin); - a.xMax = Math.Max(a.xMax, b.xMax); - a.yMax = Math.Max(a.yMax, b.yMax); - } - } - public override void Update() { - if (m_NeedsToRecomputeRootFrames) - { - UpdateRootAndPanelFrames(); - m_NeedsToRecomputeRootFrames = false; - } - foreach (var accessibilityUpdater in m_AccessibilityUpdaters) { accessibilityUpdater.Update(); @@ -172,11 +129,6 @@ public override void SetUp(Scene scene) } var panel = uiDocument.runtimePanel; - var rootAcc = uiDocument.rootVisualElement.GetOrCreateAccessibleProperties(); - - rootAcc.label = uiDocument.rootVisualElement.name; - rootAcc.active = Application.platform == RuntimePlatform.OSXPlayer; // false; - rootAcc.role = AccessibilityRole.Container; if (!panels.Contains(panel)) { diff --git a/Assets/Scripts/Screen Reader/UITk/VisualTreeAccessibilityUpdater.cs b/Assets/Scripts/Screen Reader/UITk/VisualTreeAccessibilityUpdater.cs index 684c12e..21a9b9b 100644 --- a/Assets/Scripts/Screen Reader/UITk/VisualTreeAccessibilityUpdater.cs +++ b/Assets/Scripts/Screen Reader/UITk/VisualTreeAccessibilityUpdater.cs @@ -34,24 +34,11 @@ enum NotificationType VisualElement m_VisualTree; IVisualElementScheduledItem m_UpdateJob; UITkAccessibilityService m_AccessibilityService; - AccessibilitySubHierarchy m_SubHierarchy; /// /// The sub-hierarchy this updater is managing. /// - public AccessibilitySubHierarchy hierarchy - { - get => m_SubHierarchy; - set - { - m_SubHierarchy = value; - - if (m_SubHierarchy.isValid && visualTree != null) - { - DirtyRootFrame(); - } - } - } + public AccessibilitySubHierarchy hierarchy { get; set; } /// /// The panel of the visual tree being managed. @@ -111,14 +98,10 @@ public VisualTreeAccessibilityUpdater(IPanel panel, VisualElement visualTree, UI m_AccessibilityService = service; visualTree.RegisterCallback(OnAttachmentToPanel); visualTree.RegisterCallback(OnGeometryChanged); - - DirtyRootFrame(); } void OnGeometryChanged(GeometryChangedEvent evt) { - DirtyRootFrame(); - // OnScreenDebug.Log("OnGeometryChanged " + evt.target); OnVersionChanged(evt.target as VisualElement, VersionChangeType.Size | VersionChangeType.Transform); @@ -202,9 +185,9 @@ void InsertNode(VisualElementAccessibilityHandler parentHandler, VisualElementAc m_HandlersForNodes[node] = accHandler; - if (p != null) + if (parentHandler != null) { - p.nextInsertionIndex++; + parentHandler.nextInsertionIndex++; } else { @@ -216,14 +199,13 @@ void InsertNode(VisualElementAccessibilityHandler parentHandler, VisualElementAc bool MoveNode(VisualElementAccessibilityHandler parentElement, VisualElementAccessibilityHandler accHandler) { - var p = parentElement; - var parentNode = p?.node; - var index = p?.nextInsertionIndex ?? m_RootNextInsertionIndex; + var parentNode = parentElement?.node; + var index = parentElement?.nextInsertionIndex ?? m_RootNextInsertionIndex; var moved = hierarchy.MoveNode(accHandler.node, parentNode, index); - if (p != null) + if (parentElement != null) { - p.nextInsertionIndex++; + parentElement.nextInsertionIndex++; } else { @@ -431,19 +413,6 @@ void GetMinMaxY(Vector3[] vector, out float min, out float max) } } - void DirtyRootFrame() - { - m_AccessibilityService.DirtyRootFrames(); - } - - public void UpdateRootFrame() - { - if (hierarchy.isValid) - { - hierarchy.rootNode.frame = GetScreenPosition(visualTree); - } - } - void UpdateNode(VisualElementAccessibilityHandler accElement) { if (!IsNodeValid(accElement.node)) @@ -528,30 +497,9 @@ public void Update() Update(visualTree); } - string GetPanelName(VisualElement ve) - { - // Try to get the name of the panel using reflection. - var panel = ve.panel; - - if (panel == null) - { - return null; - } - - var panelType = panel.GetType(); - var nameProperty = panelType.GetProperty("name"); - - if (nameProperty != null) - { - return nameProperty.GetValue(panel, null) as string; - } - - return null; - } - NotificationType m_Notification = NotificationType.None; - void Update(VisualElement visualTree) + void Update(VisualElement ve) { var shouldSendNotification = false; @@ -563,13 +511,8 @@ void Update(VisualElement visualTree) { if (!hierarchy.isValid) { - var panelName = GetPanelName(visualTree); - var rootNode = m_AccessibilityService.hierarchy.AddNode(string.IsNullOrEmpty(panelName) ? - visualTree.name : panelName); - rootNode.role = AccessibilityRole.Container; - rootNode.isActive = Application.platform == RuntimePlatform.OSXPlayer; - hierarchy = new AccessibilitySubHierarchy(m_AccessibilityService.hierarchy.mainHierarchy, rootNode); - DirtyRootFrame(); + hierarchy = new AccessibilitySubHierarchy(m_AccessibilityService.hierarchy.mainHierarchy); + shouldSendNotification = true; } @@ -578,24 +521,24 @@ void Update(VisualElement visualTree) var modalElement = currentModalElement; - UpdateAccessibilityHierarchyRecursively(visualTree, null, false, true); + UpdateAccessibilityHierarchyRecursively(ve, null, false, true); // If there is a current modal element or if the current model element has changed then update the // active state of all nodes. if (currentModalElement != null || currentModalElement != modalElement) { OnScreenDebug.Log("Updating active state from modality " + currentModalElement?.name); - UpdateActiveStateFromModalityRecursively(visualTree); + UpdateActiveStateFromModalityRecursively(ve); } } if (shouldSendNotification || m_Notification.HasFlag(NotificationType.ScreenChanged)) { - visualTree.schedule.Execute(() => AssistiveSupport.notificationDispatcher.SendScreenChanged()); + ve.schedule.Execute(() => AssistiveSupport.notificationDispatcher.SendScreenChanged()); } else if (m_Notification.HasFlag(NotificationType.LayoutChanged)) { - visualTree.schedule.Execute(() => AssistiveSupport.notificationDispatcher.SendLayoutChanged()); + ve.schedule.Execute(() => AssistiveSupport.notificationDispatcher.SendLayoutChanged()); } }