Skip to content

Commit d20a8c0

Browse files
author
Bianca Marina Stana
committed
Merge branch 'unite2025/lsp-uitk' into unite2025/screen-reader-improvements
2 parents 614eec7 + 0ecdeff commit d20a8c0

12 files changed

+430
-312
lines changed

Assets/Scripts/Gameplay/GameViewController.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,7 @@ void MoveCard(bool shouldMoveLeft, int count)
304304
var otherSibling = draggable.transform.parent.GetChild(otherSiblingIndex);
305305

306306
// Make the letter uppercase to ensure correct phonetic pronunciation.
307+
// TODO: This should be localized.
307308
var announcement = $"Moved {draggable.name.ToUpper()} {(shouldMoveLeft ? "before" : "after")} {otherSibling.name.ToUpper()}";
308309

309310
// Announce that the card was moved.

Assets/Scripts/Screen Reader/UGUI/AccessibleElement.cs

Lines changed: 96 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -34,23 +34,10 @@ public AccessibilityNode node
3434
return;
3535
}
3636

37-
DisconnectFromFocusChanged();
38-
DisconnectFromSelected();
39-
DisconnectFromIncremented();
40-
DisconnectFromDecremented();
41-
DisconnectFromScrolled();
42-
DisconnectFromDismissed();
43-
37+
DisconnectFromNode();
4438
m_Node = value;
45-
4639
SetNodeProperties();
47-
48-
ConnectToFocusChanged();
49-
ConnectToSelected();
50-
ConnectToIncremented();
51-
ConnectToDecremented();
52-
ConnectToScrolled();
53-
ConnectToDismissed();
40+
ConnectToNode();
5441
}
5542
}
5643

@@ -175,6 +162,26 @@ protected virtual void UnbindFromControl()
175162
#endif // UNITY_6000_3_OR_NEWER
176163
}
177164

165+
void ConnectToNode()
166+
{
167+
ConnectToFocusChanged();
168+
ConnectToSelected();
169+
ConnectToIncremented();
170+
ConnectToDecremented();
171+
ConnectToScrolled();
172+
ConnectToDismissed();
173+
}
174+
175+
void DisconnectFromNode()
176+
{
177+
DisconnectFromFocusChanged();
178+
DisconnectFromSelected();
179+
DisconnectFromIncremented();
180+
DisconnectFromDecremented();
181+
DisconnectFromScrolled();
182+
DisconnectFromDismissed();
183+
}
184+
178185
void ConnectToFocusChanged()
179186
{
180187
if (node == null)
@@ -186,6 +193,21 @@ void ConnectToFocusChanged()
186193
node.focusChanged += InvokeFocused;
187194
}
188195

196+
void DisconnectFromFocusChanged()
197+
{
198+
if (node == null)
199+
{
200+
return;
201+
}
202+
203+
node.focusChanged -= InvokeFocused;
204+
}
205+
206+
void InvokeFocused(AccessibilityNode accessibilityNode, bool isFocused)
207+
{
208+
focused?.Invoke(isFocused);
209+
}
210+
189211
void ConnectToSelected()
190212
{
191213
// Implementing the selected event tells the screen reader that the node is selectable, which may lead to
@@ -204,99 +226,93 @@ void ConnectToSelected()
204226
#endif // UNITY_6000_3_OR_NEWER
205227
}
206228

207-
void ConnectToIncremented()
229+
void DisconnectFromSelected()
208230
{
209231
if (node == null)
210232
{
211233
return;
212234
}
213235

214-
node.incremented -= InvokeIncremented;
215-
node.incremented += InvokeIncremented;
236+
#if UNITY_6000_3_OR_NEWER
237+
node.invoked -= InvokeSelected;
238+
#else // UNITY_6000_3_OR_NEWER
239+
node.selected -= InvokeSelected;
240+
#endif // UNITY_6000_3_OR_NEWER
216241
}
217242

218-
void ConnectToDecremented()
243+
bool InvokeSelected()
219244
{
220-
if (node == null)
221-
{
222-
return;
223-
}
245+
var success = m_Selected?.Invoke() ?? false;
224246

225-
node.decremented -= InvokeDecremented;
226-
node.decremented += InvokeDecremented;
247+
node.value = value;
248+
node.state = state;
249+
250+
return success;
227251
}
228252

229-
void ConnectToScrolled()
253+
void ConnectToIncremented()
230254
{
231-
#if UNITY_6000_3_OR_NEWER
232-
if (node == null || m_Scrolled == null)
255+
if (node == null)
233256
{
234257
return;
235258
}
236259

237-
node.scrolled -= InvokeScrolled;
238-
node.scrolled += InvokeScrolled;
239-
#endif // UNITY_6000_3_OR_NEWER
260+
node.incremented -= InvokeIncremented;
261+
node.incremented += InvokeIncremented;
240262
}
241263

242-
void ConnectToDismissed()
264+
void DisconnectFromIncremented()
243265
{
244-
// Implementing the dismissed event tells the screen reader that the node is dismissible, which may lead to
245-
// a specific behaviour. Therefore, we don't implement the node's dismissed event unless we actually need
246-
// it.
247-
if (node == null || m_Dismissed == null)
266+
if (node == null)
248267
{
249268
return;
250269
}
251270

252-
#if UNITY_2023_3_OR_NEWER
253-
node.dismissed -= InvokeDismissed;
254-
node.dismissed += InvokeDismissed;
255-
#endif // UNITY_2023_3_OR_NEWER
271+
node.incremented -= InvokeIncremented;
256272
}
257273

258-
void DisconnectFromFocusChanged()
274+
void InvokeIncremented()
259275
{
260-
if (node == null)
261-
{
262-
return;
263-
}
264-
265-
node.focusChanged -= InvokeFocused;
276+
incremented?.Invoke();
266277
}
267278

268-
void DisconnectFromSelected()
279+
void ConnectToDecremented()
269280
{
270281
if (node == null)
271282
{
272283
return;
273284
}
274285

275-
#if UNITY_6000_3_OR_NEWER
276-
node.invoked -= InvokeSelected;
277-
#else // UNITY_6000_3_OR_NEWER
278-
node.selected -= InvokeSelected;
279-
#endif // UNITY_6000_3_OR_NEWER
286+
node.decremented -= InvokeDecremented;
287+
node.decremented += InvokeDecremented;
280288
}
281289

282-
void DisconnectFromIncremented()
290+
void DisconnectFromDecremented()
283291
{
284292
if (node == null)
285293
{
286294
return;
287295
}
288296

289-
node.incremented -= InvokeIncremented;
297+
node.decremented -= InvokeDecremented;
290298
}
291299

292-
void DisconnectFromDecremented()
300+
void InvokeDecremented()
293301
{
294-
if (node == null)
302+
decremented?.Invoke();
303+
}
304+
305+
void ConnectToScrolled()
306+
{
307+
#if UNITY_6000_3_OR_NEWER
308+
if (node == null || m_Scrolled == null)
295309
{
296310
return;
297311
}
298312

299-
node.decremented -= InvokeDecremented;
313+
node.scrolled -= InvokeScrolled;
314+
node.scrolled += InvokeScrolled;
315+
#endif // UNITY_6000_3_OR_NEWER
300316
}
301317

302318
void DisconnectFromScrolled()
@@ -311,53 +327,44 @@ void DisconnectFromScrolled()
311327
#endif // UNITY_6000_3_OR_NEWER
312328
}
313329

314-
void DisconnectFromDismissed()
330+
#if UNITY_6000_3_OR_NEWER
331+
bool InvokeScrolled(AccessibilityScrollDirection direction)
315332
{
316-
if (node == null)
333+
return m_Scrolled?.Invoke(direction) ?? false;
334+
}
335+
#endif // UNITY_6000_3_OR_NEWER
336+
337+
void ConnectToDismissed()
338+
{
339+
// Implementing the dismissed event tells the screen reader that the node is dismissible, which may lead to
340+
// a specific behaviour. Therefore, we don't implement the node's dismissed event unless we actually need
341+
// it.
342+
if (node == null || m_Dismissed == null)
317343
{
318344
return;
319345
}
320346

321347
#if UNITY_2023_3_OR_NEWER
322348
node.dismissed -= InvokeDismissed;
349+
node.dismissed += InvokeDismissed;
323350
#endif // UNITY_2023_3_OR_NEWER
324351
}
325352

326-
void InvokeFocused(AccessibilityNode accessibilityNode, bool isFocused)
327-
{
328-
focused?.Invoke(isFocused);
329-
}
330-
331-
bool InvokeSelected()
332-
{
333-
var success = m_Selected != null && m_Selected.Invoke();
334-
335-
node.value = value;
336-
node.state = state;
337-
338-
return success;
339-
}
340-
341-
internal void InvokeIncremented()
342-
{
343-
incremented?.Invoke();
344-
}
345-
346-
internal void InvokeDecremented()
353+
void DisconnectFromDismissed()
347354
{
348-
decremented?.Invoke();
349-
}
355+
if (node == null)
356+
{
357+
return;
358+
}
350359

351-
#if UNITY_6000_3_OR_NEWER
352-
bool InvokeScrolled(AccessibilityScrollDirection direction)
353-
{
354-
return m_Scrolled != null && m_Scrolled.Invoke(direction);
360+
#if UNITY_2023_3_OR_NEWER
361+
node.dismissed -= InvokeDismissed;
362+
#endif // UNITY_2023_3_OR_NEWER
355363
}
356-
#endif // UNITY_6000_3_OR_NEWER
357364

358365
bool InvokeDismissed()
359366
{
360-
return m_Dismissed != null && m_Dismissed.Invoke();
367+
return m_Dismissed?.Invoke() ?? false;
361368
}
362369

363370
public void SetNodeProperties()

Assets/Scripts/Screen Reader/UGUI/AccessibleInput.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using UnityEngine;
33
using UnityEngine.Accessibility;
44
using UnityEngine.EventSystems;
5+
using UnityEngine.Localization.Settings;
56
using UnityEngine.UI;
67

78
namespace Unity.Samples.ScreenReader
@@ -51,7 +52,12 @@ void Start()
5152
UpdateValue(m_InputField.text);
5253
}
5354

54-
hint = "Double tap to edit.";
55+
// if (Application.platform == RuntimePlatform.Android ||
56+
// Application.platform == RuntimePlatform.IPhonePlayer)
57+
// {
58+
// // TODO: "Double tap to edit." should be localized.
59+
// hint = LocalizationSettings.StringDatabase.GetLocalizedString("", "");
60+
// }
5561
}
5662

5763
protected override void BindToControl()

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

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -117,9 +117,17 @@ public bool allowsDirectInteraction
117117
set => m_AllowsDirectInteraction.Set(this, value);
118118
}
119119

120+
public event Action<bool> focused;
120121
public event Func<bool> selected;
121-
public Action incremented;
122-
public Action decremented;
122+
public event Action incremented;
123+
public event Action decremented;
124+
public event Func<AccessibilityScrollDirection, bool> scrolled;
125+
public event Func<bool> dismissed;
126+
127+
internal void InvokeFocused(AccessibilityNode accessibilityNode, bool isFocused)
128+
{
129+
focused?.Invoke(isFocused);
130+
}
123131

124132
internal bool InvokeSelected()
125133
{
@@ -135,23 +143,33 @@ internal void InvokeDecremented()
135143
{
136144
decremented?.Invoke();
137145
}
146+
147+
internal bool InvokeScrolled(AccessibilityScrollDirection direction)
148+
{
149+
return scrolled?.Invoke(direction) ?? false;
150+
}
151+
152+
internal bool InvokeDismissed()
153+
{
154+
return dismissed?.Invoke() ?? false;
155+
}
138156
}
139157

140158
public static class AccessibilityVisualElementExtensions
141159
{
142-
static Dictionary<VisualElement, AccessibleProperties> m_AttachedAccessibleProperties = new();
160+
static Dictionary<VisualElement, AccessibleProperties> s_AttachedAccessibleProperties = new();
143161

144162
static AccessibleProperties GetAttachedAccessibleProperties(VisualElement ve)
145163
{
146-
return m_AttachedAccessibleProperties.GetValueOrDefault(ve);
164+
return s_AttachedAccessibleProperties.GetValueOrDefault(ve);
147165
}
148166

149167
static AccessibleProperties AttachAccessibleProperties(VisualElement ve)
150168
{
151169
var accessible = new AccessibleProperties();
152170
accessible.owner = ve;
153171

154-
m_AttachedAccessibleProperties[ve] = accessible;
172+
s_AttachedAccessibleProperties[ve] = accessible;
155173

156174
return accessible;
157175
}

Assets/Scripts/Screen Reader/UITk/Handlers/ButtonHandler.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,23 @@ namespace Unity.Samples.ScreenReader
77
[Preserve]
88
class ButtonHandler : VisualElementAccessibilityHandler
99
{
10+
public ButtonHandler()
11+
{
12+
selected += () =>
13+
{
14+
if (ownerElement is not Button button)
15+
{
16+
return false;
17+
}
18+
19+
using var e = new NavigationSubmitEvent();
20+
e.target = button;
21+
button.SendEvent(e);
22+
23+
return true;
24+
};
25+
}
26+
1027
public override string GetLabel()
1128
{
1229
return (ownerElement as Button)?.text;

0 commit comments

Comments
 (0)