From 0c3ceaaf04be5a991493305ddc55c0898bc56f38 Mon Sep 17 00:00:00 2001 From: Bill Dengler Date: Sun, 8 May 2022 16:13:02 -0400 Subject: [PATCH] Make POSITION_FIRST and POSITION_LAST relative to visible text in FORMATTED consoles. The ability for users to explore all console text enabled by #12669 has been well appreciated, but it poses problems in paginated output (less, more, etc.) as the review cursor jump to top/bottom commands are relative to the entire buffer, which can grow quite large. To ease review of paginated output, make these commands jump relative to visible (not full) text. Note that it is now impossible to jump quickly to the top/bottom of the entire buffer. Closes #13157. --- source/NVDAObjects/UIA/winConsoleUIA.py | 42 +++++++++++++++++++------ 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/source/NVDAObjects/UIA/winConsoleUIA.py b/source/NVDAObjects/UIA/winConsoleUIA.py index 54cad8a662e..b472f2f99b8 100644 --- a/source/NVDAObjects/UIA/winConsoleUIA.py +++ b/source/NVDAObjects/UIA/winConsoleUIA.py @@ -20,16 +20,21 @@ class ConsoleUIATextInfo(UIATextInfo): - "A TextInfo implementation for consoles with an IMPROVED, but not FORMATTED, API level." + "A TextInfo implementation for consoles with a FORMATTED API level." + + # #13157: In FORMATTED consoles, the review cursor is not bounded to the + # visible text, allowing text to be freely explored. + # However, it is often useful to jump to the top or bottom of a screen of + # text when viewing paginated output. To enable this use case, make + # POSITION_FIRST and POSITION_LAST relative to the visible text. + _RESTRICT_TO_VISIBLE_POSITIONS = ( + textInfos.POSITION_FIRST, + textInfos.POSITION_LAST + ) + def __init__(self, obj, position, _rangeObj=None): collapseToEnd = None - # We want to limit textInfos to just the visible part of the console. - # Therefore we specifically handle POSITION_FIRST, POSITION_LAST and POSITION_ALL. - if not _rangeObj and position in ( - textInfos.POSITION_FIRST, - textInfos.POSITION_LAST, - textInfos.POSITION_ALL - ): + if not _rangeObj and position in self._RESTRICT_TO_VISIBLE_POSITIONS: try: _rangeObj, collapseToEnd = self._getBoundingRange(obj, position) except (COMError, RuntimeError): @@ -61,6 +66,20 @@ def _getBoundingRange(self, obj, position): collapseToEnd = True return (_rangeObj, collapseToEnd) + +class ConsoleUIATextInfoBounded(ConsoleUIATextInfo): + "A TextInfo implementation for consoles with an IMPROVED, but not FORMATTED, API level." + + # Since pre-FORMATTED consoles have thousands of empty lines at the end of + # output, we want to limit textInfos to just the visible part of the + # console. Therefore we specifically handle POSITION_FIRST, POSITION_LAST + # and POSITION_ALL. + _RESTRICT_TO_VISIBLE_POSITIONS = ( + textInfos.POSITION_FIRST, + textInfos.POSITION_LAST, + textInfos.POSITION_ALL + ) + def move(self, unit, direction, endPoint=None): oldInfo = None if self.basePosition != textInfos.POSITION_CARET: @@ -369,9 +388,9 @@ def _get_TextInfo(self): ConsoleUIATextInfoWorkaroundEndInclusive fixes expand/collapse and implements word movement.""" if self.apiLevel >= WinConsoleAPILevel.FORMATTED: - return UIATextInfo # No TextInfo workarounds needed - elif self.apiLevel >= WinConsoleAPILevel.IMPROVED: return ConsoleUIATextInfo + elif self.apiLevel >= WinConsoleAPILevel.IMPROVED: + return ConsoleUIATextInfoBounded else: return ConsoleUIATextInfoWorkaroundEndInclusive @@ -420,6 +439,9 @@ def findExtraOverlayClasses(obj, clsList): class WinTerminalUIA(EnhancedTermTypedCharSupport): + def _get_TextInfo(self): + return ConsoleUIATextInfo + def event_UIA_notification(self, **kwargs): """ In an upcoming terminal release, UIA notification events will be sent