|
8 | 8 | # Burman's Computer and Education Ltd. |
9 | 9 |
|
10 | 10 | import itertools |
| 11 | +from _ctypes import COMError |
11 | 12 | from typing import ( |
12 | 13 | List, |
13 | 14 | Optional, |
@@ -3315,6 +3316,44 @@ def script_braille_cycleShowSelection(self, gesture: inputCore.InputGesture) -> |
3315 | 3316 | msg = _("Braille show selection %s") % BoolFlag[nextName].displayString |
3316 | 3317 | ui.message(msg) |
3317 | 3318 |
|
| 3319 | + @script( |
| 3320 | + # Translators: Input help mode message for cycle through |
| 3321 | + # braille route review cursor and system caret command. |
| 3322 | + description=_("Cycle through the braille route review cursor and system caret states"), |
| 3323 | + category=SCRCAT_BRAILLE |
| 3324 | + ) |
| 3325 | + def script_braille_cycleRouteReviewCursorAndSystemCaret(self, gesture: inputCore.InputGesture) -> None: |
| 3326 | + If braille is not tethered to focus, set next state of braille route review cursor and system caret. |
| 3327 | + # State is reported using ui.message. |
| 3328 | + # Unavailable if tether is to focus. |
| 3329 | + if TetherTo.FOCUS.value == config.conf["braille"]["tetherTo"]: |
| 3330 | + ui.message( |
| 3331 | + _( |
| 3332 | + # Translators: Gesture is unavailable because braille tether is to focus. |
| 3333 | + "Action unavailable. Braille is tethered to focus" |
| 3334 | + ) |
| 3335 | + ) |
| 3336 | + return |
| 3337 | + featureFlag: FeatureFlag = config.conf["braille"]["routeReviewCursorAndSystemCaret"] |
| 3338 | + boolFlag: BoolFlag = featureFlag.enumClassType |
| 3339 | + values = [x.value for x in boolFlag] |
| 3340 | + currentValue = featureFlag.value.value |
| 3341 | + nextValueIndex = (currentValue % len(values)) + 1 |
| 3342 | + nextName: str = boolFlag(nextValueIndex).name |
| 3343 | + config.conf["braille"]["routeReviewCursorAndSystemCaret"] = nextName |
| 3344 | + featureFlag = config.conf["braille"]["routeReviewCursorAndSystemCaret"] |
| 3345 | + if featureFlag.isDefault(): |
| 3346 | + msg = _( |
| 3347 | + # Translators: Used when reporting braille route review cursor and system caret |
| 3348 | + # state (default behavior). |
| 3349 | + "Braille route review cursor and system caret default (%s)" |
| 3350 | + ) % featureFlag.behaviorOfDefault.displayString |
| 3351 | + else: |
| 3352 | + # Translators: Reports which route review cursor and system caret state is used |
| 3353 | + # (disabled or enabled). |
| 3354 | + msg = _("Braille route review cursor and system caret %s") % BoolFlag[nextName].displayString |
| 3355 | + ui.message(msg) |
| 3356 | + |
3318 | 3357 | @script( |
3319 | 3358 | # Translators: Input help mode message for report clipboard text command. |
3320 | 3359 | description=_("Reports the text on the Windows clipboard"), |
@@ -3483,8 +3522,73 @@ def script_braille_scrollForward(self, gesture): |
3483 | 3522 | description=_("Routes the cursor to or activates the object under this braille cell"), |
3484 | 3523 | category=SCRCAT_BRAILLE |
3485 | 3524 | ) |
3486 | | - def script_braille_routeTo(self, gesture): |
| 3525 | + def script_braille_routeTo(self, gesture: inputCore.InputGesture) -> None: |
| 3526 | + # Routes cursor to or activates the object under this braille cell. |
3487 | 3527 | braille.handler.routeTo(gesture.routingIndex) |
| 3528 | + # Try to ensure that braille message can be dismissed. |
| 3529 | + if braille.handler.buffer is braille.handler.messageBuffer: |
| 3530 | + return |
| 3531 | + # To proceed braille should be tethered to review cursor which means |
| 3532 | + # that tether is automatic (and review cursor is shown in braille) |
| 3533 | + # or tether is to review cursor. |
| 3534 | + # "Route review cursor and system caret" should be also enabled |
| 3535 | + # in braille settings. |
| 3536 | + if ( |
| 3537 | + braille.handler.getTether() != TetherTo.REVIEW.value |
| 3538 | + or not config.conf["braille"]["routeReviewCursorAndSystemCaret"] |
| 3539 | + ): |
| 3540 | + return |
| 3541 | + navigatorObject: NVDAObject = api.getNavigatorObject() |
| 3542 | + if not isinstance(navigatorObject, NVDAObject): |
| 3543 | + ui.message( |
| 3544 | + _( |
| 3545 | + # Translators: There is no focusable object e.g. cannot use |
| 3546 | + # tab and shift tab to move to controls. |
| 3547 | + "No focus" |
| 3548 | + ) |
| 3549 | + ) |
| 3550 | + return |
| 3551 | + # Try to set focus to current navigator object |
| 3552 | + if navigatorObject != api.getFocusObject(): |
| 3553 | + # This script is available on the lock screen via getSafeScripts, as such |
| 3554 | + # ensure the navigatorObject does not contain secure information |
| 3555 | + # before setting focus to this object |
| 3556 | + if objectBelowLockScreenAndWindowsIsLocked(navigatorObject): |
| 3557 | + ui.message(gui.blockAction.Context.WINDOWS_LOCKED.translatedMessage) |
| 3558 | + return |
| 3559 | + # When trying to move focus in Word 2019 system menu, setFocus |
| 3560 | + # caused _ctypes.COMError. |
| 3561 | + try: |
| 3562 | + # It is not always possible to move caret, but setting focus can |
| 3563 | + # provide more possibilities such as activating controls with routing |
| 3564 | + # buttons. |
| 3565 | + navigatorObject.setFocus() |
| 3566 | + except COMError: |
| 3567 | + log.debug("Set focus failed.", exc_info=True) |
| 3568 | + return |
| 3569 | + review: textInfos.TextInfo = api.getReviewPosition() |
| 3570 | + # This script is available on the lock screen via getSafeScripts, as such |
| 3571 | + # ensure the review object does not contain secure information |
| 3572 | + # before displaying this object in braille line |
| 3573 | + if objectBelowLockScreenAndWindowsIsLocked(review.obj): |
| 3574 | + ui.reviewMessage(gui.blockAction.Context.WINDOWS_LOCKED.translatedMessage) |
| 3575 | + return |
| 3576 | + # If not in browse mode, try to reduce "no caret" messages. |
| 3577 | + if not api.isObjectInActiveTreeInterceptor(navigatorObject): |
| 3578 | + if not navigatorObject._hasNavigableText: |
| 3579 | + log.debug(f"Navigator object {navigatorObject} is not navigable") |
| 3580 | + return |
| 3581 | + try: |
| 3582 | + review.updateCaret() |
| 3583 | + except NotImplementedError: |
| 3584 | + log.debug("Unable to move caret", exc_info=True) |
| 3585 | + # Translators: Reported when trying to move caret to the position |
| 3586 | + # of the review cursor but there is no caret. |
| 3587 | + ui.message( |
| 3588 | + _( |
| 3589 | + "No caret" |
| 3590 | + ) |
| 3591 | + ) |
3488 | 3592 |
|
3489 | 3593 | @script( |
3490 | 3594 | # Translators: Input help mode message for Braille report formatting command. |
|
0 commit comments