Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UI Automation in Windows Console: Make UIA the default for Windows 10 1803 and later #9771

Merged
merged 20 commits into from
Aug 2, 2019
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion source/NVDAObjects/UIA/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -861,7 +861,7 @@ def findOverlayClasses(self,clsList):
# Support Windows Console's UIA interface
if (
self.windowClassName == "ConsoleWindowClass"
and config.conf['UIA']['winConsoleImplementation'] == "UIA"
and shouldUseUIAConsole()
):
from . import winConsoleUIA
winConsoleUIA.findExtraOverlayClasses(self, clsList)
Expand Down
9 changes: 2 additions & 7 deletions source/NVDAObjects/UIA/winConsoleUIA.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
import UIAHandler

from scriptHandler import script
from winVersion import isWin10
from . import UIATextInfo
from ..behaviors import Terminal
from ..window import Window
Expand All @@ -27,9 +26,7 @@ class consoleUIATextInfo(UIATextInfo):
_expandCollapseBeforeReview = False

def collapse(self,end=False):
"""Works around a UIA bug on Windows 10 1903 and later."""
if not isWin10(1903):
return super(consoleUIATextInfo, self).collapse(end=end)
"""Works around a UIA bug on Windows 10 1803 and later."""
# When collapsing, consoles seem to incorrectly push the start of the
# textRange back one character.
# Correct this by bringing the start back up to where the end is.
Expand Down Expand Up @@ -146,9 +143,7 @@ def expand(self, unit):
return super(consoleUIATextInfo, self).expand(unit)

def _get_isCollapsed(self):
"""Works around a UIA bug on Windows 10 1903 and later."""
if not isWin10(1903):
return super(consoleUIATextInfo, self)._get_isCollapsed()
"""Works around a UIA bug on Windows 10 1803 and later."""
# Even when a console textRange's start and end have been moved to the
# same position, the console incorrectly reports the end as being
# past the start.
Expand Down
18 changes: 17 additions & 1 deletion source/UIAUtils.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
#A part of NonVisual Desktop Access (NVDA)
#Copyright (C) 2015-2016 NV Access Limited
#Copyright (C) 2015-2019 NV Access Limited, Bill Dengler
#This file is covered by the GNU General Public License.
#See the file COPYING for more details.

import operator
from comtypes import COMError
import config
import ctypes
import UIAHandler
from winVersion import isWin10

def createUIAMultiPropertyCondition(*dicts):
"""
Expand Down Expand Up @@ -203,3 +205,17 @@ def getValue(self,ID,ignoreMixedValues=False):
raise UIAMixedAttributeError
return val

def shouldUseUIAConsole(setting=None):
"""Determines whether to use UIA in the Windows Console.
@param setting: the config value to base this check on (if not provided,
it is retrieved from config).
"""
if not setting:
setting = config.conf['UIA']['winConsoleImplementation']
if setting == "legacy":
return False
elif setting == "UIA":
return True
# #7497: Windows 10 Fall Creators Update has an incomplete UIA implementation for console windows, therefore for now we should ignore it.
# It does not implement caret/selection, and probably has no new text events.
return isWin10(1803)
feerrenrut marked this conversation as resolved.
Show resolved Hide resolved
7 changes: 4 additions & 3 deletions source/_UIAHandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -355,9 +355,10 @@ def IUIAutomationNotificationEventHandler_HandleNotificationEvent(self,sender,No

def _isBadUIAWindowClassName(self, windowClass):
"Given a windowClassName, returns True if this is a known problematic UIA implementation."
# #7497: Windows 10 Fall Creators Update has an incomplete UIA implementation for console windows, therefore for now we should ignore it.
# It does not implement caret/selection, and probably has no new text events.
if windowClass == "ConsoleWindowClass" and config.conf['UIA']['winConsoleImplementation'] != "UIA":
if (
windowClass == "ConsoleWindowClass"
and not UIAUtils.shouldUseUIAConsole()
):
return True
return windowClass in badUIAWindowClassNames

Expand Down
67 changes: 53 additions & 14 deletions source/gui/settingsDialogs.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import inputCore
from . import nvdaControls
from driverHandler import *
from UIAUtils import shouldUseUIAConsole
import touchHandler
import winVersion
import weakref
Expand Down Expand Up @@ -2050,20 +2051,51 @@ def __init__(self, parent):
self.UIAInMSWordCheckBox.SetValue(config.conf["UIA"]["useInMSWordWhenAvailable"])
self.UIAInMSWordCheckBox.defaultValue = self._getDefaultValue(["UIA", "useInMSWordWhenAvailable"])

# Translators: This is the label for a checkbox in the
# Advanced settings panel.
label = _("Use UI Automation to access the Windows Console when available")
consoleUIADevMap = True if config.conf['UIA']['winConsoleImplementation'] == 'UIA' else False
self.ConsoleUIACheckBox=UIAGroup.addItem(wx.CheckBox(self, label=label))
self.ConsoleUIACheckBox.SetValue(consoleUIADevMap)
self.ConsoleUIACheckBox.defaultValue = self._getDefaultValue(["UIA", "winConsoleImplementation"])
# Translators: This is the label for a combo box for selecting the
# active console implementation in the advanced settings panel.
# Choices are automatic, prefer UIA, and legacy.
consoleComboText = _("Windows C&onsole support:")
consoleChoices=[
#Translators: A choice in a combo box in the advanced settings
# panel to have NVDA determine its Windows Console implementation
# automatically.
_("Automatic"),
#Translators: A choice in a combo box in the advanced settings
# panel to have NVDA use UIA in the Windows Console when available.
_("Prefer UIA"),
#Translators: A choice in a combo box in the advanced settings
# panel to have NVDA use its legacy Windoes Console support
# in all cases.
_("Legacy")
]
#: The possible console config values, in the order they appear
#: in the combo box.
self.consoleVals = (
"auto",
"UIA",
"legacy"
)
self.consoleCombo = UIAGroup.addLabeledControl(consoleComboText, wx.Choice, choices=consoleChoices)
self.consoleCombo.Bind(
wx.EVT_CHOICE,
self.enableConsolePasswordsCheckBox,
self.consoleCombo
)
curChoice = self.consoleVals.index(
config.conf['UIA']['winConsoleImplementation']
)
self.consoleCombo.SetSelection(curChoice)
feerrenrut marked this conversation as resolved.
Show resolved Hide resolved
self.consoleCombo.defaultValue = self.consoleVals.index(
self._getDefaultValue(["UIA", "winConsoleImplementation"])
)

# Translators: This is the label for a checkbox in the
# Advanced settings panel.
feerrenrut marked this conversation as resolved.
Show resolved Hide resolved
label = _("Speak &passwords in UIA consoles (may improve performance)")
label = _("Speak &passwords in Windows Console (may improve performance)")
self.winConsoleSpeakPasswordsCheckBox=UIAGroup.addItem(wx.CheckBox(self, label=label))
self.winConsoleSpeakPasswordsCheckBox.SetValue(config.conf["UIA"]["winConsoleSpeakPasswords"])
self.winConsoleSpeakPasswordsCheckBox.defaultValue = self._getDefaultValue(["UIA", "winConsoleSpeakPasswords"])
self.enableConsolePasswordsCheckBox()

# Translators: This is the label for a group of advanced options in the
# Advanced settings panel
Expand Down Expand Up @@ -2137,6 +2169,13 @@ def __init__(self, parent):
]
self.Layout()

def enableConsolePasswordsCheckBox(self, evt=None):
return self.winConsoleSpeakPasswordsCheckBox.Enable(
shouldUseUIAConsole(self.consoleVals[
self.consoleCombo.GetSelection()
])
)

def onOpenScratchpadDir(self,evt):
path=config.getScratchpadDir(ensureExists=True)
os.startfile(path)
Expand All @@ -2149,7 +2188,7 @@ def haveConfigDefaultsBeenRestored(self):
self._defaultsRestored and
self.scratchpadCheckBox.IsChecked() == self.scratchpadCheckBox.defaultValue and
self.UIAInMSWordCheckBox.IsChecked() == self.UIAInMSWordCheckBox.defaultValue and
self.ConsoleUIACheckBox.IsChecked() == (self.ConsoleUIACheckBox.defaultValue=='UIA') and
self.consoleCombo.GetSelection() == self.consoleCombo.defaultValue and
self.winConsoleSpeakPasswordsCheckBox.IsChecked() == self.winConsoleSpeakPasswordsCheckBox.defaultValue and
self.autoFocusFocusableElementsCheckBox.IsChecked() == self.autoFocusFocusableElementsCheckBox.defaultValue and
self.caretMoveTimeoutSpinControl.GetValue() == self.caretMoveTimeoutSpinControl.defaultValue and
Expand All @@ -2160,7 +2199,7 @@ def haveConfigDefaultsBeenRestored(self):
def restoreToDefaults(self):
self.scratchpadCheckBox.SetValue(self.scratchpadCheckBox.defaultValue)
self.UIAInMSWordCheckBox.SetValue(self.UIAInMSWordCheckBox.defaultValue)
self.ConsoleUIACheckBox.SetValue(self.ConsoleUIACheckBox.defaultValue=='UIA')
self.consoleCombo.SetSelection(self.consoleCombo.defaultValue=='UIA')
self.winConsoleSpeakPasswordsCheckBox.SetValue(self.winConsoleSpeakPasswordsCheckBox.defaultValue)
self.autoFocusFocusableElementsCheckBox.SetValue(self.autoFocusFocusableElementsCheckBox.defaultValue)
self.caretMoveTimeoutSpinControl.SetValue(self.caretMoveTimeoutSpinControl.defaultValue)
Expand All @@ -2171,10 +2210,10 @@ def onSave(self):
log.debug("Saving advanced config")
config.conf["development"]["enableScratchpadDir"]=self.scratchpadCheckBox.IsChecked()
config.conf["UIA"]["useInMSWordWhenAvailable"]=self.UIAInMSWordCheckBox.IsChecked()
if self.ConsoleUIACheckBox.IsChecked():
config.conf['UIA']['winConsoleImplementation'] = "UIA"
else:
config.conf['UIA']['winConsoleImplementation'] = "auto"
consoleChoice = self.consoleCombo.GetSelection()
config.conf['UIA']['winConsoleImplementation'] = (
self.consoleVals[consoleChoice]
)
config.conf["UIA"]["winConsoleSpeakPasswords"]=self.winConsoleSpeakPasswordsCheckBox.IsChecked()
config.conf["virtualBuffers"]["autoFocusFocusableElements"] = self.autoFocusFocusableElementsCheckBox.IsChecked()
config.conf["editableText"]["caretMoveTimeoutMs"]=self.caretMoveTimeoutSpinControl.GetValue()
Expand Down
17 changes: 13 additions & 4 deletions user_docs/en/userGuide.t2t
Original file line number Diff line number Diff line change
Expand Up @@ -1671,11 +1671,20 @@ This includes in Microsoft Word itself, and also the Microsoft Outlook message v
However, There may be some information which is either not exposed, or exposed incorrectly in some versions of Microsoft Office, which means this UI automation support cannot always be relied upon.
We still do not recommend that the majority of users turn this on by default, though we do welcome users of Office 2016/365 to test this feature and provide feedback.

==== Use UI Automation to access the Windows Console when available ====[AdvancedSettingsConsoleUIA]
When this option is enabled, NVDA will use a new, work in progress version of its support for Windows Console which takes advantage of [accessibility improvements made by Microsoft https://devblogs.microsoft.com/commandline/whats-new-in-windows-console-in-windows-10-fall-creators-update/]. This feature is highly experimental and is still incomplete, so its use is not yet recommended. However, once completed, it is anticipated that this new support will become the default, improving NVDA's performance and stability in Windows command consoles.
==== Windows Console support ====[AdvancedSettingsConsoleUIA]
This option selects how NVDA interacts with the Windows Console used by command prompt, PowerShell, and the Windows Subsystem for Linux. It does not affect the modern Windows Terminal.
feerrenrut marked this conversation as resolved.
Show resolved Hide resolved
In Windows 10 version 1709, Microsoft [added support for its UI Automation API to the console https://devblogs.microsoft.com/commandline/whats-new-in-windows-console-in-windows-10-fall-creators-update/], bringing vastly improved performance and stability for screen readers that support it.
In situations where UI Automation is unavailable or known to result in an inferior user experience, NVDA's legacy console support is available as a fallback.
The Windows Console support combo box has three options:
- Automatic: Uses UI Automation in consoles on Windows 10 version 1803 and later. This option is recommended and set by default.
- Prefer UIA: Uses UI Automation in consoles if available, even on Windows versions with incomplete or buggy implementations. While this limited functionality may be useful (and even sufficient for your usage), use of this option is entirely at your own risk and no support for it will be provided.
- Legacy: UI Automation in the Windows Console will be completely disabled, so the legacy fallback will always be used.
feerrenrut marked this conversation as resolved.
Show resolved Hide resolved
-

==== Speak passwords in UIA consoles ====[AdvancedSettingsWinConsoleSpeakPasswords]
This setting controls whether characters are spoken by [speak typed characters #KeyboardSettingsSpeakTypedCharacters] or [speak typed words #KeyboardSettingsSpeakTypedWords] in situations where the screen does not update (such as password entry) in the Windows Console with UI automation support enabled. For security purposes, this setting should be left disabled. However, you may wish to enable it if you experience performance issues or instability with typed character and/or word reporting while using NVDA's new experimental console support.
==== Speak passwords in Windows Console ====[AdvancedSettingsWinConsoleSpeakPasswords]
This setting controls whether characters are spoken by [speak typed characters #KeyboardSettingsSpeakTypedCharacters] or [speak typed words #KeyboardSettingsSpeakTypedWords] in situations where the screen does not update (such as password entry) in the Windows Console with UI automation support enabled.
For security purposes, this setting should be left disabled.
However, you may wish to enable it if you experience performance issues or instability with typed character and/or word reporting in consoles, or work in trusted environments and prefer password announcement.

==== Automatically set system focus to focusable elements in Browse Mode ====[BrowseModeSettingsAutoFocusFocusableElements]
Key: NVDA+8
Expand Down