Skip to content

Commit 64348e2

Browse files
authored
Merge bb55e64 into c22509b
2 parents c22509b + bb55e64 commit 64348e2

1 file changed

Lines changed: 36 additions & 24 deletions

File tree

source/NVDAObjects/UIA/winConsoleUIA.py

Lines changed: 36 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# A part of NonVisual Desktop Access (NVDA)
22
# This file is covered by the GNU General Public License.
33
# See the file COPYING for more details.
4-
# Copyright (C) 2019-2020 Bill Dengler
4+
# Copyright (C) 2019-2021 Bill Dengler
55

66
import ctypes
77
import NVDAHelper
@@ -16,7 +16,7 @@
1616
from ..window import Window
1717

1818

19-
class consoleUIATextInfo(UIATextInfo):
19+
class TextInfo(UIATextInfo):
2020
def __init__(self, obj, position, _rangeObj=None):
2121
collapseToEnd = None
2222
# We want to limit textInfos to just the visible part of the console.
@@ -33,7 +33,7 @@ def __init__(self, obj, position, _rangeObj=None):
3333
log.warning("Couldn't get bounding range for console", exc_info=True)
3434
# Fall back to presenting the entire buffer.
3535
_rangeObj, collapseToEnd = None, None
36-
super(consoleUIATextInfo, self).__init__(obj, position, _rangeObj)
36+
super(TextInfo, self).__init__(obj, position, _rangeObj)
3737
if collapseToEnd is not None:
3838
self.collapse(end=collapseToEnd)
3939

@@ -90,7 +90,7 @@ def move(self, unit, direction, endPoint=None):
9090

9191
def _move(self, unit, direction, endPoint=None):
9292
"Perform a move without respect to bounding."
93-
return super(consoleUIATextInfo, self).move(unit, direction, endPoint)
93+
return super(TextInfo, self).move(unit, direction, endPoint)
9494

9595
def __ne__(self, other):
9696
"""Support more accurate caret move detection."""
@@ -99,17 +99,17 @@ def __ne__(self, other):
9999
def _get_text(self):
100100
# #10036: return a space if the text range is empty.
101101
# Consoles don't actually store spaces, the character is merely left blank.
102-
res = super(consoleUIATextInfo, self)._get_text()
102+
res = super(TextInfo, self)._get_text()
103103
if not res:
104104
return ' '
105105
else:
106106
return res
107107

108108

109-
class consoleUIATextInfoPre21H1(consoleUIATextInfo):
110-
"""Fixes expand/collapse on end inclusive UIA text ranges, uses rangeFromPoint
111-
instead of broken GetVisibleRanges for bounding, and implements word
112-
movement support."""
109+
class TextInfoWorkaroundEndInclusive(TextInfo):
110+
"""Implementation of various workarounds for pre-microsoft/terminal#4018
111+
conhost: fixes expand/collapse, uses rangeFromPoint instead of broken
112+
GetVisibleRanges for bounding, and implements word movement support."""
113113
def _getBoundingRange(self, obj, position):
114114
# We could use IUIAutomationTextRange::getVisibleRanges, but it seems very broken in consoles
115115
# once more than a few screens worth of content has been written to the console.
@@ -139,12 +139,12 @@ def _getBoundingRange(self, obj, position):
139139
return (_rangeObj, None)
140140

141141
def collapse(self, end=False):
142-
"""Works around a UIA bug on Windows 10 versions before 21H1.
142+
"""Works around a UIA bug on conhost versions before microsoft/terminal#4018.
143143
When collapsing, consoles seem to incorrectly push the start of the
144144
textRange back one character.
145145
Correct this by bringing the start back up to where the end is."""
146146
oldInfo = self.copy()
147-
super(consoleUIATextInfo, self).collapse(end=end)
147+
super(TextInfo, self).collapse(end=end)
148148
if not end:
149149
self._rangeObj.MoveEndpointByRange(
150150
UIAHandler.TextPatternRangeEndpoint_Start,
@@ -153,7 +153,7 @@ def collapse(self, end=False):
153153
)
154154

155155
def compareEndPoints(self, other, which):
156-
"""Works around a UIA bug on Windows 10 versions before 21H1.
156+
"""Works around a UIA bug on conhost versions before microsoft/terminal#4018.
157157
Even when a console textRange's start and end have been moved to the
158158
same position, the console incorrectly reports the end as being
159159
past the start.
@@ -168,7 +168,7 @@ def compareEndPoints(self, other, which):
168168

169169
def setEndPoint(self, other, which):
170170
"""Override of L{textInfos.TextInfo.setEndPoint}.
171-
Works around a UIA bug on Windows 10 versions before 21H1 that means we can
171+
Works around a UIA bug on conhost versions before microsoft/terminal#4018 that means we can
172172
not trust the "end" endpoint of a collapsed (empty) text range
173173
for comparisons.
174174
"""
@@ -205,11 +205,11 @@ def expand(self, unit):
205205
wordEndPoints[1]
206206
)
207207
else:
208-
return super(consoleUIATextInfo, self).expand(unit)
208+
return super(TextInfo, self).expand(unit)
209209

210210
def _move(self, unit, direction, endPoint=None):
211211
if unit == textInfos.UNIT_WORD and direction != 0:
212-
# On Windows 10 versions before 21H1, UIA doesn't implement word
212+
# On conhost versions before microsoft/terminal#4018, UIA doesn't implement word
213213
# movement, so we need to do it manually.
214214
# Relative to the current line, calculate our offset
215215
# and the current word's offsets.
@@ -261,7 +261,7 @@ def _move(self, unit, direction, endPoint=None):
261261
endPoint=endPoint
262262
)
263263
else: # moving by a unit other than word
264-
res = super(consoleUIATextInfo, self).move(unit, direction,
264+
res = super(TextInfo, self).move(unit, direction,
265265
endPoint)
266266
if not endPoint:
267267
# #10191: IUIAutomationTextRange::move in consoles does not correctly produce a collapsed range
@@ -309,7 +309,7 @@ def _getWordOffsetsInThisLine(self, offset, lineInfo):
309309
)
310310

311311
def _isCollapsed(self):
312-
"""Works around a UIA bug on Windows 10 versions before 21H1 that means we
312+
"""Works around a UIA bug on conhost versions before microsoft/terminal#4018 that means we
313313
cannot trust the "end" endpoint of a collapsed (empty) text range
314314
for comparisons.
315315
Instead we check to see if we can get the first character from the
@@ -348,19 +348,31 @@ def _get_windowThreadID(self):
348348
threadID = super().windowThreadID
349349
return threadID
350350

351-
def _get_is21H1Plus(self):
352-
"Returns whether this is a newer version of Windows Console with an improved UIA implementation."
351+
def _get_isImprovedTextRangeAvailable(self):
352+
"""This property determines whether microsoft/terminal#4495
353+
and by extension microsoft/terminal#4018 are present in this conhost.
354+
In consoles before these PRs, a number of workarounds were needed
355+
in our UIA implementation. However, these do not fix all bugs and are
356+
problematic on newer console releases. This property is therefore used
357+
internally to determine whether to activate workarounds and as a
358+
convenience when debugging.
359+
"""
353360
# microsoft/terminal#4495: In newer consoles,
354361
# IUIAutomationTextRange::getVisibleRanges returns one visible range.
362+
# Therefore, if exactly one range is returned, it is almost definitely a newer console.
355363
return self.UIATextPattern.GetVisibleRanges().length == 1
356364

357365
def _get_TextInfo(self):
358366
"""Overriding _get_TextInfo and thus the TextInfo property
359367
on NVDAObjects.UIA.UIA
360-
consoleUIATextInfo bounds review to the visible text.
361-
ConsoleUIATextInfoPre21H1 fixes expand/collapse and implements word
362-
movement."""
363-
return consoleUIATextInfo if self.is21H1Plus else consoleUIATextInfoPre21H1
368+
TextInfo bounds review to the visible text.
369+
TextInfoWorkaroundEndInclusive fixes expand/collapse and implements
370+
word movement."""
371+
return (
372+
TextInfo
373+
if self.isImprovedTextRangeAvailable
374+
else TextInfoWorkaroundEndInclusive
375+
)
364376

365377
def detectPossibleSelectionChange(self):
366378
try:
@@ -384,4 +396,4 @@ def findExtraOverlayClasses(obj, clsList):
384396

385397
class WinTerminalUIA(EnhancedTermTypedCharSupport):
386398
def _get_TextInfo(self):
387-
return consoleUIATextInfo
399+
return TextInfo

0 commit comments

Comments
 (0)