diff --git a/source/browseMode.py b/source/browseMode.py index bf4a488ccc..b0a2180a75 100644 --- a/source/browseMode.py +++ b/source/browseMode.py @@ -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. @@ -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") @@ -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): @@ -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 @@ -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) @@ -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() @@ -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. @@ -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 diff --git a/source/config/configSpec.py b/source/config/configSpec.py index 8a6a082dab..692428126b 100644 --- a/source/config/configSpec.py +++ b/source/config/configSpec.py @@ -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. @@ -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}") diff --git a/source/globalCommands.py b/source/globalCommands.py index 9c22287a3c..56cacf7397 100755 --- a/source/globalCommands.py +++ b/source/globalCommands.py @@ -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. @@ -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 to implement a battery status script @script( # Translators: Input help mode message for report battery status command. diff --git a/source/gui/settingsDialogs.py b/source/gui/settingsDialogs.py index 793f6e04f3..550ba10f62 100644 --- a/source/gui/settingsDialogs.py +++ b/source/gui/settingsDialogs.py @@ -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, @@ -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() @@ -2627,9 +2613,6 @@ def onSave(self): config.conf["virtualBuffers"]["trapNonCommandGestures"] = ( self.trapNonCommandGesturesCheckBox.IsChecked() ) - config.conf["virtualBuffers"]["autoFocusFocusableElements"] = ( - self.autoFocusFocusableElementsCheckBox.IsChecked() - ) class DocumentFormattingPanel(SettingsPanel): diff --git a/user_docs/en/changes.md b/user_docs/en/changes.md index 1d701a8811..fced5466bc 100644 --- a/user_docs/en/changes.md +++ b/user_docs/en/changes.md @@ -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 @@ -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. diff --git a/user_docs/en/userGuide.md b/user_docs/en/userGuide.md index 8b5ef0d340..9330a82f0d 100644 --- a/user_docs/en/userGuide.md +++ b/user_docs/en/userGuide.md @@ -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. - - -##### 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}