Skip to content

Commit c84460e

Browse files
committed
Change: Add some basic screen reader support for in-game menu
1 parent 619b872 commit c84460e

19 files changed

+733
-11
lines changed

Readme.md

+4-3
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,9 @@ Please also see the following issue for further discussion on the topic: https:/
6969
- openBVE uses the [**NVorbis**](https://github.com/NVorbis/NVorbis) for decoding Vorbis file. This is licensed under the *Microsoft Public License*, which may be found in [here](licenses/NVorbis.txt).
7070
- openBVE uses the [**OpenTK**](https://github.com/opentk/opentk) library for windowing and input handling. This is licensed under the _Open Toolkit Library License_, which may be found in [here](licenses/OpenTK.txt).
7171
- openBVE uses the [**Prism**](https://github.com/PrismLibrary/Prism). This is licensed under the *MIT License*, which may be found in [here](licenses/Prism.txt).
72-
- openBVE uses the [**ReactiveProperty**](https://github.com/runceel/ReactiveProperty). This is licensed under the *MIT License*, which may be found in [here](licenses/ReactiveProperty.txt).
72+
- openBVE uses the [**ReactiveProperty**](https://github.com/runceel/ReactiveProperty) This is licensed under the *MIT License*, which may be found in [here](licenses/ReactiveProperty.txt).
7373
- openBVE uses the [**SharpCompress**](https://github.com/adamhathcock/sharpcompress) for archive handling. This is licensed under the _MIT License_, which may be found in [here](licenses/SharpCompress.txt).
74-
- openBVE uses the [**Reactive Extensions**](https://github.com/dotnet/reactive). This is licensed under the *Apache License, Version 2.0*, which may be found in [here](licenses/ReactiveExtensions.txt).
74+
- openBVE uses the [**Reactive Extensions**](https://github.com/dotnet/reactive) This is licensed under the *Apache License, Version 2.0*, which may be found in [here](licenses/ReactiveExtensions.txt).
7575
- openBVE uses the [**Ude**](https://github.com/yinyue200/ude) for character set detection. This is tri-licensed under the _Mozilla Public License v1.1_, _GPL 2.0_ and _LGPL 2.0_, which may be found in [here](licenses/Ude.txt).
76-
- openBVE uses the [**XamlBehaviors for WPF**](https://github.com/microsoft/XamlBehaviorsWpf). This is licensed under the *MIT License*, which may be found in [here](licenses/XamlBehaviorsForWPF.txt).
76+
- openBVE uses the [**XamlBehaviors for WPF**](https://github.com/microsoft/XamlBehaviorsWpf) This is licensed under the *MIT License*, which may be found in [here](licenses/XamlBehaviorsForWPF.txt).
77+
- openBVE uses the [**TOLK**] (https://github.com/dkager/tolk) library for screen reader API access. This is licenced under the *LGPL V3* which may be found in [here](licences/TOLK.txt)

dependencies/TolkDotNet.dll

4 KB
Binary file not shown.

dependencies/x64/SAAPI64.dll

84 KB
Binary file not shown.

dependencies/x64/Tolk.dll

121 KB
Binary file not shown.

dependencies/x64/Tolk.exp

4.45 KB
Binary file not shown.

dependencies/x64/Tolk.lib

7.79 KB
Binary file not shown.
150 KB
Binary file not shown.

dependencies/x86/SAAPI32.dll

76 KB
Binary file not shown.

dependencies/x86/Tolk.dll

95 KB
Binary file not shown.

dependencies/x86/Tolk.exp

4.6 KB
Binary file not shown.

dependencies/x86/Tolk.lib

8.05 KB
Binary file not shown.

dependencies/x86/dolapi32.dll

145 KB
Binary file not shown.
130 KB
Binary file not shown.

licenses/NVDA.txt

+504
Large diffs are not rendered by default.

licenses/TOLK.txt

+165
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
GNU LESSER GENERAL PUBLIC LICENSE
2+
Version 3, 29 June 2007
3+
4+
Copyright (C) 2007 Free Software Foundation, Inc. [http://fsf.org/]
5+
Everyone is permitted to copy and distribute verbatim copies
6+
of this license document, but changing it is not allowed.
7+
8+
9+
This version of the GNU Lesser General Public License incorporates
10+
the terms and conditions of version 3 of the GNU General Public
11+
License, supplemented by the additional permissions listed below.
12+
13+
0. Additional Definitions.
14+
15+
As used herein, "this License" refers to version 3 of the GNU Lesser
16+
General Public License, and the "GNU GPL" refers to version 3 of the GNU
17+
General Public License.
18+
19+
"The Library" refers to a covered work governed by this License,
20+
other than an Application or a Combined Work as defined below.
21+
22+
An "Application" is any work that makes use of an interface provided
23+
by the Library, but which is not otherwise based on the Library.
24+
Defining a subclass of a class defined by the Library is deemed a mode
25+
of using an interface provided by the Library.
26+
27+
A "Combined Work" is a work produced by combining or linking an
28+
Application with the Library. The particular version of the Library
29+
with which the Combined Work was made is also called the "Linked
30+
Version".
31+
32+
The "Minimal Corresponding Source" for a Combined Work means the
33+
Corresponding Source for the Combined Work, excluding any source code
34+
for portions of the Combined Work that, considered in isolation, are
35+
based on the Application, and not on the Linked Version.
36+
37+
The "Corresponding Application Code" for a Combined Work means the
38+
object code and/or source code for the Application, including any data
39+
and utility programs needed for reproducing the Combined Work from the
40+
Application, but excluding the System Libraries of the Combined Work.
41+
42+
1. Exception to Section 3 of the GNU GPL.
43+
44+
You may convey a covered work under sections 3 and 4 of this License
45+
without being bound by section 3 of the GNU GPL.
46+
47+
2. Conveying Modified Versions.
48+
49+
If you modify a copy of the Library, and, in your modifications, a
50+
facility refers to a function or data to be supplied by an Application
51+
that uses the facility (other than as an argument passed when the
52+
facility is invoked), then you may convey a copy of the modified
53+
version:
54+
55+
a) under this License, provided that you make a good faith effort to
56+
ensure that, in the event an Application does not supply the
57+
function or data, the facility still operates, and performs
58+
whatever part of its purpose remains meaningful, or
59+
60+
b) under the GNU GPL, with none of the additional permissions of
61+
this License applicable to that copy.
62+
63+
3. Object Code Incorporating Material from Library Header Files.
64+
65+
The object code form of an Application may incorporate material from
66+
a header file that is part of the Library. You may convey such object
67+
code under terms of your choice, provided that, if the incorporated
68+
material is not limited to numerical parameters, data structure
69+
layouts and accessors, or small macros, inline functions and templates
70+
(ten or fewer lines in length), you do both of the following:
71+
72+
a) Give prominent notice with each copy of the object code that the
73+
Library is used in it and that the Library and its use are
74+
covered by this License.
75+
76+
b) Accompany the object code with a copy of the GNU GPL and this license
77+
document.
78+
79+
4. Combined Works.
80+
81+
You may convey a Combined Work under terms of your choice that,
82+
taken together, effectively do not restrict modification of the
83+
portions of the Library contained in the Combined Work and reverse
84+
engineering for debugging such modifications, if you also do each of
85+
the following:
86+
87+
a) Give prominent notice with each copy of the Combined Work that
88+
the Library is used in it and that the Library and its use are
89+
covered by this License.
90+
91+
b) Accompany the Combined Work with a copy of the GNU GPL and this license
92+
document.
93+
94+
c) For a Combined Work that displays copyright notices during
95+
execution, include the copyright notice for the Library among
96+
these notices, as well as a reference directing the user to the
97+
copies of the GNU GPL and this license document.
98+
99+
d) Do one of the following:
100+
101+
0) Convey the Minimal Corresponding Source under the terms of this
102+
License, and the Corresponding Application Code in a form
103+
suitable for, and under terms that permit, the user to
104+
recombine or relink the Application with a modified version of
105+
the Linked Version to produce a modified Combined Work, in the
106+
manner specified by section 6 of the GNU GPL for conveying
107+
Corresponding Source.
108+
109+
1) Use a suitable shared library mechanism for linking with the
110+
Library. A suitable mechanism is one that (a) uses at run time
111+
a copy of the Library already present on the user's computer
112+
system, and (b) will operate properly with a modified version
113+
of the Library that is interface-compatible with the Linked
114+
Version.
115+
116+
e) Provide Installation Information, but only if you would otherwise
117+
be required to provide such information under section 6 of the
118+
GNU GPL, and only to the extent that such information is
119+
necessary to install and execute a modified version of the
120+
Combined Work produced by recombining or relinking the
121+
Application with a modified version of the Linked Version. (If
122+
you use option 4d0, the Installation Information must accompany
123+
the Minimal Corresponding Source and Corresponding Application
124+
Code. If you use option 4d1, you must provide the Installation
125+
Information in the manner specified by section 6 of the GNU GPL
126+
for conveying Corresponding Source.)
127+
128+
5. Combined Libraries.
129+
130+
You may place library facilities that are a work based on the
131+
Library side by side in a single library together with other library
132+
facilities that are not Applications and are not covered by this
133+
License, and convey such a combined library under terms of your
134+
choice, if you do both of the following:
135+
136+
a) Accompany the combined library with a copy of the same work based
137+
on the Library, uncombined with any other library facilities,
138+
conveyed under the terms of this License.
139+
140+
b) Give prominent notice with the combined library that part of it
141+
is a work based on the Library, and explaining where to find the
142+
accompanying uncombined form of the same work.
143+
144+
6. Revised Versions of the GNU Lesser General Public License.
145+
146+
The Free Software Foundation may publish revised and/or new versions
147+
of the GNU Lesser General Public License from time to time. Such new
148+
versions will be similar in spirit to the present version, but may
149+
differ in detail to address new problems or concerns.
150+
151+
Each version is given a distinguishing version number. If the
152+
Library as you received it specifies that a certain numbered version
153+
of the GNU Lesser General Public License "or any later version"
154+
applies to it, you have the option of following the terms and
155+
conditions either of that published version or of any later version
156+
published by the Free Software Foundation. If the Library as you
157+
received it does not specify a version number of the GNU Lesser
158+
General Public License, you may choose any version of the GNU Lesser
159+
General Public License ever published by the Free Software Foundation.
160+
161+
If the Library as you received it specifies that a proxy can decide
162+
whether future versions of the GNU Lesser General Public License shall
163+
apply, that proxy's public statement of acceptance of any version is
164+
permanent authorization for you to choose that version for the
165+
Library.

source/OpenBVE/Game/Menu.cs

+25-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
using OpenBveApi.Colors;
22
using OpenBveApi.Graphics;
33
using OpenBveApi.Interface;
4-
using OpenBveApi.Math;
54
using System;
65
using System.Drawing;
6+
using DavyKager;
77
using LibRender2.Screens;
88
using LibRender2.Texts;
99
using OpenBve.Input;
@@ -137,7 +137,30 @@ MENU FIELDS
137137
public readonly int ItemWidth = 0;
138138
public readonly int Width = 0;
139139
public readonly int Height = 0;
140-
public int Selection;
140+
141+
private int lastSelection = int.MaxValue;
142+
private int currentSelection;
143+
144+
public int Selection
145+
{
146+
get
147+
{
148+
return currentSelection;
149+
}
150+
set
151+
{
152+
lastSelection = currentSelection;
153+
currentSelection = value;
154+
if (currentSelection != lastSelection && Interface.CurrentOptions.ScreenReaderAvailable)
155+
{
156+
if (!Tolk.Output(Items[currentSelection].Text))
157+
{
158+
// failed to output to screen reader, so don't keep trying
159+
Interface.CurrentOptions.ScreenReaderAvailable = false;
160+
}
161+
}
162+
}
163+
}
141164
public int TopItem; // the top displayed menu item
142165

143166

source/OpenBVE/OpenBve.csproj

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="12.0">
3-
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
3+
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
44
<PropertyGroup>
55
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
66
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
@@ -124,6 +124,9 @@
124124
<Reference Include="System.Windows.Forms" />
125125
<Reference Include="System.Xml" />
126126
<Reference Include="System.Xml.Linq" />
127+
<Reference Include="TolkDotNet">
128+
<HintPath>..\..\dependencies\TolkDotNet.dll</HintPath>
129+
</Reference>
127130
</ItemGroup>
128131
<ItemGroup>
129132
<Compile Include="Game\AI\AI.cs" />

source/OpenBVE/System/MainLoop.cs

+20-5
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
using System.ComponentModel;
33
using System.Globalization;
44
using System.Linq;
5-
using LibRender2;
5+
using DavyKager;
66
using LibRender2.Screens;
77
using OpenBve.Input;
88
using OpenBveApi.Interface;
@@ -30,7 +30,7 @@ internal enum QuitMode
3030
internal static bool BlockKeyRepeat;
3131
/// <summary>The current simulation time-factor</summary>
3232
internal static int TimeFactor = 1;
33-
33+
3434
internal static double timeSinceLastMouseEvent;
3535

3636
internal static formMain.MainDialogResult currentResult;
@@ -52,6 +52,21 @@ internal enum QuitMode
5252
internal static void StartLoopEx(formMain.MainDialogResult result)
5353
{
5454
Program.Sounds.Initialize(Program.CurrentHost, Interface.CurrentOptions.SoundRange);
55+
Interface.CurrentOptions.Accessibility = true;
56+
if (Interface.CurrentOptions.Accessibility)
57+
{
58+
Tolk.Load();
59+
string name = Tolk.DetectScreenReader();
60+
if (!string.IsNullOrEmpty(name))
61+
{
62+
Interface.CurrentOptions.ScreenReaderAvailable = true;
63+
Program.FileSystem.AppendToLogFile("Supported screen reader driver " + name + " initialised.");
64+
}
65+
else
66+
{
67+
Program.FileSystem.AppendToLogFile("No supported screen reader found.");
68+
}
69+
}
5570
//Process extra command line arguments supplied
5671
if (result.InitialStation != null)
5772
{
@@ -65,13 +80,13 @@ internal static void StartLoopEx(formMain.MainDialogResult result)
6580

6681
Game.InitialAIDriver = result.AIDriver;
6782
Game.InitialReversedConsist = result.ReverseConsist;
68-
if (result.FullScreen == true)
83+
if (result.FullScreen)
6984
{
7085
Interface.CurrentOptions.FullscreenMode = true;
7186
}
7287
if (result.Width != default(double) && result.Height != default(double))
7388
{
74-
if (Interface.CurrentOptions.FullscreenMode == true)
89+
if (Interface.CurrentOptions.FullscreenMode)
7590
{
7691
Interface.CurrentOptions.FullscreenWidth = result.Width;
7792
Interface.CurrentOptions.FullscreenHeight = result.Height;
@@ -390,7 +405,7 @@ internal static void ProcessKeyboard()
390405
}
391406
else
392407
{
393-
Interface.CurrentControls[i].AnalogState = (double)Math.Sign(axisState);
408+
Interface.CurrentControls[i].AnalogState = Math.Sign(axisState);
394409
}
395410
}
396411
else

source/OpenBVE/System/Options.cs

+11
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,11 @@ internal class Options : BaseOptions
8484
/// <remarks>Set to zero to never hide the cursor</remarks>
8585
internal double CursorHideDelay;
8686
internal string CursorFileName;
87+
/// <summary>Whether various accessibility helpers are enabled</summary>
88+
internal bool Accessibility;
89+
/// <summary>Whether a screen reader is available</summary>
90+
/// <remarks>Not saved, detected on game init</remarks>
91+
internal bool ScreenReaderAvailable;
8792

8893
internal TimeTableMode TimeTableStyle;
8994

@@ -173,6 +178,8 @@ internal Options()
173178
this.CurrentXParser = XParsers.Original; //Set to Michelle's original X parser by default
174179
this.CurrentObjParser = ObjParsers.Original; //Set to original Obj parser by default
175180
this.CursorHideDelay = 10;
181+
this.Accessibility = false;
182+
this.ScreenReaderAvailable = false;
176183
}
177184
}
178185
/// <summary>The current game options</summary>
@@ -269,6 +276,9 @@ internal static void LoadOptions()
269276
}
270277
Interface.CurrentOptions.KioskModeTimer = d;
271278
break;
279+
case "accessibility":
280+
Interface.CurrentOptions.Accessibility = string.Compare(Value, "true", StringComparison.OrdinalIgnoreCase) == 0;
281+
break;
272282
} break;
273283
case "display":
274284
switch (Key)
@@ -780,6 +790,7 @@ internal static void SaveOptions()
780790
}
781791
Builder.AppendLine("kioskMode = " + (CurrentOptions.KioskMode ? "true" : "false"));
782792
Builder.AppendLine("kioskModeTimer = " + CurrentOptions.KioskModeTimer);
793+
Builder.AppendLine("accessibility = " + (CurrentOptions.Accessibility ? "true" : "false"));
783794
Builder.AppendLine();
784795
Builder.AppendLine("[display]");
785796
Builder.AppendLine("preferNativeBackend = " + (CurrentOptions.PreferNativeBackend ? "true" : "false"));

0 commit comments

Comments
 (0)