diff --git a/source/NVDAObjects/UIA/__init__.py b/source/NVDAObjects/UIA/__init__.py index 3c78ae7dd36..2cd862ac9ad 100644 --- a/source/NVDAObjects/UIA/__init__.py +++ b/source/NVDAObjects/UIA/__init__.py @@ -26,7 +26,6 @@ import textInfos from logHandler import log from UIAUtils import * -from UIAUtils import shouldUseUIAConsole from NVDAObjects.window import Window from NVDAObjects import NVDAObjectTextInfo, InvalidNVDAObject from NVDAObjects.behaviors import ( @@ -930,7 +929,7 @@ def findOverlayClasses(self,clsList): # Support Windows Console's UIA interface if ( self.windowClassName == "ConsoleWindowClass" - and shouldUseUIAConsole() + and config.conf['UIA']['winConsoleImplementation'] == "UIA" ): from . import winConsoleUIA winConsoleUIA.findExtraOverlayClasses(self, clsList) diff --git a/source/NVDAObjects/UIA/winConsoleUIA.py b/source/NVDAObjects/UIA/winConsoleUIA.py index a987c4105e3..f1717d67f1c 100644 --- a/source/NVDAObjects/UIA/winConsoleUIA.py +++ b/source/NVDAObjects/UIA/winConsoleUIA.py @@ -12,6 +12,7 @@ from comtypes import COMError from UIAUtils import isTextRangeOffscreen +from winVersion import isWin10 from . import UIATextInfo from ..behaviors import KeyboardHandlerBasedTypedCharSupport from ..window import Window @@ -48,13 +49,15 @@ def __init__(self, obj, position, _rangeObj=None): _rangeObj = first._rangeObj super(consoleUIATextInfo, self).__init__(obj, position, _rangeObj) - def collapse(self, end=False): - """Works around a UIA bug on Windows 10 1803 and later.""" + 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) # 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. - oldInfo = self.copy() - super(consoleUIATextInfo, self).collapse(end=end) + oldInfo=self.copy() + super(consoleUIATextInfo,self).collapse(end=end) if not end: self._rangeObj.MoveEndpointByRange( UIAHandler.TextPatternRangeEndpoint_Start, @@ -258,9 +261,9 @@ def _getWordOffsetsInThisLine(self, offset, lineInfo): min(end.value, max(1, lineTextLen - 2)) ) - def __ne__(self, other): + def __ne__(self,other): """Support more accurate caret move detection.""" - return not self == other + return not self==other def _get_text(self): # #10036: return a space if the text range is empty. diff --git a/source/NVDAObjects/behaviors.py b/source/NVDAObjects/behaviors.py index c392ed1f1cd..43fc2f0911d 100755 --- a/source/NVDAObjects/behaviors.py +++ b/source/NVDAObjects/behaviors.py @@ -436,7 +436,7 @@ def event_typedCharacter(self, ch): config.conf['keyboard']['speakTypedCharacters'] or config.conf['keyboard']['speakTypedWords'] ) - and not config.conf['terminals']['speakPasswords'] + and not config.conf['UIA']['winConsoleSpeakPasswords'] and self._supportsTextChange ): self._queuedChars.append(ch) diff --git a/source/UIAUtils.py b/source/UIAUtils.py index a20ea4b49e7..3c01776a8af 100644 --- a/source/UIAUtils.py +++ b/source/UIAUtils.py @@ -1,14 +1,12 @@ -# A part of NonVisual Desktop Access (NVDA) -# 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. +#A part of NonVisual Desktop Access (NVDA) +#Copyright (C) 2015-2016 NV Access Limited +#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): """ @@ -226,22 +224,3 @@ def getValue(self,ID,ignoreMixedValues=False): if not ignoreMixedValues and val==UIAHandler.handler.ReservedMixedAttributeValue: 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(1809) diff --git a/source/_UIAHandler.py b/source/_UIAHandler.py index 6d6058c580f..0583c6250e7 100644 --- a/source/_UIAHandler.py +++ b/source/_UIAHandler.py @@ -500,10 +500,9 @@ def IUIAutomationNotificationEventHandler_HandleNotificationEvent( def _isBadUIAWindowClassName(self, windowClass): "Given a windowClassName, returns True if this is a known problematic UIA implementation." - if ( - windowClass == "ConsoleWindowClass" - and not UIAUtils.shouldUseUIAConsole() - ): + # #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": return True return windowClass in badUIAWindowClassNames diff --git a/source/config/profileUpgradeSteps.py b/source/config/profileUpgradeSteps.py index 0a8bf9d05e1..582df076384 100644 --- a/source/config/profileUpgradeSteps.py +++ b/source/config/profileUpgradeSteps.py @@ -60,3 +60,4 @@ def upgradeConfigFrom_2_to_3(profile): if "terminals" not in profile: profile["terminals"] = {} profile["terminals"]["speakPasswords"] = speakPasswords + \ No newline at end of file diff --git a/source/gui/settingsDialogs.py b/source/gui/settingsDialogs.py index 7ef81bc593a..d3c44bd6fe6 100644 --- a/source/gui/settingsDialogs.py +++ b/source/gui/settingsDialogs.py @@ -1,11 +1,9 @@ # -*- coding: UTF-8 -*- -# settingsDialogs.py -# A part of NonVisual Desktop Access (NVDA) -# Copyright (C) 2006-2019 NV Access Limited, Peter Vágner, Aleksey Sadovoy, -# Rui Batista, Joseph Lee, Heiko Folkerts, Zahari Yurukov, Leonard de Ruijter, -# Derek Riemer, Babbage B.V., Davy Kager, Ethan Holliger, Bill Dengler -# This file is covered by the GNU General Public License. -# See the file COPYING for more details. +#settingsDialogs.py +#A part of NonVisual Desktop Access (NVDA) +#Copyright (C) 2006-2019 NV Access Limited, Peter Vágner, Aleksey Sadovoy, Rui Batista, Joseph Lee, Heiko Folkerts, Zahari Yurukov, Leonard de Ruijter, Derek Riemer, Babbage B.V., Davy Kager, Ethan Holliger +#This file is covered by the GNU General Public License. +#See the file COPYING for more details. import logging from abc import abstractmethod, ABCMeta @@ -2271,43 +2269,20 @@ 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 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) - self.consoleCombo.defaultValue = self.consoleVals.index( - self._getDefaultValue(["UIA", "winConsoleImplementation"]) - ) + # 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 checkbox in the + # Advanced settings panel. + label = _("Speak &passwords in UIA consoles (may improve performance)") + self.winConsoleSpeakPasswordsCheckBox=UIAGroup.addItem(wx.CheckBox(self, label=label)) + self.winConsoleSpeakPasswordsCheckBox.SetValue(config.conf["terminals"]["speakPasswords"]) + self.winConsoleSpeakPasswordsCheckBox.defaultValue = self._getDefaultValue(["terminals", "speakPasswords"]) # Translators: This is the label for a group of advanced options in the # Advanced settings panel @@ -2319,14 +2294,7 @@ def __init__(self, parent): sHelper.addItem(terminalsGroup) # Translators: This is the label for a checkbox in the # Advanced settings panel. - label = _("Speak &passwords in Windows Console (may improve performance)") - self.speakPasswordsCheckBox = terminalsGroup.addItem(wx.CheckBox(self, label=label)) - self.speakPasswordsCheckBox.SetValue(config.conf["terminals"]["speakPasswords"]) - self.speakPasswordsCheckBox.defaultValue = self._getDefaultValue(["terminals", "speakPasswords"]) - self.enableConsolePasswordsCheckBox() - # Translators: This is the label for a checkbox in the - # Advanced settings panel. - label = _("Use the new t&yped character support in legacy Windows consoles when available") + label = _("Use the new t&yped character support in Windows Console when available") self.keyboardSupportInLegacyCheckBox=terminalsGroup.addItem(wx.CheckBox(self, label=label)) self.keyboardSupportInLegacyCheckBox.SetValue(config.conf["terminals"]["keyboardSupportInLegacy"]) self.keyboardSupportInLegacyCheckBox.defaultValue = self._getDefaultValue(["terminals", "keyboardSupportInLegacy"]) @@ -2407,13 +2375,6 @@ def __init__(self, parent): ] self.Layout() - def enableConsolePasswordsCheckBox(self, evt=None): - return self.speakPasswordsCheckBox.Enable( - shouldUseUIAConsole(self.consoleVals[ - self.consoleCombo.GetSelection() - ]) - ) - def onOpenScratchpadDir(self,evt): path=config.getScratchpadDir(ensureExists=True) os.startfile(path) @@ -2426,8 +2387,8 @@ def haveConfigDefaultsBeenRestored(self): self._defaultsRestored and self.scratchpadCheckBox.IsChecked() == self.scratchpadCheckBox.defaultValue and self.UIAInMSWordCheckBox.IsChecked() == self.UIAInMSWordCheckBox.defaultValue and - self.consoleCombo.GetSelection() == self.consoleCombo.defaultValue and - self.speakPasswordsCheckBox.IsChecked() == self.speakPasswordsCheckBox.defaultValue and + self.ConsoleUIACheckBox.IsChecked() == (self.ConsoleUIACheckBox.defaultValue=='UIA') and + self.winConsoleSpeakPasswordsCheckBox.IsChecked() == self.winConsoleSpeakPasswordsCheckBox.defaultValue and self.keyboardSupportInLegacyCheckBox.IsChecked() == self.keyboardSupportInLegacyCheckBox.defaultValue and self.autoFocusFocusableElementsCheckBox.IsChecked() == self.autoFocusFocusableElementsCheckBox.defaultValue and self.caretMoveTimeoutSpinControl.GetValue() == self.caretMoveTimeoutSpinControl.defaultValue and @@ -2438,8 +2399,8 @@ def haveConfigDefaultsBeenRestored(self): def restoreToDefaults(self): self.scratchpadCheckBox.SetValue(self.scratchpadCheckBox.defaultValue) self.UIAInMSWordCheckBox.SetValue(self.UIAInMSWordCheckBox.defaultValue) - self.consoleCombo.SetSelection(self.consoleCombo.defaultValue == 'UIA') - self.speakPasswordsCheckBox.SetValue(self.speakPasswordsCheckBox.defaultValue) + self.ConsoleUIACheckBox.SetValue(self.ConsoleUIACheckBox.defaultValue=='UIA') + self.winConsoleSpeakPasswordsCheckBox.SetValue(self.winConsoleSpeakPasswordsCheckBox.defaultValue) self.keyboardSupportInLegacyCheckBox.SetValue(self.keyboardSupportInLegacyCheckBox.defaultValue) self.autoFocusFocusableElementsCheckBox.SetValue(self.autoFocusFocusableElementsCheckBox.defaultValue) self.caretMoveTimeoutSpinControl.SetValue(self.caretMoveTimeoutSpinControl.defaultValue) @@ -2450,11 +2411,11 @@ def onSave(self): log.debug("Saving advanced config") config.conf["development"]["enableScratchpadDir"]=self.scratchpadCheckBox.IsChecked() config.conf["UIA"]["useInMSWordWhenAvailable"]=self.UIAInMSWordCheckBox.IsChecked() - consoleChoice = self.consoleCombo.GetSelection() - config.conf['UIA']['winConsoleImplementation'] = ( - self.consoleVals[consoleChoice] - ) - config.conf["terminals"]["speakPasswords"] = self.speakPasswordsCheckBox.IsChecked() + if self.ConsoleUIACheckBox.IsChecked(): + config.conf['UIA']['winConsoleImplementation'] = "UIA" + else: + config.conf['UIA']['winConsoleImplementation'] = "auto" + config.conf["terminals"]["speakPasswords"]=self.winConsoleSpeakPasswordsCheckBox.IsChecked() config.conf["terminals"]["keyboardSupportInLegacy"]=self.keyboardSupportInLegacyCheckBox.IsChecked() config.conf["virtualBuffers"]["autoFocusFocusableElements"] = self.autoFocusFocusableElementsCheckBox.IsChecked() config.conf["editableText"]["caretMoveTimeoutMs"]=self.caretMoveTimeoutSpinControl.GetValue() diff --git a/user_docs/en/userGuide.t2t b/user_docs/en/userGuide.t2t index d1cf39fdc39..a95a0781fe3 100644 --- a/user_docs/en/userGuide.t2t +++ b/user_docs/en/userGuide.t2t @@ -1779,24 +1779,14 @@ This includes Microsoft Word itself, and also the Microsoft Outlook message view 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. -==== 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. -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 1809 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. -- +==== 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. -==== 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 some terminal programs, such as the Windows Console with UI automation support enabled and Mintty. -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. +==== 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. -==== Use the new typed character support in legacy Windows consoles when available ====[AdvancedSettingsKeyboardSupportInLegacy] -This option enables an alternative method for detecting typed characters in legacy Windows consoles. +==== Use the new typed character support in Windows Console when available ====[AdvancedSettingsKeyboardSupportInLegacy] +This option enables an alternative method for detecting typed characters in Windows command consoles. While it improves performance and prevents some console output from being spelled out, it may be incompatible with some terminal programs. This feature is available and enabled by default on Windows 10 versions 1607, 1703, 1709 and 1803 as well as on newer Windows 10 releases when UI Automation is unavailable or disabled. Warning: with this option enabled, typed characters that do not appear onscreen, such as passwords, will not be suppressed.