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

Merged
merged 4 commits into from
Jan 22, 2025
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 16 additions & 43 deletions source/browseMode.py
seanbudd marked this conversation as resolved.
Show resolved Hide resolved
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
# pass-through and disables auto pass-through.
# NVDA doesn't automatically sync 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
3 changes: 1 addition & 2 deletions source/config/configSpec.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# A part of NonVisual Desktop Access (NVDA)
# Copyright (C) 2006-2024 NV Access Limited, Babbage B.V., Davy Kager, Bill Dengler, Julien Cochuyt,
# Copyright (C) 2006-2025 NV Access Limited, Babbage B.V., Davy Kager, Bill Dengler, Julien Cochuyt,
# Joseph Lee, Dawid Pieper, mltony, Bram Duvigneau, Cyrille Bougot, Rob Meredith,
# Burman's Computer and Education Ltd., Leonard de Ruijter, Łukasz Golonka
# This file is covered by the GNU General Public License.
Expand Down 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
21 changes: 1 addition & 20 deletions source/globalCommands.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# A part of NonVisual Desktop Access (NVDA)
# This file is covered by the GNU General Public License.
# See the file COPYING for more details.
# Copyright (C) 2006-2024 NV Access Limited, Peter Vágner, Aleksey Sadovoy, Rui Batista, Joseph Lee,
# Copyright (C) 2006-2025 NV Access Limited, Peter Vágner, Aleksey Sadovoy, Rui Batista, Joseph Lee,
# Leonard de Ruijter, Derek Riemer, Babbage B.V., Davy Kager, Ethan Holliger, Łukasz Golonka, Accessolutions,
# Julien Cochuyt, Jakub Lukowicz, Bill Dengler, Cyrille Bougot, Rob Meredith, Luke Davis,
# Burman's Computer and Education Ltd.
Expand Down 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<[email protected]> to implement a battery status script
@script(
# Translators: Input help mode message for report battery status command.
Expand Down
19 changes: 1 addition & 18 deletions source/gui/settingsDialogs.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# A part of NonVisual Desktop Access (NVDA)
# Copyright (C) 2006-2024 NV Access Limited, Peter Vágner, Aleksey Sadovoy,
# Copyright (C) 2006-2025 NV Access Limited, Peter Vágner, Aleksey Sadovoy,
# Rui Batista, Joseph Lee, Heiko Folkerts, Zahari Yurukov, Leonard de Ruijter,
# Derek Riemer, Babbage B.V., Davy Kager, Ethan Holliger, Bill Dengler,
# Thomas Stivers, Julien Cochuyt, Peter Vágner, Cyrille Bougot, Mesar Hameed,
Expand Down 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 @@ -52,6 +52,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)
* Microsoft Speech API version 5 and Microsoft Speech Platform voices now use WASAPI for audio output, which may improve the responsiveness of those voices. (#13284, @gexgd0419)

### Bug Fixes
Expand Down Expand Up @@ -178,6 +179,10 @@ To change sanitization rules, such as whitelisting tags or attributes, create a
* `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`
* Because SAPI5 voices now use `nvwave.WavePlayer` to output audio: (#17592, @gexgd0419)
* `synthDrivers.sapi5.SPAudioState` has been removed.
* `synthDrivers.sapi5.SynthDriver.ttsAudioStream` has been removed.
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
Loading