Skip to content

Commit d84699e

Browse files
authored
Merge 94b9193 into 3f89b60
2 parents 3f89b60 + 94b9193 commit d84699e

6 files changed

Lines changed: 143 additions & 0 deletions

File tree

source/braille.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
TetherTo,
4343
ReportTableHeaders,
4444
)
45+
from config.featureFlagEnums import ReviewRoutingMovesSystemCaretFlag
4546
from logHandler import log
4647
import controlTypes
4748
import api
@@ -1418,13 +1419,49 @@ def _setCursor(self, info):
14181419
class ReviewTextInfoRegion(TextInfoRegion):
14191420

14201421
allowPageTurns=False
1422+
_isInRoutingAction = False
1423+
1424+
def routeTo(self, braillePos):
1425+
self._isInRoutingAction = True
1426+
try:
1427+
super().routeTo(braillePos)
1428+
finally:
1429+
self._isInRoutingAction = False
14211430

14221431
def _getSelection(self):
14231432
return api.getReviewPosition().copy()
14241433

14251434
def _setCursor(self, info):
1435+
if self._isInRoutingAction:
1436+
reviewRoutingMovesSystemCaret = config.conf["braille"]["reviewRoutingMovesSystemCaret"].calculated()
1437+
configuredTether = config.conf["braille"]["tetherTo"]
1438+
shouldMoveCaretTetheredReview = (
1439+
configuredTether == TetherTo.REVIEW.value
1440+
and reviewRoutingMovesSystemCaret == ReviewRoutingMovesSystemCaretFlag.ALWAYS
1441+
)
1442+
shouldMoveCaretTetheredAuto = (
1443+
configuredTether == TetherTo.AUTO.value
1444+
and reviewRoutingMovesSystemCaret != ReviewRoutingMovesSystemCaretFlag.NEVER
1445+
)
1446+
if shouldMoveCaretTetheredReview or shouldMoveCaretTetheredAuto:
1447+
from displayModel import DisplayModelTextInfo, EditableTextDisplayModelTextInfo
1448+
if (
1449+
isinstance(info, DisplayModelTextInfo)
1450+
and not isinstance(info, EditableTextDisplayModelTextInfo)
1451+
):
1452+
# This region either reviews the screen or an object that has
1453+
# DisplayModelTextInfo without a caret, e.g. IAccessible.ContentGenericClient.
1454+
# In this case, we can at least emulate a kind of caret
1455+
# by trying to focus the object at start of the range.
1456+
obj = info.NVDAObjectAtStart
1457+
if controlTypes.State.FOCUSABLE in obj.states and not obj.hasFocus:
1458+
obj.setFocus()
1459+
else:
1460+
# Update the physical caret
1461+
super()._setCursor(info)
14261462
api.setReviewPosition(info)
14271463

1464+
14281465
def rindex(seq, item, start, end):
14291466
for index in range(end - 1, start - 1, -1):
14301467
if seq[index] == item:

source/config/configSpec.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@
7878
# Timeout after the message will disappear from braille display
7979
messageTimeout = integer(default=4, min=1, max=20)
8080
tetherTo = option("auto", "focus", "review", default="auto")
81+
reviewRoutingMovesSystemCaret = featureFlag(\
82+
optionsEnum="ReviewRoutingMovesSystemCaretFlag", behaviorOfDefault="NEVER")
8183
readByParagraph = boolean(default=false)
8284
wordWrap = boolean(default=true)
8385
focusContextPresentation = option("changedContext", "fill", "scroll", default="changedContext")

source/config/featureFlagEnums.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,24 @@ def _displayStringLabels(self):
8585
MULTI_LINE_BREAK = enum.auto()
8686

8787

88+
class ReviewRoutingMovesSystemCaretFlag(DisplayStringEnum):
89+
@property
90+
def _displayStringLabels(self):
91+
return {
92+
# Translators: Label for setting to move the system caret when routing review cursor with braille.
93+
self.NEVER: _("Never"),
94+
# Translators: Label for setting to move the system caret when routing review cursor with braille.
95+
self.ONLY_WHEN_AUTO_TETHERED: _("Only when tethered automatically"),
96+
# Translators: Label for setting to move the system caret when routing review cursor with braille.
97+
self.ALWAYS: _("Always")
98+
}
99+
100+
DEFAULT = enum.auto()
101+
NEVER = enum.auto()
102+
ONLY_WHEN_AUTO_TETHERED = enum.auto()
103+
ALWAYS = enum.auto()
104+
105+
88106
class WindowsTerminalStrategyFlag(DisplayStringEnum):
89107
"""
90108
A feature flag for defining how new text is calculated in Windows Terminal

source/globalCommands.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3210,6 +3210,42 @@ def script_braille_toggleTether(self, gesture):
32103210
# (braille can be tethered automatically or to either focus or review position).
32113211
ui.message(_("Braille tethered %s") % TetherTo(newTetherChoice).displayString)
32123212

3213+
@script(
3214+
# Translators: Input help mode message for cycle through
3215+
# braille move system caret when Routing review cursor command.
3216+
description=_("Cycle through the braille move system caret when Routing review cursor states"),
3217+
category=SCRCAT_BRAILLE
3218+
)
3219+
def script_braille_cycleReviewRoutingMovesSystemCaret(self, gesture: inputCore.InputGesture) -> None:
3220+
# If braille is not tethered to focus, set next state of
3221+
# braille Move system caret when Routing review cursor.
3222+
if TetherTo.FOCUS.value == config.conf["braille"]["tetherTo"]:
3223+
ui.message(
3224+
# Translators: Reported when action is unavailable because braille tether is to focus.
3225+
_("Action unavailable. Braille is tethered to focus")
3226+
)
3227+
return
3228+
featureFlag: FeatureFlag = config.conf["braille"]["reviewRoutingMovesSystemCaret"]
3229+
reviewRoutingMovesSystemCaretFlag = featureFlag.enumClassType
3230+
values = [x.value for x in reviewRoutingMovesSystemCaretFlag]
3231+
currentValue = featureFlag.value.value
3232+
nextValueIndex = (currentValue % len(values)) + 1
3233+
nextName: str = reviewRoutingMovesSystemCaretFlag(nextValueIndex).name
3234+
config.conf["braille"]["reviewRoutingMovesSystemCaret"] = nextName
3235+
featureFlag = config.conf["braille"]["reviewRoutingMovesSystemCaret"]
3236+
if featureFlag.isDefault():
3237+
msg = _(
3238+
# Translators: Used when reporting braille move system caret when Routing review cursor
3239+
# state (default behavior).
3240+
"Braille move system caret when Routing review cursor default (%s)"
3241+
) % featureFlag.behaviorOfDefault.displayString
3242+
else:
3243+
msg = _(
3244+
# Translators: Used when reporting braille move system caret when Routing review cursor state.
3245+
"Braille move system caret when Routing review cursor %s"
3246+
) % reviewRoutingMovesSystemCaretFlag[nextName].displayString
3247+
ui.message(msg)
3248+
32133249
@script(
32143250
# Translators: Input help mode message for toggle braille focus context presentation command.
32153251
description=_("Toggle the way context information is presented in braille"),

source/gui/settingsDialogs.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3707,12 +3707,30 @@ def makeSettings(self, settingsSizer):
37073707
tetherChoices = [x[1] for x in braille.handler.tetherValues]
37083708
self.tetherList = sHelper.addLabeledControl(tetherListText, wx.Choice, choices=tetherChoices)
37093709
self.bindHelpEvent("BrailleTether", self.tetherList)
3710+
self.tetherList.Bind(wx.EVT_CHOICE, self.onTetherToChange)
37103711
tetherChoice = config.conf["braille"]["tetherTo"]
37113712
selection = [x.value for x in TetherTo].index(tetherChoice)
37123713
self.tetherList.SetSelection(selection)
37133714
if gui._isDebug():
37143715
log.debug("Loading tether settings completed, now at %.2f seconds from start"%(time.time() - startTime))
37153716

3717+
self.brailleReviewRoutingMovesSystemCaretCombo: nvdaControls.FeatureFlagCombo = sHelper.addLabeledControl(
3718+
labelText=_(
3719+
# Translators: This is a label for a combo-box in the Braille settings panel.
3720+
"Move system caret when Ro&uting review cursor"
3721+
),
3722+
wxCtrlClass=nvdaControls.FeatureFlagCombo,
3723+
keyPath=["braille", "reviewRoutingMovesSystemCaret"],
3724+
conf=config.conf,
3725+
)
3726+
self.bindHelpEvent(
3727+
"BrailleSettingsReviewRoutingMovesSystemCaret",
3728+
self.brailleReviewRoutingMovesSystemCaretCombo
3729+
)
3730+
# Setting has no effect when braille is tethered to focus.
3731+
if tetherChoice == TetherTo.FOCUS.value:
3732+
self.brailleReviewRoutingMovesSystemCaretCombo.Disable()
3733+
37163734
# Translators: The label for a setting in braille settings to read by paragraph (if it is checked, the commands to move the display by lines moves the display by paragraphs instead).
37173735
readByParagraphText = _("Read by &paragraph")
37183736
self.readByParagraphCheckBox = sHelper.addItem(wx.CheckBox(self, label=readByParagraphText))
@@ -3778,6 +3796,7 @@ def onSave(self):
37783796
config.conf["braille"]["tetherTo"] = TetherTo.AUTO.value
37793797
else:
37803798
braille.handler.setTether(tetherChoice, auto=False)
3799+
self.brailleReviewRoutingMovesSystemCaretCombo.saveCurrentValueToConf()
37813800
config.conf["braille"]["readByParagraph"] = self.readByParagraphCheckBox.Value
37823801
config.conf["braille"]["wordWrap"] = self.wordWrapCheckBox.Value
37833802
config.conf["braille"]["focusContextPresentation"] = self.focusContextPresentationValues[self.focusContextPresentationList.GetSelection()]
@@ -3796,6 +3815,12 @@ def onBlinkCursorChange(self, evt):
37963815
def onShowMessagesChange(self, evt):
37973816
self.messageTimeoutEdit.Enable(evt.GetSelection() == 1)
37983817

3818+
def onTetherToChange(self, evt: wx.CommandEvent) -> None:
3819+
"""Showss or hides "Move system caret when Routing review cursor" braille setting."""
3820+
tetherChoice = [x.value for x in TetherTo][evt.GetSelection()]
3821+
self.brailleReviewRoutingMovesSystemCaretCombo.Enable(tetherChoice != TetherTo.FOCUS.value)
3822+
3823+
37993824
def showStartErrorForProviders(
38003825
parent: wx.Window,
38013826
providers: List[vision.providerInfo.ProviderInfo],

user_docs/en/userGuide.t2t

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1613,6 +1613,31 @@ In this case, braille will not follow the NVDA navigator during object navigatio
16131613
If you want braille to follow object navigation and text review instead, you need to configure braille to be tethered to review.
16141614
In this case, Braille will not follow system focus and system caret.
16151615

1616+
==== Move system caret when Routing review cursor ====[BrailleSettingsReviewRoutingMovesSystemCaret]
1617+
: Default
1618+
Never
1619+
: Options
1620+
Default (Never), Never, Only when tethered automatically, Always
1621+
:
1622+
1623+
This setting determines if system focus/caret should be also tried to be moved
1624+
with a routing button press when [braille tethering #BrailleTether] is set to automatic
1625+
and braille is temporarily tethered to review, or tethering is explicitly set to tether to the review cursor.
1626+
This option is set to Never by default, meaning that the caret will never move the caret when routing the review cursor.
1627+
1628+
When this option is set to Always, and braille is tethered to review either automatically or explicitly,
1629+
pressing a cursor routing key will also move the system caret when supported.
1630+
When the current review mode is [Screen Review #ScreenReview], there is no physical caret.
1631+
In this case, NVDA tries to focus the object under the text you're routing to.
1632+
You can also set this option to only move the caret when tethered automatically.
1633+
In that case, pressing a cursor routing key will only move the system caret when NVDA tethered to the review cursor automatically,
1634+
whereas no movement of the caret will occur for manual tethering to the review cursor.
1635+
1636+
This option is shown only if "[tether braille #BrailleTether]" is set to "Automatically" or "To focus".
1637+
1638+
To toggle move system caret when Routing review cursor from anywhere,
1639+
please assign a custom gesture using the [Input Gestures dialog #InputGestures].
1640+
16161641
==== Read by Paragraph ====[BrailleSettingsReadByParagraph]
16171642
If enabled, braille will be displayed by paragraphs instead of lines.
16181643
Also, the next and previous line commands will move by paragraph accordingly.

0 commit comments

Comments
 (0)