Skip to content

Merge beta to master#19098

Merged
seanbudd merged 21 commits into
betafrom
master
Oct 14, 2025
Merged

Merge beta to master#19098
seanbudd merged 21 commits into
betafrom
master

Conversation

@seanbudd

Copy link
Copy Markdown
Member

No description provided.

seanbudd and others added 21 commits October 3, 2025 16:07
Closes #18657
Merges changes from nvaccess/brltty#1 and
nvaccess/nvda-misc-deps#39

### Summary of the issue:
BRLTTY needs to be updated for 64bit and python 3.13.
Since updating python it has been broken on alphas.

### Description of user facing changes:
BRLTTY restored usage restored

### Description of developer facing changes:
None

### Description of development approach:
Update commit from miscDeps built from
https://github.com/nvaccess/brltty/pull/

### Testing strategy:
Unit tests re-enabled

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

NVDA incorrectly identified the OS architecture as 32bit when running as a 64bit process.
This caused the update check to return 2025.3 as the expected NVDA version, as NVDA falsely said the system was 32bit.
Description of user facing changes:

Update check works for alphas
Description of developer facing changes:

None
Description of development approach:

Fix PROCESSOR_ARCHITEW6432 usages
    There are inconsistencies in the descriptions of how many languages are supported for NVDA within the user guide.
    In touchHandler.py, there is a spelling error where ‘triple’ is written as ‘tripple’, and another spelling error where ‘quadruple’ is written as ‘quodruple’.

Description of user facing chan
Resolves #19019
Summary of the issue:

No progress of AI Image Descriptions download shown
Description of user facing changes:

User can get progress notice during AI Image descriptions model downloading
Description of developer facing changes:

Reduce timeouts in modelDownloader to avoid excessive waiting for users when the network is poor during multi-threaded downloads

remove timeout option in future.result() in modelDownloader to avoid raise timeout error when download success

Use OOP to introduce progress reporting in _localCaptioner.messageDialogs.
Description of development approach:

None
Follow up #18924
Fixes #19033
Fixes #19039
Summary of the issue:

AI Image Descriptions turned on causes NVDA to load more slowly to some extent

the image description is not shown in braille
Description of user facing changes:

Improved NVDA startup speed to some extent when AI image descriptions is enabled.

Show image description in braille

Reduced NVDA memory usage to some extent.
Description of developer facing changes:

Improve grammar and variable name

Show image description message in main thread

Load image descriptioner in background
Fixes #19031
Summary of the issue:

import numpy directly may cause high memory useage when AI image descriptions is disabled.
Description of user facing changes:

The memory usage caused by NumPy will only occur when the AI image descriptions is loaded.
Description of developer facing changes:

Move captioner.py into a captioner/ package to support lazy import of large libraries such as numpy and onnxruntime. This reduces startup time and memory usage to some extent.
Fixes #19037
Summary of the issue:

After switching to 64 bit, when locking the user session with windows+l, or when cuming out of the lock screen, NVDA will freeze and become unusable. It was necessary to restart NVDA.

This was caused by NVDA going into an infinit loop when trying to detect if a given window was above or below the lock screen. A loop would be calling winUser.GetWindow, and breaking when the window equals GWL_NOT_FOUND (0). However, after switching to 64 bit, the value from winUser.getWindow when there was no window, was now None, not 0, so it never matched and the loop continued for ever.

winUser.getwindow internally calls user32's GetWindow, which with our new tightened winBindings ctypes definitions, was defined to return HWND, rather than just a default long. Problem is that ctypes always converts NULL pointers (including HWND) to None on return.
Description of user facing changes:
Description of developer facing changes:
Description of development approach:

for all functions in our high-level winUser module that return a window handle, ensure that 0 is returned instead of None if a null HWND is being returned. This keeps these high-level functions compatible with existing code, and therefore no longer breaks lock screen detection logic. Also add type hints for params and return for these particular functions.
…19057)

Fixes #19045
Summary of the issue:

Image Description not disabled while Screen Curtain is enabled
Description of user facing changes:

Users will be notified that AI image description is unavailable when they try to use it while the screen curtain is enabled.
Description of developer facing changes:

The item of SCREEN_CURTAIN is added to gui.blockAction.Context , developers can use it in decoration to avoid actions when screen curtain is enabled.
…19056)

Fixes #18004

### Summary of the issue:

Currently, when controlling a remote computer via NVDA Remote Access,
messages emitted via `ui.message` on the local computer are not
displayed on the refreshable braille display. This is problematic
because Remote Access outputs some status messages via `ui.message`, and
this bug means that braille-only users are unable to perceive these
messages.

### Description of user facing changes:

These messages are now shown in braille.

### Description of developer facing changes:

None.

### Description of development approach:

* Add `_pre_showBrailleMessage`, `_post_dismissBrailleMessage` and
`_decide_disabledIncludesMessage` extension points.
* Allow `BrailleHandler.message` to show a message if `enabled` is
`False` and `_decide_disabledIncludesMessage.decide()` is also `False`.
* Set Remote Access to not receive braille when showing a `ui.message`,
as detected by the aforementioned extension points.
* Temporarily enable `braille.handler` when showing a ui.message, as
detected by the aforementioned extension points.
* Process braille display scrolling and routing locally when showing a
`ui.message`, as these keys are used to pan through and dismiss the
message.
* Add a `hostPendingNonmodifier` attribute to
`_RemoteClient.client.RemoteClient`, to track the non-modifier key of
the toggle gesture.
* When processing key input, also block the `hostPendingNonmodifier`
from being sent.
* When controlling the remote computer, dismiss a `ui.message` shown by
the local computer on keyboard or braille display input.
* This input is also sent to the remote computer, unlike routing or
panning keys if a local message is being shown.

### Testing strategy:

Ensure that the "Controlling remote computer" message can be read and
interacted with in braille.

Trigger local `ui.message` while controlling the remote computer (via
`wx.CallLater` in the NVDA Python Console), and ensure the message can
be read and interacted with in braille. Did this with short and long
messages (to ensure panning works).

Performed these tests with "Show messages" set to "Use timeout", "Show
indefinitely" and "Disabled" (in the latter case confirming that
messages weren't shown).

### Known issues with pull request:

The display contents changing on the remote computer does not cause the
message to be dismissed. This is because we cannot tell the difference
between a contentful display change, and something like the cursor
flashing.

Some users may prefer the old behaviour. We could possibly make this
configurable, though I think doing so may be premature since we don't
know if users will want the option.

---------

Co-authored-by: Sean Budd <sean@nvaccess.org>
Fixes #19029

### Summary of the issue:

The uninstaller for 64-bit builds of NVDA doesn't work.

### Description of user facing changes:

The uninstaller works again.

### Description of developer facing changes:

None.

### Description of development approach:

Tell NSIS that the NVDA install path should be retrieved from a 64-bit
view of the registry.

### Testing strategy:

Build a launcher. Install it in Windows Sandbox. Uninstall it.

### Known issues with pull request:

None.
Fixup of #19020

### Summary of the issue:

Since migrating alphas to 64bit, the NV Access server has been updated
to refer 32bit OSs to 2025.3 rather than the latest NVDA version.
However, this was implemented incorrectly, checking the `x64` parameter
rather than `osArchitecture`.
Historically the `x64` parameter is used to determine if the OS is
AMD64, not if the OS supports 64-bit software, which includes ARM based
OSs.
#19020 changed updateCheck to always send True for 64-bit OSs, whereas
it should continue to only send the flag if AMD64 and instead the server
should be fixed

### Description of user facing changes:
None (with server side changes implemented)

### Description of developer facing changes:
None

### Description of development approach:
Restore update check behaviour to before 64-bit alphas

### Testing strategy:
Test on prod

### Known issues with pull request:

None
Fixes #19022

### Summary of the issue:

When updating frm 32-bit NVDA to 64-bit NVDA, the system config is lost.

### Description of user facing changes:

The system config is retained when updating from 32- to 64-bit NVDA.

### Description of developer facing changes:

None

### Description of development approach:

Add a keyword-only parameter, `prefix`, to `config._setSystemConfig`,
which by default is set to `sys.prefix` so as not to break existing
callers.
In the installer, if `shouldCleanX86` is `True` and the x86 copy has a
`systemConfig` directory, use `config._setSystemConfig` to copy the
32-bit copy's system config to the 64-bit directory before deleting the
32-bit copy's directory.

### Testing strategy:

Installed nvda_snapshot_alpha-52864,2772fde8. Changed the user
configuration, and used the "Use currently saved settings during sign-in
and on secure screens (requires administrator privileges)" button to
copy the config to the system profile. Checked that the expected files
were in `C:\Program Files (x86)\nvda\systemConfig`.

Ran a launcher built from this branch. Installed NVDA. Checked that the
same contents were present in `C:\Program Files\nvda\systemConfig`.

Performed the abovesteps, but without changing the system config, and
ensured that the upgrade process worked as expected and no
`systemConfig` directory was created.

### Known issues with pull request:

None
…8528)

Fixes #15905
Reimplements #18354, #18402, #18490

### Summary of the issue:
When trying to download an add-on from the add-on store in certain
environments such as corporates, the download fails due to the machine
not trusting the root certificate of the add-on source.

This can be caused by two issues:

* the requests library using certifi rather than the system root
certificates
* the system root certificates not trusting the add-on download source

When performing an update check, we update windows root certificates if
our certificate is invalid or out of date.

### Description of user facing changes:
NVDA should more reliably trust request endpoints using windows root
certificates. e.g. accessing the add-on store in a corporate
environment.

### Description of developer facing changes:
requests and similar libraries now has truststore injected into it

### Description of development approach:
This pull request improves how NVDA handles SSL/TLS certificate
verification, particularly for HTTPS requests and add-on downloads. It
ensures that the application uses the Windows root certificate store
instead of the Python default (certifi), provides a fallback mechanism
to update root certificates when encountering untrusted certificates,
and enhances user interaction when certificate errors occur during
add-on downloads. Additionally, shared networking logic has been
refactored and centralized for maintainability.

**Certificate Verification and Networking Improvements:**

* Added the `truststore` dependency and injected it at startup so that
all `requests` HTTP calls use the Windows root certificate store instead
of certifi, improving compatibility in corporate and managed
environments. (`pyproject.toml`, `source/core.py`)
[[1]](diffhunk://#diff-50c86b7ed8ac2cf95bd48334961bf0530cdc77b5a56f852c5c61b89d735fd711R32-R33)
[[2]](diffhunk://#diff-dbe862167add4fbe8e502757f792615f714c7603621c03d0c60c08a6a613ad68R34)
[[3]](diffhunk://#diff-dbe862167add4fbe8e502757f792615f714c7603621c03d0c60c08a6a613ad68R680-R683)
* Introduced a new `utils/networking.py` module that centralizes logic
for fetching URLs, handling certificate verification errors, and
updating Windows root certificates. This includes helper functions like
`_fetchUrlAndUpdateRootCertificates`, `_getCertificate`, and
`_updateWindowsRootCertificates`. (`source/utils/networking.py`)

**Add-on Store and Update Check Enhancements:**

* Updated add-on store and update check logic to use the new
`_fetchUrlAndUpdateRootCertificates` function, ensuring robust handling
of certificate verification failures and automatic root certificate
updates when necessary. (`source/addonStore/dataManager.py`,
`source/updateCheck.py`)
[[1]](diffhunk://#diff-9fd9bbb610bac3157554c0876fba6ea3475383ea9de36c2101ba1127cf5189e5R30)
[[2]](diffhunk://#diff-9fd9bbb610bac3157554c0876fba6ea3475383ea9de36c2101ba1127cf5189e5L127-R128)
[[3]](diffhunk://#diff-9fd9bbb610bac3157554c0876fba6ea3475383ea9de36c2101ba1127cf5189e5L138-R143)
[[4]](diffhunk://#diff-69aa1f3d46c308cf71c96483fd196eb49d6348727ab1953f834b1974ff031a43R68-R76)
[[5]](diffhunk://#diff-69aa1f3d46c308cf71c96483fd196eb49d6348727ab1953f834b1974ff031a43L241-R245)
* Improved the add-on download process to prompt the user when
encountering an untrusted certificate, displaying the SHA256 fingerprint
and allowing the user to trust and install the root certificate if
appropriate. (`source/addonStore/network.py`)
[[1]](diffhunk://#diff-097e46da59cc87eb0100bd63db7cfe32c7095ec66cf4be02d5dc84f28682ac7eL239-R297)
[[2]](diffhunk://#diff-097e46da59cc87eb0100bd63db7cfe32c7095ec66cf4be02d5dc84f28682ac7eR314-R315)

**Codebase Cleanup and Refactoring:**

* Removed duplicate and now-unnecessary certificate update logic from
`updateCheck.py` and centralized all certificate handling in
`utils/networking.py`. (`source/updateCheck.py`)
* Updated variable naming and improved code clarity in the add-on
download logic. (`source/addonStore/network.py`)
[[1]](diffhunk://#diff-097e46da59cc87eb0100bd63db7cfe32c7095ec66cf4be02d5dc84f28682ac7eL239-R297)
[[2]](diffhunk://#diff-097e46da59cc87eb0100bd63db7cfe32c7095ec66cf4be02d5dc84f28682ac7eR314-R315)
[[3]](diffhunk://#diff-097e46da59cc87eb0100bd63db7cfe32c7095ec66cf4be02d5dc84f28682ac7eL268-R324)
[[4]](diffhunk://#diff-097e46da59cc87eb0100bd63db7cfe32c7095ec66cf4be02d5dc84f28682ac7eL278-R334)
[[5]](diffhunk://#diff-097e46da59cc87eb0100bd63db7cfe32c7095ec66cf4be02d5dc84f28682ac7eL290-R346)

### Testing strategy:

- [x] Get user testing from #15905
- [x] Smoke test using add-on store
- [x] Smoke test update check

### Known issues with pull request:
None

---------

Co-authored-by: Sascha Cowley <16543535+SaschaCowley@users.noreply.github.com>
Fixes #19025
Summary of the issue:

Translation can cause access violations on 64 bit version of NVDA.
Description of user facing changes:

Errors are hopefully fixed
Description of developer facing changes:

None
Description of development approach:

Our table resolver was returning an array of tables, but that array was not terminated with a NULLPTR as expected by liblouis. Added the None/NULLPTR to the end of the array.
Update the documentation for the release process:
- We no longer automatically add issues to the milestone since #18396
- add info on manually adding milestones
- add a more useful explanation of NVDA release timings
Closes #18837
Summary of the issue:

Remote Access logs a warning when i receives a message with type ping:

WARNING - logging.Logger.warn (07:19:52.888) - Thread-3_connector_loop (13428):
Received message with unhandled type: ping {}

Description of user facing changes:

None
Description of developer facing changes:

No-longer log when ping messages are received.
Description of development approach:

Return early from _remoteClient.transport.TCPTransport.parse if a message is received with type _remoteClient.protocol.RemoteMessageType.PING.
…#19088)

<!-- Please read and fill in the following template, for an explanation
of the sections see:

https://github.com/nvaccess/nvda/blob/master/projectDocs/dev/githubPullRequestTemplateExplanationAndExamples.md
Please also note that the NVDA project has a Citizen and Contributor
Code of Conduct which can be found at
https://github.com/nvaccess/nvda/blob/master/CODE_OF_CONDUCT.md. NV
Access expects that all contributors and other community members read
and abide by the rules set out in this document while participating or
contributing to this project. This includes creating or commenting on
issues and pull requests.

Please initially open PRs as a draft.
When you would like a review, mark the PR as "ready for review".
See
https://github.com/nvaccess/nvda/blob/master/.github/CONTRIBUTING.md.
-->

### Link to issue number:
<!-- Use Closes/Fixes/Resolves #xxx to link this PR to the issue it is
responding to. -->

Fixes #19073
Fixes #19069 
### Summary of the issue:
The input help message for the image description script doesn't
descriptive enough.

The gesture for it is awkward in some case.
### Description of user facing changes:
Change gesture for recognise image script from NVDA+Windows+, to
NVDA+Windows+D

Make the input help message for recognise image script more descriptive.
### Description of developer facing changes:
None
### Description of development approach:
None
### Testing strategy:
Use new gesture in input help mode.
### Known issues with pull request:
None
### Code Review Checklist:

<!--
This checklist is a reminder of things commonly forgotten in a new PR.
Authors, please do a self-review of this pull-request.
Check items to confirm you have thought about the relevance of the item.
Where items are missing (eg unit / system tests), please explain in the
PR.
To check an item `- [ ]` becomes `- [x]`, note spacing.
You can also check the checkboxes after the PR is created.
A detailed explanation of this checklist is available here:

https://github.com/nvaccess/nvda/blob/master/projectDocs/dev/githubPullRequestTemplateExplanationAndExamples.md#code-review-checklist
-->

- [x] Documentation:
  - Change log entry
  - User Documentation
  - Developer / Technical Documentation
  - Context sensitive help for GUI changes
- [x] 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: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Sean Budd <seanbudd123@gmail.com>
Co-authored-by: Cyrille Bougot <cyrille.bougot2@laposte.net>
Closes #17751
Summary of the issue:

Solving #12224 required introducing a hack to fix wx.lib.scrolledpanel.ScrolledPanel.
This has now been fixed in wxPython 4.2.3: wxWidgets/Phoenix#1950.
As such, we can revert the hack now
Description of user facing changes:

None
Description of developer facing changes:

wxPython has been updated, this can cause API breaking changes sometimes
Support class has been removed.
### Link to issue number:

Fixes #9003.

### Summary of the issue:

Battery time script was reporting redundant "0 hours" and "0 minutes",
and using plural forms for single hours and minutes.

### Description of user facing changes:

NVDA will no longer speak remaining time when it reaches zero, for both
hours and minutes.

### Description of developer facing changes:

None.

### Description of development approach:

- Added logic to skip time reporting when both hours and minutes are
zero
- Separated hour and minute handling to only display non-zero values
- Used proper singular/plural forms via ngettext for 1 hour/1 minute
cases

### Testing strategy:

Manually tested running from source.

### Known issues with pull request:

None.

### Code Review Checklist:

<!--
This checklist is a reminder of things commonly forgotten in a new PR.
Authors, please do a self-review of this pull-request.
Check items to confirm you have thought about the relevance of the item.
Where items are missing (eg unit / system tests), please explain in the
PR.
To check an item `- [ ]` becomes `- [x]`, note spacing.
You can also check the checkboxes after the PR is created.
A detailed explanation of this checklist is available here:

https://github.com/nvaccess/nvda/blob/master/projectDocs/dev/githubPullRequestTemplateExplanationAndExamples.md#code-review-checklist
-->

- [x] Documentation:
  - Change log entry
  - User Documentation
  - Developer / Technical Documentation
  - Context sensitive help for GUI changes
- [x] 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: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Copilot AI review requested due to automatic review settings October 14, 2025 06:18
@seanbudd seanbudd requested review from a team as code owners October 14, 2025 06:18
@seanbudd seanbudd merged commit 6ebc472 into beta Oct 14, 2025
19 of 20 checks passed
@github-actions github-actions Bot added this to the 2026.1 milestone Oct 14, 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 is a merge commit from the beta branch to master, primarily introducing on-device AI image descriptions functionality along with numerous bug fixes and improvements. The most significant addition is an AI image captioner that runs locally without sending data to the internet.

  • Introduction of local AI image descriptions with NVDA+g keyboard shortcut
  • Various bug fixes including braille output improvements, battery reporting enhancements, and update mechanism changes
  • Component updates including LibLouis Braille translator, wxPython, and BrlAPI for BRLTTY

Reviewed Changes

Copilot reviewed 41 out of 42 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
user_docs/en/userGuide.md Updated documentation for AI image descriptions feature with new keyboard shortcut
user_docs/en/changes.md Changelog entries for version 2026.1 with new features and bug fixes
source/winUser.py Added null safety for Windows API function returns
source/winAPI/_powerTracking.py Improved battery time announcements to skip redundant zero values
source/utils/networking.py New networking utility module for certificate handling
source/updateCheck.py Refactored update checking to use new networking utilities
source/touchHandler.py Fixed spelling errors in touch gesture descriptions
source/louisHelper.py Enhanced braille table path handling and function signatures
source/globalCommands.py Updated AI image description commands with new shortcuts
source/core.py Added Windows root certificate injection
source/config/init.py Enhanced system config copying with prefix parameter
source/braille.py Added extension points for remote access braille message handling
source/addonStore/network.py Improved add-on download with certificate verification
source/_remoteClient/* Multiple files with remote access improvements for braille handling
source/_localCaptioner/* New AI image captioner implementation files
tests/* Various test updates and improvements
pyproject.toml Updated dependencies including wxPython and truststore

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

try:
# Use a short timeout to avoid blocking indefinitely
ok, msg = future.result(timeout=1.0)
ok, msg = future.result()

Copilot AI Oct 14, 2025

Copy link

Choose a reason for hiding this comment

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

Removing the timeout parameter could cause indefinite blocking if a download thread becomes unresponsive. Consider adding a reasonable timeout value to prevent the application from hanging.

Copilot uses AI. Check for mistakes.
@github-actions github-actions Bot requested a deployment to snapshot October 14, 2025 06:41 Abandoned
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