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

Several fixes to native selection mode #16129

Merged
merged 4 commits into from Feb 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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"))
Comment on lines +2040 to +2044
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"browse mode document" -> "document"

My feeling is that, for users and translators, there is no need to specify here that the document is a browse mode document (no possible ambiguity). This way, the messages are lighter. Feel free to ignore this suggestion if you disagree with me though.

Suggested change
# 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"))
# Translators: the message when native selection mode is not available in this document.
ui.message(_("Native selection mode unsupported in this document"))
else:
# Translators: the message when native selection mode cannot be turned off in this document.
ui.message(_("Native selection mode cannot be turned off in this 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 @@ -39,6 +39,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