Skip to content

Commit a6dc616

Browse files
committed
Check for VoiceOver screen reader on macOS
Spawns a quick `defaults` process since in .NET using the macOS events is difficult, but this is quick and easy.
1 parent 4baae08 commit a6dc616

File tree

1 file changed

+48
-2
lines changed

1 file changed

+48
-2
lines changed

PSReadLine/Accessibility.cs

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
Copyright (c) Microsoft Corporation. All rights reserved.
33
--********************************************************************/
44

5+
using System.Diagnostics;
56
using System.Runtime.InteropServices;
67

78
namespace Microsoft.PowerShell.Internal
@@ -10,10 +11,22 @@ internal class Accessibility
1011
{
1112
internal static bool IsScreenReaderActive()
1213
{
13-
// TODO: Support other platforms per https://code.visualstudio.com/docs/configure/accessibility/accessibility
14-
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
14+
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
15+
{
16+
return IsAnyWindowsScreenReaderEnabled();
17+
}
18+
19+
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
20+
{
21+
return IsVoiceOverEnabled();
22+
}
23+
24+
// TODO: Support Linux per https://code.visualstudio.com/docs/configure/accessibility/accessibility
1525
return false;
26+
}
1627

28+
private static bool IsAnyWindowsScreenReaderEnabled()
29+
{
1730
// The supposedly official way to check for a screen reader on
1831
// Windows is SystemParametersInfo(SPI_GETSCREENREADER, ...) but it
1932
// doesn't detect the in-box Windows Narrator and is otherwise known
@@ -48,5 +61,38 @@ internal static bool IsScreenReaderActive()
4861

4962
return false;
5063
}
64+
65+
private static bool IsVoiceOverEnabled()
66+
{
67+
try
68+
{
69+
// Use the 'defaults' command to check if VoiceOver is enabled
70+
// This checks the com.apple.universalaccess preference for voiceOverOnOffKey
71+
ProcessStartInfo startInfo = new()
72+
{
73+
FileName = "defaults",
74+
Arguments = "read com.apple.universalaccess voiceOverOnOffKey",
75+
UseShellExecute = false,
76+
RedirectStandardOutput = true,
77+
RedirectStandardError = true,
78+
CreateNoWindow = true
79+
};
80+
81+
using Process process = Process.Start(startInfo);
82+
process.WaitForExit(250);
83+
if (process.HasExited && process.ExitCode == 0)
84+
{
85+
string output = process.StandardOutput.ReadToEnd().Trim();
86+
// VoiceOver is enabled if the value is 1
87+
return output == "1";
88+
}
89+
}
90+
catch
91+
{
92+
// If we can't determine the status, assume VoiceOver is not enabled
93+
}
94+
95+
return false;
96+
}
5197
}
5298
}

0 commit comments

Comments
 (0)