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

Remove 'Automatically set system focus to focusable elements' #17598

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 13 additions & 40 deletions source/browseMode.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# A part of NonVisual Desktop Access (NVDA)
# Copyright (C) 2007-2023 NV Access Limited, Babbage B.V., James Teh, Leonard de Ruijter,
# Copyright (C) 2007-2025 NV Access Limited, Babbage B.V., James Teh, Leonard de Ruijter,
# Thomas Stivers, Accessolutions, Julien Cochuyt, Cyrille Bougot
# This file is covered by the GNU General Public License.
# See the file COPYING for more details.
Expand Down Expand Up @@ -694,11 +694,8 @@ def _activatePosition(self, obj=None):
else:
self._activateNVDAObject(obj)

def script_activatePosition(self, gesture):
if config.conf["virtualBuffers"]["autoFocusFocusableElements"]:
self._activatePosition()
else:
self._focusLastFocusableObject(activatePosition=True)
def script_activatePosition(self, gesture: inputCore.InputGesture) -> None:
self._focusLastFocusableObject(activatePosition=True)

# Translators: the description for the activatePosition script on browseMode documents.
script_activatePosition.__doc__ = _("Activates the current object in the document")
Expand All @@ -725,10 +722,9 @@ def _focusLastFocusableObject(self, activatePosition=False):
# Make sure we activate the object at the caret, which is not necessarily focusable.
self._activatePosition()

def script_passThrough(self, gesture):
if not config.conf["virtualBuffers"]["autoFocusFocusableElements"]:
self._focusLastFocusableObject()
api.processPendingEvents(processEventQueue=True)
def script_passThrough(self, gesture: inputCore.InputGesture) -> None:
self._focusLastFocusableObject()
api.processPendingEvents(processEventQueue=True)
gesture.send()

def script_disablePassThrough(self, gesture):
Expand All @@ -744,13 +740,13 @@ def script_disablePassThrough(self, gesture):

script_disablePassThrough.ignoreTreeInterceptorPassThrough = True

def _set_disableAutoPassThrough(self, state):
def _set_disableAutoPassThrough(self, state: bool):
# If the user manually switches to focus mode with NVDA+space, that enables
# pass-through and disables auto pass-through. If auto focusing of focusable
# elements is disabled, NVDA won't have synced the focus to the browse mode
# cursor. However, since the user is switching to focus mode, they probably
# want to interact with the focus, so sync the focus here.
if state and not config.conf["virtualBuffers"]["autoFocusFocusableElements"] and self.passThrough:
if state and self.passThrough:
self._focusLastFocusableObject()
self._disableAutoPassThrough = state

Expand Down Expand Up @@ -1794,14 +1790,8 @@ def _set_selection(self, info, reason=OutputReason.CARET):
and focusObj != api.getFocusObject()
and self._shouldSetFocusToObj(focusObj)
):
followBrowseModeFocus = config.conf["virtualBuffers"]["autoFocusFocusableElements"]
if followBrowseModeFocus or self.passThrough:
if self.passThrough:
focusObj.setFocus()
# Track this object as NVDA having just requested setting focus to it
# So that when NVDA does receive the focus event for it
# It can handle it quietly rather than speaking the new focus.
if followBrowseModeFocus:
self._objPendingFocusBeforeActivate = obj
# Queue the reporting of pass through mode so that it will be spoken after the actual content.
queueHandler.queueFunction(queueHandler.eventQueue, reportPassThrough, self)

Expand Down Expand Up @@ -1863,12 +1853,9 @@ def event_caretMovementFailed(self, obj, nextHandler, gesture=None):
currentExpandedControl = None #: an NVDAObject representing the control that has just been expanded with the collapseOrExpandControl script.

def script_collapseOrExpandControl(self, gesture: inputCore.InputGesture):
if not config.conf["virtualBuffers"]["autoFocusFocusableElements"]:
self._focusLastFocusableObject()
# Give the application time to focus the control.
core.callLater(100, self._collapseOrExpandControl_scriptHelper, gesture)
else:
self._collapseOrExpandControl_scriptHelper(gesture)
self._focusLastFocusableObject()
# Give the application time to focus the control.
core.callLater(100, self._collapseOrExpandControl_scriptHelper, gesture)

def _collapseOrExpandControl_scriptHelper(self, gesture: inputCore.InputGesture):
oldFocus = api.getFocusObject()
Expand Down Expand Up @@ -2050,15 +2037,6 @@ def event_gainFocus(self, obj, nextHandler):
if not self._hadFirstGainFocus or previousFocusObjIsDefunct:
# still initializing or the old focus is dead.
isOverlapping = False
elif config.conf["virtualBuffers"]["autoFocusFocusableElements"]:
# if this focus event was caused by NVDA setting the focus itself
# Due to auto focus focusable elements option being enabled,
# And we detect that the caret was already positioned within the focus.
# Note that this is not the default and may be removed in future.
caretInfo = self.makeTextInfo(textInfos.POSITION_CARET)
# Expand to one character, as isOverlapping() doesn't treat, for example, (4,4) and (4,5) as overlapping.
caretInfo.expand(textInfos.UNIT_CHARACTER)
isOverlapping = focusInfo.isOverlapping(caretInfo)
else:
# if this focus event was caused by NVDA setting the focus itself
# due to activation or applications key etc.
Expand Down Expand Up @@ -2097,12 +2075,7 @@ def event_gainFocus(self, obj, nextHandler):
# This focus change was caused by a virtual caret movement, so don't speak the focused node to avoid double speaking.
# However, we still want to update the speech property cache so that property changes will be spoken properly.
speech.speakObject(obj, OutputReason.ONLYCACHE)
if config.conf["virtualBuffers"]["autoFocusFocusableElements"]:
# As we do not call nextHandler which would trigger the vision framework to handle gain focus,
# we need to call it manually here.
# Note: this is usually called after the caret movement.
vision.handler.handleGainFocus(obj)
elif (
if (
objPendingFocusBeforeActivate
and obj == objPendingFocusBeforeActivate
and obj is not objPendingFocusBeforeActivate
Expand Down
1 change: 0 additions & 1 deletion source/config/configSpec.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,6 @@
autoSayAllOnPageLoad = boolean(default=true)
trapNonCommandGestures = boolean(default=true)
enableOnPageLoad = boolean(default=true)
autoFocusFocusableElements = boolean(default=False)
loadChromiumVBufOnBusyState = featureFlag(optionsEnum="BoolFlag", behaviorOfDefault="enabled")
textParagraphRegex = string(default="{configDefaults.DEFAULT_TEXT_PARAGRAPH_REGEX}")

Expand Down
19 changes: 0 additions & 19 deletions source/globalCommands.py
Original file line number Diff line number Diff line change
Expand Up @@ -3223,25 +3223,6 @@ def script_toggleFocusMovesNavigatorObject(self, gesture):
config.conf["reviewCursor"]["followFocus"] = True
ui.message(state)

@script(
description=_(
# Translators: Input help mode message for toggle auto focus focusable elements command.
"Toggles on and off automatic movement of the system focus due to browse mode commands",
),
category=inputCore.SCRCAT_BROWSEMODE,
gesture="kb:NVDA+8",
)
def script_toggleAutoFocusFocusableElements(self, gesture):
if config.conf["virtualBuffers"]["autoFocusFocusableElements"]:
# Translators: presented when toggled.
state = _("Automatically set system focus to focusable elements off")
config.conf["virtualBuffers"]["autoFocusFocusableElements"] = False
else:
# Translators: presented when toggled.
state = _("Automatically set system focus to focusable elements on")
config.conf["virtualBuffers"]["autoFocusFocusableElements"] = True
ui.message(state)

# added by Rui Batista<ruiandrebatista@gmail.com> to implement a battery status script
@script(
# Translators: Input help mode message for report battery status command.
Expand Down
17 changes: 0 additions & 17 deletions source/gui/settingsDialogs.py
Original file line number Diff line number Diff line change
Expand Up @@ -2594,20 +2594,6 @@ def makeSettings(self, settingsSizer):
)
self.trapNonCommandGesturesCheckBox.SetValue(config.conf["virtualBuffers"]["trapNonCommandGestures"])

# Translators: This is the label for a checkbox in the
# browse mode settings panel.
autoFocusFocusableElementsText = _("Automatically set system &focus to focusable elements")
self.autoFocusFocusableElementsCheckBox = sHelper.addItem(
wx.CheckBox(self, label=autoFocusFocusableElementsText),
)
self.bindHelpEvent(
"BrowseModeSettingsAutoFocusFocusableElements",
self.autoFocusFocusableElementsCheckBox,
)
self.autoFocusFocusableElementsCheckBox.SetValue(
config.conf["virtualBuffers"]["autoFocusFocusableElements"],
)

def onSave(self):
config.conf["virtualBuffers"]["maxLineLength"] = self.maxLengthEdit.GetValue()
config.conf["virtualBuffers"]["linesPerPage"] = self.pageLinesEdit.GetValue()
Expand All @@ -2627,9 +2613,6 @@ def onSave(self):
config.conf["virtualBuffers"]["trapNonCommandGestures"] = (
self.trapNonCommandGesturesCheckBox.IsChecked()
)
config.conf["virtualBuffers"]["autoFocusFocusableElements"] = (
self.autoFocusFocusableElementsCheckBox.IsChecked()
)


class DocumentFormattingPanel(SettingsPanel):
Expand Down
5 changes: 5 additions & 0 deletions user_docs/en/changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ To use this feature, "allow NVDA to control the volume of other applications" mu
* Updated CLDR to version 46.0. (#17484, @OzancanKaratas)
* Short versions of the most commonly used command line options have been added: `-d` for `--disable-addons` and `-n` for `--lang`.
Prefix matching on command line flags, e.g. using `--di` for `--disable-addons` is no longer supported. (#11644, @CyrilleB79)
* The Browse Mode setting "Automatically set system focus to focusable elements" has been removed, the behaviour is now disabled. (#17598)

### Bug Fixes

Expand Down Expand Up @@ -168,6 +169,10 @@ As the NVDA update check URL is now configurable directly within NVDA, no replac
* `updateCheck.UpdateAskInstallDialog` no longer automatically performs an action when the update or postpone buttons are pressed.
Instead, a `callback` property has been added, which returns a function that performs the appropriate action when called with the return value from the dialog. (#17582)
* Dialogs opened with `gui.runScriptModalDialog` are now recognised as modal by NVDA. (#17582)
* The following API symbols related to the setting "Automatically set system focus to focusable elements" have been removed with no replacement: (#17598)
* `globalCommands.GlobalCommands.script_toggleAutoFocusFocusableElements`
* `config.conf["virtualBuffers"]["autoFocusFocusableElements"]`
* `gui.settingsDialogs.BrowseModePanel.autoFocusFocusableElementsCheckBox`

#### Deprecations

Expand Down
12 changes: 0 additions & 12 deletions user_docs/en/userGuide.md
Original file line number Diff line number Diff line change
Expand Up @@ -2944,18 +2944,6 @@ Enabled by default, this option allows you to choose if gestures (such as key pr
As an example, if enabled and the letter j was pressed, it would be trapped from reaching the document, even though it is not a quick navigation command nor is it likely to be a command in the application itself.
In this case NVDA will tell Windows to play a default sound whenever a key which gets trapped is pressed.

<!-- KC:setting -->

##### Automatically set system focus to focusable elements {#BrowseModeSettingsAutoFocusFocusableElements}

Key: NVDA+8

Disabled by default, this option allows you to choose if the system focus should automatically be set to elements that can take the system focus (links, form fields, etc.) when navigating content with the browse mode caret.
Leaving this option disabled will not automatically focus focusable elements when they are selected with the browse mode caret.
This might result in faster browsing experience and better responsiveness in browse mode.
The focus will yet be updated to the particular element when interacting with it (e.g. pressing a button, checking a check box).
Enabling this option may improve support for some websites at the cost of performance and stability.

#### Document Formatting {#DocumentFormattingSettings}

<!-- KC:setting -->
Expand Down