Skip to content

Commit cfed451

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 24919d0 commit cfed451

File tree

1 file changed

+44
-3
lines changed

1 file changed

+44
-3
lines changed

PSReadLine/Accessibility.cs

Lines changed: 44 additions & 3 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,17 @@ 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))
15-
return false;
14+
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
15+
return IsAnyWindowsScreenReaderEnabled(); // Check for macOS VoiceOver
1616

17+
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
18+
return IsVoiceOverEnabled();
19+
20+
// TODO: Support Linux per https://code.visualstudio.com/docs/configure/accessibility/accessibility
21+
return false;
22+
}
23+
24+
private static bool IsAnyWindowsScreenReaderEnabled() {
1725
// The supposedly official way to check for a screen reader on
1826
// Windows is SystemParametersInfo(SPI_GETSCREENREADER, ...) but it
1927
// doesn't detect the in-box Windows Narrator and is otherwise known
@@ -48,5 +56,38 @@ internal static bool IsScreenReaderActive()
4856

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

0 commit comments

Comments
 (0)