Skip to content

Master to beta#19159

Merged
seanbudd merged 17 commits into
betafrom
master
Nov 3, 2025
Merged

Master to beta#19159
seanbudd merged 17 commits into
betafrom
master

Conversation

@seanbudd

@seanbudd seanbudd commented Nov 3, 2025

Copy link
Copy Markdown
Member

No description provided.

seanbudd and others added 17 commits October 14, 2025 06:49
Closes #17749
Summary of the issue:

#17744 introduced pyright using it's default server nodeenv.
The pyright python package recommends installing pyright[nodejs] for a faster and more reliable server.
Hwever we couldn't use it while NVDA was 32bit.
This is because the node wheel binaries required a 64bit environment.
Now that NVDA has migrated to 64bit, we should update the pyright package version to using nodejs.
Link to issue number:

#18574
Summary of the issue:

Updating NVDA license from GPL-2 to GPL-2 or later. Full details: #18574
Description of user facing changes:

n/a
Description of developer facing changes:

copying.txt file updated to GPL-2 or later, and addition of GPL-3 T&Cs
…mote (#18528)" (#19106)

This reverts commit 2fa3658.


### Reverts PR
Reverts #18528

### Issues fixed

Fixes #19076

### Issues reopened

Reopens #15905

### Reason for revert

- Add-on API solution doesn't work - extracting SSL from context is
dangerous
- Regression with NVDA remote

### Can this PR be reimplemented? If so, what is required for the next
attempt

- Instead use trust store directly rather than injecting into all SSL
contexts
Closes #18831

### Summary of the issue:

Remote Access was using the deprecated `braille.filter_displaySize`
extension point.

It was also using `displaySize` instead of `displayDimensions.numCols`,
meaning that in the case that a user with a multi-line display was
controlling a computer with a single-line display that was wider than
the leader's display, braille from the follower would wrap at the width
of the leader display. While this would not result in information loss,
it was unexpected behaviour.

### Description of user facing changes:

In remote access sessions where one or more users have multi-line
braille displays connected, only the width of these displays will be
considered when finding the shared display width. For instance, if
leader connects with a DotPad (8x20 cells) and follower connects with a
Hims Brailleedge 40 (1x40 cells), the display width for the session will
be constrained to 20 cells.

### Description of developer facing changes:

None

### Description of development approach:

Replace usage of `braill.filter_displaySize` with
`braille.filter_displayDimensions` in `_remoteClient.session`. Also
renamed
`_remoteClient.localMachine.LocalMachine.handleFilterDisplaySize` to
`_handleFilterDisplayDimensions`.

Replace usages of `braille.handler.displaySize` with
`braille.handler.displayDimension.numCols` where appropriate in
`_remoteClient`.

### Testing strategy:

Created a session in which the leader was using a DotPad and the
follower was using a Brailleedge40.

### Known issues with pull request:

Users may desire the existing behaviour of all rows of multi-line
displays being considered.

We cannot support multi-line displays over Remote Access without
changing the protocol. NV Access does not have a clear policy on when we
can change the Remote Access Protocol and in what ways.
… workarounds (#19117)

Closes #18757 

### Summary of the issue:
NVDA includes Windows 8.x Start screen workarounds which are no longer
needed.

### Description of user facing changes:
None

### Description of developer facing changes:
Revmoes Windows 8.x Start screen support symbols from the File Explorer
app modules: `SuggestionListItem`, `SearchBoxClient`, `GridTileElement`,
`GridListTileElement`, `GridGroup`, `ImmersiveLauncher`.

### Description of development approach:
Removed the no longer used Windows 8.x Start screen attributes, test it
after compiling NVDA on Windows 10/11.

### Testing strategy:
Manual: make sure Windows 10/11 File Explorer support code such as
notificaiton area and UI property objects do not cause errors for NVDA.

### Known issues with pull request:
None
### Summary of the issue:
We're two Python patches behind.

### Description of user facing changes:
NOne

### Description of developer facing changes:
None

### Description of development approach:
* Grep for "3\.13\.7", change to 3.13.9.
* Removed some 32-bit left-overs.

### Testing strategy:
CI

### Known issues with pull request:
None
Closes #7455

### Summary of the issue:

In browse mode documents, the number of ítems for lists is not reported
in braille, just via speech output.

### Description of user facing changes:

The number of ítems Will be appended to lst for lists in browse mode
documents.

### Description of developer facing changes:

None

### Description of development approach:

Use the _childcontrolcount attribute of text info fields to get the
number of ítems of lists, and set the appropriate roleText when the
number of ítems of a list is available.

### Testing strategy:
Tested locally, checking that the number of ítems is reported for lists
in browse mode.

### Known issues with pull request:

In rare cases, the number of items can be reported via speech output,
not in braille, or in braille, not speech. Here is an example of a
webpage where the number of items is reported just via speech. I've
observed this just when the list contains 1 element.
In braille, in Spanish, in this webpage, pressing l to reach a list with
1 item, I read the word "fin" (end). This is not read via speech. Seems
a non standard control (like an empty list inside a menu):

https://duckduckgo.com/

I've seen, once, that the number of items was reported just in braille,
not speech. If I find the webpage I'll include it here.
### Summary of the issue:
NVDA builds are intended to upload debug symbols to Mozilla. This makes
it easier to diagnose issues related to NVDA's in-process code in
Firefox (both crash analysis and profiling), which helps both projects.
Unfortunately, this broke years ago for various reasons.

### Description of user facing changes:
None.

### Description of developer facing changes:
Mozilla crash reports and profiles will show useful symbols for NVDA
code.
I haven't included a change log entry for NVDA because this doesn't
impact NVDA developers normally, only if they're working with Firefox.

### Description of development approach:
1. The version of dump_syms.exe in miscDeps from Google Breakpad is very
outdated and probably no longer works. Mozilla completely rewrote this a
few years ago. Download that from GitHub releases and use that instead.
2. mozillaSyms.py uses relative paths, but the script was moved in
bd6b99e, which broke these paths. Update the script accordingly.
3. The structure of NVDA's lib directory has changed significantly in
the last few years. Furthermore, NVDA now supports more architectures
(arm64, arm64ec). Update mozillaSyms.py accordingly.
4. Remove some unnecessary actions from the uploadSymbols CI job.

### Testing strategy:
Confirmed that [symbols were uploaded successfully in a try
run](https://github.com/nvaccess/nvda/actions/runs/18735136393/job/53440453068).

### Known issues with pull request:
None.
## Summary of the issue:

Lilli.dll is a 32-bit DLL, so the MDV Lilli display can't be used with
64-bit builds of NVDA.

### Description of user facing changes:

TheLilli display can be used again.

### Description of developer facing changes:

None

### Description of development approach:

Update miscDeps

### Testing strategy:

This DLL was reported to work by MDV.

### Known issues with pull request:

None
Resolves #18171

### Summary of the issue:

Some configuration can still be written to disk when running from the
launcher.

### Description of user facing changes:

These configurations can no-longer be saved to disk from the launcher.

### Description of developer facing changes:

None

### Description of development approach:

* [x] Speech dictionaries: return early from
`speechDictHandler.SpeechDict.save` if `shouldWriteToDisk` returns
`False`.
* [x] Punctuation/symbol pronunciation: Return early from
`characterProcessing.SymbolPronunciations.save` if `shouldWriteToDisk`
returns `False`.
* [x] Input gestures: return early from
`inputCore.GlobalGestureMap.save` if `shouldWriteToDisk` returns
`False`.
* [x] Configuration profiles: Use `not NVDAState.shouldWriteToDisk()`
rather than `globalVars.appArgs.secure` when deciding whether to force
the config profiles dialog's new, triggers, rename and delete buttons to
be disabled.
* [x] Create: Use `not NVDAState.shouldWriteToDisk()` rather than
`globalVars.appArgs.secure` when deciding whether to return early from
`config.ConfigManager.createProfile`.
* [x] Modify: Use `not NVDAState.shouldWriteToDisk()` rather than
`globalVars.appArgs.secure` when deciding whether to return early from
`config.ConfigManager.saveProfileTriggers`.
* [x] Rename: Use `not NVDAState.shouldWriteToDisk()` rather than
`globalVars.appArgs.secure` when deciding whether to return early from
`config.ConfigManager.renameProfile`.
* [x] Delete: Use `not NVDAState.shouldWriteToDisk()` rather than
`globalVars.appArgs.secure` when deciding whether to return early from
`config.ConfigManager.deleteProfile`.

### Testing strategy:

#### Speech dictionaries:

* Build a launcher.
* Run the launcher, and ensure that existing speech dictentries work as
expected.
* Add a newentry and press Ok.
* Ensure the new entry works as expected.
* Restart NVDA, and ensure that the new entries were not persisted.

#### Symbol pronunciations

* Run from source. Modify a symbol. Ensure that the new pronunciation
works as expected.
* Restart the source copy. Ensure the modification has persisted.
* Create a launcher. Run it. Modify a symbol. Ensure that the new
pronunciation works as expected.
* Start the instaled copy of NVDA. Ensure that the modified symbol has
not been persisted.

#### Input gestures:

* Build a launcher.
* Create a new gesture in the installed copy (in my case,
`NVDA+conrol+shift+t` to report the time. Check that it works. Restart
NVDA and use the gesture t ensure it has been persisted to disk.
* Start the launcher. Use the new gesture to ensure it works in the
launcher.
* Add a new gesture (in my case, `NVDA+control+shift+r` to report the
time. Perfor the gesture to ensure that it works as expected.
* Check the log outpu to ensure that a message was logged about gestures
not being saved.
* Restart the installed copy. Ensure that the gesture created in the
launcher copy does not work, but the gesture created in the installed
copy does.

#### Config profiles

* Build a launcher.
* From the installed copy, create a new configuration profile.
* Run the launcher. Open the config profiles dialog. Attempt to create,
update or delete a profile.
* From the NVDA Python Console, attempt to call all of
`config.conf.createProfile`, `config.conf.renameProfile`,
`config.conf.deleteProfile`, and `config.conf.saveProfileTriggers`.
Observe the log to ensre the functions return early.

### Known issues with pull request:

None.
Fixes #19028

### Summary of the issue:

Papenmeier braille displays don't work with 64-bit NVDA.

### Description of user facing changes:

Papenmeier displays should work again.

### Description of developer facing changes:

* `ftdi2.py` has been moved from `miscDeps` into `nvda`, and
significantly refactored.

### Description of development approach:

* [x] Copy `ftdi2.py` from `miscdeps/python` to
`source/ftdi2/__init__.py`
* [x] Reimplement `ftExceptionDecorator` as a ctypes `errcheck` function
* [x] For each of the `_PY_*` functions, look up the corresponding
function in the [D2XX Programmer’s
Guide](https://ftdichip.com/document/programming-guides/) (revision 1.6)
and implement the corresponding ctypes prototype in `ftd2xx.py`
* [x] Convert enumerations to actual `Enum`s, and move to `ftd2xx.py`
* [x] Verify struct definitions
* [x] Rename the various pythonic functions and methods according to NV
Access' house style
* [x] Update the copyright headers and docstrings
* [x] Compare the old `ftdi2.py` wth the new `ftdi2` package and
document API differences
* [x] Remove `ftdi2.py` from miscdeps (PR nvaccess/nvda-misc-deps#46)
* [x] Update miscdeps

### Testing strategy:

Asked affected users to test try builds.

### Known issues with pull request:

None

### Code Review Checklist:

- [x] Documentation:
  - Change log entry
  - User Documentation
  - Developer / Technical Documentation
  - Context sensitive help for GUI changes
- [ ] Testing:
  - Unit tests
  - System (end to end) tests
  - Manual testing
- [x] UX of all users considered:
  - Speech
  - Braille
  - Low Vision
  - Different web browsers
  - Localization in other languages / culture than English
- [x] API is compatible with existing add-ons.
- [x] Security precautions taken.

---------

Co-authored-by: Michael Curran <mick@nvaccess.org>
…ble. (#19146)

Fixes #13897.

### Summary of the issue:
Currently, in web browsers, NVDA treats controls with a 0 width or
height and no children as invisible. While this makes sense in theory,
there are quite a few instances in the wild where authors use off-screen
content to expose something to screen readers without exposing it
visually. Because it's not visible, they sometimes don't necessarily
consider that the width or height is relevant and end up with 0
width/height, making it completely inaccessible in NVDA browse mode.
This is most common for custom radio buttons and check boxes, but I've
also seen it for custom text editors and some other controls.

I would argue this is misguided authoring on multiple levels, but
ultimately, this is causing real problems for NVDA users across the web
and our first responsibility is to users. This was implemented a long
time ago when the web was a lot simpler and there has been a shift over
the years towards trusting explicit semantics rather than fragile visual
heuristics. Finally, as far as I've been able to determine, no other
screen reader does this, which is problematic for interoperability. This
means there is content which works in every other screen reader except
NVDA.

### Description of user facing changes:
In browse mode in web browsers, NVDA no longer sometimes treats controls
with 0 visual width or height as invisible. This technique is sometimes
used to make content accessible to screen readers without it being
visible visually. Such controls will now be accessible in browse mode
where they weren't before.

### Description of developer facing changes:
None.

### Description of development approach:
In the gecko_ia2 vbuf backend, removed the code which results in
isVisible being set to false if width or height is 0.

### Testing strategy:
In both Firefox and Edge:

1. Tested with the [CodePen
example](https://codepen.io/blindguynw/pen/MWLXKvB) from
#13897 (comment).
Before the change: radio buttons do not appear in browse mode. After the
change: they do.
2. Tested with this simple test case:
`data:text/html,before<div role="radio"
aria-label="control"></div>after`
Before the change: the radio button does not appear in browse mode.
After the change: it does.
3. Loaded [the Monaco Editor
website](https://microsoft.github.io/monaco-editor/). Before the change:
quick nav to edit field often didn't find anything, though sometimes it
would appear on the first load and then disappear when refreshed. After
the change: quick nav to edit field always finds the editor.

### Known issues with pull request:
@seanbudd noted in
#13897 (comment)
that NV Access supports making this a setting. While I understand the
desire for caution here, there is currently no way to have settings like
this that affect vbuf backends without a significant amount of work. It
can't be done like layout tables because it needs to affect the content
that is rendered into the buffer, not just what semantic information
gets reported. It might be slightly more feasible to do this for pages
loaded after the setting is changed, but that is probably confusing for
users and is still a reasonable chunk of work. Meanwhile, this issue
would remain unfixed and continue to cause problems for users,
potentially on a daily basis.

I accept that if this causes unanticipated problems, it might need to be
reverted. It's a simple enough change that this can be done without much
churn.

---------

Co-authored-by: Leonard de Ruijter <3049216+LeonarddeR@users.noreply.github.com>
…is not displayed in braille (#19109)

Fixes #18993

### Summary of the issue:
When navigating the list of messages in Outlook Classic, the navigator
object is moved from the focus, showing unexpected information in
braille.

### Description of user facing changes:
The list of messages can be navigated in Outlook Classic, without
receiving unexpected information in braille.

### Description of developer facing changes:
None.

### Description of development approach:
In the `ContactEditField` class of the Outlook app module, call to
`api.setNavigatorObject` for the `event_valueChange`, has been modified
setting `isFocus` to `True`

### Testing strategy:
- Navigate the list of messages and chek that unexpected information is
not presented in braille.
- Compose messages using fields like To or CC, and check that side
effects are not produced.

### Known issues with pull request:
The navigator object is still moved, so that the reported navigator
object doesn't match the reported focus.
Fixes issue found while working on #19059
Summary of the issue:

In #19059, commit 9595711, an error is raised during check Pot:

scons: *** [tests\checkPot] IndexError : list index out of range
Traceback (most recent call last):
  File "D:\a\nvda\nvda\.venv\Lib\site-packages\SCons\Action.py", line 1434, in execute
    result = self.execfunction(target=target, source=rsources, env=env)
  File "D:\a\nvda\nvda\tests\sconscript", line 21, in checkPotAction
    return checkPot.checkPot(source[0].abspath)
           ~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^
  File "D:\a\nvda\nvda\tests\checkPot.py", line 142, in checkPot
    msgid += getStringFromLine(line)
             ~~~~~~~~~~~~~~~~~^^^^^^
  File "D:\a\nvda\nvda\tests\checkPot.py", line 201, in getStringFromLine
    quoted = line.split(" ", 1)[1]
             ~~~~~~~~~~~~~~~~~~^^^
IndexError: list index out of range
Error: Process completed with exit code 1.

The test should pass or fail but no error should be raised.

The error occurs if a msgid command containing a multi-line string is followed by a msgid_plural command. This had probably never happened before the string introduced in #19059.
Description of user facing changes:

The Python script to check Pot does not raise an error before completing.
Description of developer facing changes:

N/A
Description of development approach:

Take into account the presence of msgid_plural token. Taken into account that a multi-line string in the msgid command can end:

    either with a msgstr command
    or a msgid_plural command
Fix-up of #18974
Summary of the issue:

One newly translatable string needs to support plural forms:
"{malicious} out of {total} malware scanners detected this add-on as potentially malicious."

In English, there is no difference, since "detected" uses the same form at singular or plural; but in other languages, not. There are also languages where scanners pluralization needs to change.
Description of user facing changes:

The information will have correct pluralization form.

After discussion, I have tried to find a wording where only one of the two numbers needs an agreement to avoid splitting and re-building the sentence.
Description of developer facing changes:

N/A
Description of development approach:

Use npgettext instead of pgettext.
Copilot AI review requested due to automatic review settings November 3, 2025 01:42
@seanbudd seanbudd requested review from a team as code owners November 3, 2025 01:42
@seanbudd seanbudd merged commit a68d93d into beta Nov 3, 2025
11 of 14 checks passed
@github-actions github-actions Bot added this to the 2026.1 milestone Nov 3, 2025

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR merges changes from the master branch into the beta branch, primarily focusing on license updates, dependency changes, and code refactoring. The major change is updating NVDA's license from GPL-2 only to GPL-2 or later.

  • Updated NVDA's license from GPL-2 to GPL-2 or later, including full GPL-3 text in copying.txt
  • Removed truststore dependency and related certificate handling code, replacing with native urllib.request
  • Refactored ftdi2 module into a proper package with improved type safety and naming conventions

Reviewed Changes

Copilot reviewed 34 out of 35 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
copying.txt Added GPL-3 license text and updated references to support GPL-2 or later
pyproject.toml Updated license classifier and removed truststore dependency
source/versionInfo.py Updated license description to GPL-2 or later
source/updateCheck.py Replaced requests library with urllib.request for update checks and moved certificate handling
source/utils/networking.py File deleted - functionality moved to updateCheck.py
source/ftdi2/ftd2xx.py New file with FFI bindings for FTD2XX DLL
source/ftdi2/init.py New file with pythonic interface for ftdi2 module
source/brailleDisplayDrivers/papenmeier.py Updated to use refactored ftdi2 API
source/config/init.py Replaced globalVars.appArgs.secure checks with NVDAState.shouldWriteToDisk()
user_docs/en/changes.md Added changelog entries and removed deprecated items
Comments suppressed due to low confidence (3)

source/ftdi2/ftd2xx.py:1

  • Corrected spelling of 'existin' to 'existing'.
# A part of NonVisual Desktop Access (NVDA)

source/ftdi2/ftd2xx.py:1

  • Missing space after 'The' before backtick - should be 'The none'.
# A part of NonVisual Desktop Access (NVDA)

source/ftdi2/ftd2xx.py:1

  • Missing closing backtick after 'set_baud_rate' - should be 'set_baud_ratetosetBaudRate`'.
# A part of NonVisual Desktop Access (NVDA)

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread source/braille.py
level = field.get("level")
if level:
props["positionInfo"] = {"level": level}
if role == controlTypes.Role.LIST and (int(childControlCount := field.get("_childcontrolcount", 0))) > 0:

Copilot AI Nov 3, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The walrus operator with int() conversion and comparison makes this line overly complex. Consider splitting into multiple lines for readability.

Suggested change
if role == controlTypes.Role.LIST and (int(childControlCount := field.get("_childcontrolcount", 0))) > 0:
childControlCount = int(field.get("_childcontrolcount", 0))
if role == controlTypes.Role.LIST and childControlCount > 0:

Copilot uses AI. Check for mistakes.
#### Python

[Python](https://www.python.org/), version 3.13.7, 32 bit.
[Python](https://www.python.org/), version 3.13.9, 64-bit.

Copilot AI Nov 3, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Inconsistent bit-width specification - changed from '32 bit' to '64-bit' (note the hyphen). Should maintain consistent formatting with the original style.

Suggested change
[Python](https://www.python.org/), version 3.13.9, 64-bit.
[Python](https://www.python.org/), version 3.13.9, 64 bit.

Copilot uses AI. Check for mistakes.
if vision.handler:
vision.handler.handleGainFocus(self)
api.setNavigatorObject(self)
api.setNavigatorObject(self)

Copilot AI Nov 3, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The indentation change moves this call inside the if vision.handler: block, changing the behavior. If vision.handler is None, setNavigatorObject will no longer be called.

Suggested change
api.setNavigatorObject(self)
api.setNavigatorObject(self)

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants