Skip to content

Commit

Permalink
Several fixes to native selection mode (nvaccess#16129)
Browse files Browse the repository at this point in the history
Fixes nvaccess#16064
Fixes nvaccess#16097

Summary of the issue:
Native selection mode can be enabled in unsupported Gecko, such as Thunderbird 115.x nvaccess#16064: turning on native selection mode in thunderbird 115 would cause errors when moving with the arrow keys as IAccessibleTextSelectionContainer is unavailable.
Wrong message reported when toggling native selection in Word nvaccess#16097: NVDA is misleading in MS Word browse mode when it says that native selection mode is not supported when trying to toggle it on, as MS word Browse mode does move the caret / selection, thus it has always used native selection mode.. It is just you can't toggle it off.
Description of user facing changes
In firefox, If NVDA fails to update the native selection when turning on native selection mode, it is now left off, and the user is
notified that native selection mode is not supported. this stops errors when moving with the arrow keys in Thunderbird after turning on native selection mode.
NVDA no longer incorrectly alerts the user that native selection mode is not supported in Microsoft Word. Rather, the message state that it canot be turned off.
when copying text with control+c in Microsoft Word with Browse mode on, formatting is now also copied, fulfilling the expectation of a native selection mode.
Description of development approach
Gecko virtualBuffer's updateAppSelection method: if the selection is collapsed, don't try fetching information for the selection, instead just clear the app selection. This error was previously silently ignored.
In UIA Browse mode documents, _nativeAppSelectionMode is now set to True, as this correctly reflects that UIA browse mode documents move the native selection.
BrowseMode document's toggleNativeSelectionMode script:
Tailor the message reported if native selection mode is not supported (by looking at _nativeSelectionMode). If _nativeSelectionMode is True, then the message is changed to state it can't be turned off.
If updateappSelection fails when turning on native selection mode, log the error, turn it off, and alert the user that it is not supported.
In MS word, suppress the "copy" UIA notification, if in MS word Browse mode. Otherwise there would be double speaking along with the message in cursorManager's copyToclipboard script when doing a native copy.
  • Loading branch information
michaelDCurran authored and Adriani90 committed Mar 13, 2024
1 parent 35268bf commit 8228ae3
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 26 deletions.
1 change: 1 addition & 0 deletions source/NVDAObjects/UIA/web.py
Expand Up @@ -487,6 +487,7 @@ def HeadingControlQuicknavIterator(itemType, document, position, direction="next

class UIAWebTreeInterceptor(cursorManager.ReviewCursorManager, UIABrowseModeDocument):
TextInfo = UIABrowseModeDocumentTextInfo
_nativeAppSelectionMode = False

def makeTextInfo(self, position):
try:
Expand Down
6 changes: 6 additions & 0 deletions source/NVDAObjects/UIA/wordDocument.py
Expand Up @@ -554,6 +554,12 @@ def event_UIA_notification(self, activityId=None, **kwargs):
# such as "delete back word" when Control+Backspace is pressed.
if activityId == "AccSN2": # Delete activity ID
return
# copy to clipboard
if activityId == 'AccSN3':
ti = self.treeInterceptor
if ti and not ti.passThrough:
# Browse mode provides its own copy to clipboard message.
return
super(WordDocument, self).event_UIA_notification(**kwargs)

# The following overide of the EditableText._caretMoveBySentenceHelper private method
Expand Down
1 change: 1 addition & 0 deletions source/UIAHandler/browseMode.py
Expand Up @@ -373,6 +373,7 @@ class UIABrowseModeDocument(UIADocumentWithTableNavigation,browseMode.BrowseMode
# UIA browseMode documents cannot remember caret positions across loads (I.e. when going back a page in Edge)
# Because UIA TextRanges are opaque and are tied specifically to one particular document.
shouldRememberCaretPositionAcrossLoads=False
_nativeAppSelectionMode = True

def event_UIA_activeTextPositionChanged(self, obj, nextHandler, textRange=None):
if not self.isReady:
Expand Down
29 changes: 19 additions & 10 deletions source/browseMode.py
Expand Up @@ -2036,21 +2036,30 @@ def clearAppSelection(self):
)
def script_toggleNativeAppSelectionMode(self, gesture: inputCore.InputGesture):
if not self._nativeAppSelectionModeSupported:
# Translators: the message when native selection mode is not available in this browse mode document.
ui.message(_("Native selection mode unsupported in this document"))
if not self._nativeAppSelectionMode:
# Translators: the message when native selection mode is not available in this browse mode document.
ui.message(_("Native selection mode unsupported in this browse mode document"))
else:
# Translators: the message when native selection mode cannot be turned off in this browse mode document.
ui.message(_("Native selection mode cannot be turned off in this browse mode document"))
return
self._nativeAppSelectionMode = not self._nativeAppSelectionMode
if self._nativeAppSelectionMode:
# Translators: reported when native selection mode is toggled on.
ui.message(_("Native app selection mode enabled."))
nativeAppSelectionModeOn = not self._nativeAppSelectionMode
if nativeAppSelectionModeOn:
try:
self.updateAppSelection()
except NotImplementedError:
pass
log.debugWarning("updateAppSelection failed", exc_info=True)
# Translators: the message when native selection mode is not available in this browse mode document.
ui.message(_("Native selection mode unsupported in this document"))
return
self._nativeAppSelectionMode = True
# Translators: reported when native selection mode is toggled on.
ui.message(_("Native app selection mode enabled"))
else:
# Translators: reported when native selection mode is toggled off.
ui.message(_("Native app selection mode disabled."))
try:
self.clearAppSelection()
except NotImplementedError:
pass
log.debugWarning("clearAppSelection failed", exc_info=True)
self._nativeAppSelectionMode = False
# Translators: reported when native selection mode is toggled off.
ui.message(_("Native app selection mode disabled"))
36 changes: 20 additions & 16 deletions source/virtualBuffers/gecko_ia2.py
Expand Up @@ -699,22 +699,26 @@ def updateAppSelection(self):
except COMError as e:
raise NotImplementedError from e
selInfo = self.makeTextInfo(textInfos.POSITION_SELECTION)
selFields = selInfo.getTextWithFields()
ia2Sel = _Ia2Selection()

log.debug("checking fields...")
self._getStartSelection(ia2Sel, selFields)
self._getEndSelection(ia2Sel, selFields)

log.debug("setting selection...")
r = IA2TextSelection(
ia2Sel.startObj,
ia2Sel.startOffset,
ia2Sel.endObj,
ia2Sel.endOffset,
False
)
paccTextSelectionContainer.SetSelections(1, byref(r))
if not selInfo.isCollapsed:
selFields = selInfo.getTextWithFields()
ia2Sel = _Ia2Selection()

log.debug("checking fields...")
self._getStartSelection(ia2Sel, selFields)
self._getEndSelection(ia2Sel, selFields)

log.debug("setting selection...")
r = IA2TextSelection(
ia2Sel.startObj,
ia2Sel.startOffset,
ia2Sel.endObj,
ia2Sel.endOffset,
False
)
paccTextSelectionContainer.SetSelections(1, byref(r))
else: # No selection
r = IA2TextSelection(None, 0, None, 0, False)
paccTextSelectionContainer.SetSelections(0, byref(r))

def clearAppSelection(self):
"""Clear the native selection in the application."""
Expand Down
1 change: 1 addition & 0 deletions user_docs/en/changes.t2t
Expand Up @@ -77,6 +77,7 @@ Windows 8.1 is the minimum Windows version supported.
- A new Native Selection mode (toggled by ``NVDA+shift+f10``) is now available in NVDA's browse mode for Mozilla Firefox.
When turned on, selecting text in browse mode will also manipulate Firefox's own native selection.
Copying text with ``control+c`` will pass straight through to Firefox, thus copying the rich content, rather than NVDA's plain text representation. (#15830)
- When copying text in Microsoft Word with NVDA's browse mode enabled, formatting is now also included. (#16129)
- A new "on-demand" speech mode has been added.
When speech is on-demand, NVDA does not speak automatically (e.g. when moving the cursor) but still speaks when calling commands whose goal is explicitly to report something (e.g. report window title). (#481, @CyrilleB79)
- In the Speech category of NVDA's settings, it is now possible to exclude unwanted speech modes from the Cycle speech modes command (``NVDA+s``). (#15806, @lukaszgo1)
Expand Down

0 comments on commit 8228ae3

Please sign in to comment.