Skip to content
Merged
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
0f553b5
SConscript: set Windows subsystem version to Windows 10 (for NVDA hel…
josephsl Aug 13, 2025
11d8524
NVDA helper readme: WINBLUE -> WIN10 (consistency with arch build sco…
josephsl Aug 13, 2025
5e4b53f
winVersion: minimum Windows version -> Windows 10 (RTM/1507)
josephsl Aug 13, 2025
cb3a5ba
winVersion: deprecate Windows 8.1 attribute (the attribute will be re…
josephsl Aug 13, 2025
3b52eac
winVersion: remove Windows 8.1 (6.3) detection and attribute and edit…
josephsl Aug 13, 2025
2245e2d
Synth drivers: set Windows OneCore as default synthesizer and say 'tr…
josephsl Aug 13, 2025
6b98980
UIA handler: unconditionally add text change and auto-selection detec…
josephsl Aug 13, 2025
74c053c
UIA handler: remove text change event check.
josephsl Aug 13, 2025
d15ce30
appModules/excel: remove richedit60/Windows version check.
josephsl Aug 13, 2025
073a885
appModules/outlook: remove richedit60/Windows version check.
josephsl Aug 13, 2025
b0f98a9
winAPI/session tracking: remove Windows 10 check when determining sec…
josephsl Aug 13, 2025
3bbc60e
User guide: drop Windows 8.1 content (system requirements, eSpeak NG,…
josephsl Aug 13, 2025
837cefb
Update copyright headers
josephsl Aug 13, 2025
ecaf2ef
Changes: document Windows 10 requirement and winVErsion.WIN81 constan…
josephsl Aug 13, 2025
2088ca8
Pre-commit auto-fix
pre-commit-ci[bot] Aug 13, 2025
c535ee7
winVersoin: add type hints.
josephsl Aug 13, 2025
19c0e20
User guide: update system requirements.
josephsl Aug 13, 2025
05d76a9
What's new: declare Windows 10 (Version 1507) as minimum version unde…
josephsl Aug 13, 2025
2c0bb69
Synth drivers/OneCore: remove Windows 10 comment as it is unnecessary.
josephsl Aug 13, 2025
9cdbe72
What's new: add word on Windows 10 22H2 as recommended Windows 10 ver…
josephsl Aug 14, 2025
71baf1f
User guide: refinements to system requirements section (with review f…
josephsl Aug 14, 2025
4105576
NVDAObjects.UIA: remove UIAHandler.autoSelectDetectionAvailable attri…
josephsl Aug 14, 2025
e0749e6
UIA handler: remove 'autoSelectDetectionAvailable' attribute as it is…
josephsl Aug 14, 2025
22bd1d3
What's new: add removal of 'UIAHanlder.autoSelectDetectionAvailable' …
josephsl Aug 14, 2025
3500a33
UIA handler (bonus): remove typing.Optoinal (handler: UIAHandler | None)
josephsl Aug 14, 2025
bdd8f6a
Update user_docs/en/userGuide.md
seanbudd Aug 14, 2025
96bc259
NVDAObjects.UIA: remove unused import
josephsl Aug 14, 2025
42bace4
Update user_docs/en/userGuide.md
seanbudd Aug 14, 2025
42af13b
Merge branch 'master' into win10Requirement
josephsl Aug 17, 2025
f4960af
Merge branch 'master' into win10Requirement
josephsl Aug 19, 2025
6af6ab7
NVDA manifest/compatibility: remove Windows 8.1 manifest content
josephsl Aug 19, 2025
a78efab
Merge branch 'master' into win10Requirement
josephsl Aug 20, 2025
47c74af
What's new: tweak Windows version requirement entry to state Windows …
josephsl Aug 20, 2025
f8b83d3
User guide: edit Windows release requirements.
josephsl Aug 20, 2025
98f965e
Project docs/dev guide: remove 'Windows 8' qualifier on wwahost.exe
josephsl Aug 20, 2025
12780c2
Project docs/creating dev environment: enforce Windows 10 requireemtn…
josephsl Aug 20, 2025
ed9c0cb
Apply suggestions from code review
seanbudd Aug 20, 2025
7b1de15
User guide: reorder Windows 11/11 requireement
josephsl Aug 22, 2025
4473ee9
Update user_docs/en/userGuide.md
seanbudd Aug 22, 2025
190aa67
Merge branch 'master' into win10Requirement
seanbudd Aug 26, 2025
f084656
Update user_docs/en/changes.md
seanbudd Aug 26, 2025
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
8 changes: 4 additions & 4 deletions nvdaHelper/archBuild_sconscript
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# A part of NonVisual Desktop Access (NVDA)
# Copyright (C) 2006-2023 NV Access Limited
# Copyright (C) 2006-2025 NV Access Limited
# This file may be used under the terms of the GNU General Public License, version 2 or later.
# For more details see: https://www.gnu.org/licenses/gpl-2.0.html

Expand Down Expand Up @@ -81,7 +81,7 @@ env.Append(
"UNICODE",
"_CRT_SECURE_NO_DEPRECATE",
("LOGLEVEL", "${nvdaHelperLogLevel}"),
("_WIN32_WINNT", "_WIN32_WINNT_WINBLUE"),
("_WIN32_WINNT", "_WIN32_WINNT_WIN10"),
# NOMINMAX: prevent minwindef.h min/max macro definition, which unexpectedly override developer
# expectations
"NOMINMAX",
Expand All @@ -92,8 +92,8 @@ env.Append(CXXFLAGS=["/EHsc"])

env.Append(CPPPATH=["#/include", "#/include/wil/include", "#/miscDeps/include", Dir(".").abspath])

# Windows 8.1 (blue)
subsystem = "/subsystem:windows,6.03"
# Windows 10
subsystem = "/subsystem:windows,10.00"

env.Append(
LINKFLAGS=[
Expand Down
4 changes: 2 additions & 2 deletions nvdaHelper/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ You should still build on the command line to verify errors.
- Press next
- Specify Debug Configuration Settings
- Build command line: `scons source`
- Preprocessor definitions (/D): `WIN32;_WINDOWS;_USRDLL;NVDAHELPER_EXPORTS;UNICODE;_CRT_SECURE_NO_DEPRECATE;LOGLEVEL=15;_WIN32_WINNT=_WIN32_WINNT_WINBLUE;NOMINMAX`
- Preprocessor definitions (/D): `WIN32;_WINDOWS;_USRDLL;NVDAHELPER_EXPORTS;UNICODE;_CRT_SECURE_NO_DEPRECATE;LOGLEVEL=15;_WIN32_WINNT=_WIN32_WINNT_WIN10;NOMINMAX`
- Include search paths (/I): `../include;../miscDeps/include;./;../build\x86_64;../include/minhook/include`
- Forced Included files (/FI): `winuser.h`
- Press next
Expand All @@ -85,7 +85,7 @@ You should still build on the command line to verify errors.
```
cl /Fobuild\x86\vbufBackends\gecko_ia2\gecko_ia2.obj /c build\x86\vbufBackends\gecko_ia2\gecko_ia2.cpp
/TP /EHsc /nologo /std:c++20 /permissive- /Od /MT /W3 /WX
/DUNICODE /D_CRT_SECURE_NO_DEPRECATE /DLOGLEVEL=15 /D_WIN32_WINNT=_WIN32_WINNT_WINBLUE /DNOMINMAX /DNDEBUG
/DUNICODE /D_CRT_SECURE_NO_DEPRECATE /DLOGLEVEL=15 /D_WIN32_WINNT=_WIN32_WINNT_WIN10 /DNOMINMAX /DNDEBUG
/Iinclude /Imiscdeps\include /Ibuild\x86
/Z7
```
Expand Down
6 changes: 1 addition & 5 deletions source/NVDAObjects/UIA/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@
from NVDAObjects.behaviors import (
ProgressBar,
EditableTextBase,
EditableTextWithoutAutoSelectDetection,
EditableTextWithAutoSelectDetection,
Dialog,
Notification,
Expand Down Expand Up @@ -1448,10 +1447,7 @@ def findOverlayClasses(self, clsList): # NOQA: C901
clsList.append(XamlEditableText)
elif UIAClassName == "WpfTextView":
clsList.append(WpfTextView)
if UIAHandler.autoSelectDetectionAvailable:
clsList.append(EditableTextWithAutoSelectDetection)
else:
clsList.append(EditableTextWithoutAutoSelectDetection)
clsList.append(EditableTextWithAutoSelectDetection)

clsList.append(UIA)

Expand Down
28 changes: 12 additions & 16 deletions source/UIAHandler/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
# This file is covered by the GNU General Public License.
# See the file COPYING for more details.

from typing import Optional
import ctypes
import ctypes.wintypes
from ctypes import (
Expand Down Expand Up @@ -250,19 +249,16 @@

localEventHandlerGroupUIAEventIds = set()

autoSelectDetectionAvailable = False
if winVersion.getWinVer() >= winVersion.WIN10:
UIAEventIdsToNVDAEventNames.update(
{
UIA.UIA_Text_TextSelectionChangedEventId: "caret",
},
)
localEventHandlerGroupUIAEventIds.update(
{
UIA.UIA_Text_TextSelectionChangedEventId,
},
)
autoSelectDetectionAvailable = True
UIAEventIdsToNVDAEventNames.update(
{
UIA.UIA_Text_TextSelectionChangedEventId: "caret",
},
)
localEventHandlerGroupUIAEventIds.update(
{
UIA.UIA_Text_TextSelectionChangedEventId,
},
)

globalEventHandlerGroupUIAEventIds = set(UIAEventIdsToNVDAEventNames) - localEventHandlerGroupUIAEventIds

Expand Down Expand Up @@ -594,7 +590,7 @@ def _registerGlobalEventHandlers(self, handler: "UIAHandler"):
self.baseCacheRequest,
handler,
)
if not utils._shouldSelectivelyRegister() and winVersion.getWinVer() >= winVersion.WIN10:
if not utils._shouldSelectivelyRegister():
# #14067: Due to poor performance, textChange requires special handling
self.globalEventHandlerGroup.AddAutomationEventHandler(
UIA.UIA_Text_TextChangedEventId,
Expand Down Expand Up @@ -1512,7 +1508,7 @@ def isNativeUIAElement(self, UIAElement):
return False


handler: Optional[UIAHandler] = None
handler: UIAHandler | None = None


def initialize():
Expand Down
5 changes: 2 additions & 3 deletions source/appModules/excel.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# -*- coding: UTF-8 -*-
# A part of NonVisual Desktop Access (NVDA)
# Copyright (C) 2018 NV Access Limited, Łukasz Golonka
# Copyright (C) 2018-2025 NV Access Limited, Łukasz Golonka
# This file may be used under the terms of the GNU General Public License, version 2 or later.
# For more details see: https://www.gnu.org/licenses/gpl-2.0.html

Expand All @@ -13,7 +13,6 @@
from NVDAObjects import NVDAObject
from NVDAObjects.UIA import UIA
import winUser
import winVersion
import controlTypes
import appModuleHandler
from scriptHandler import script
Expand Down Expand Up @@ -111,7 +110,7 @@ def isGoodUIAWindow(self, hwnd: int) -> bool:
return True
windowClass = winUser.getClassName(hwnd)
versionMajor = int(self.productVersion.split(".")[0])
if versionMajor >= 16 and windowClass == "RICHEDIT60W" and winVersion.getWinVer() >= winVersion.WIN10:
if versionMajor >= 16 and windowClass == "RICHEDIT60W":
# RICHEDIT60W In Excel 2016+ on Windows 10+
# has a very good UI Automation implementation,
# Though oddly IsServerSideProvider returns false for these windows.
Expand Down
5 changes: 2 additions & 3 deletions source/appModules/outlook.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-2021 NV Access Limited, Yogesh Kumar, Manish Agrawal, Joseph Lee, Davy Kager,
# Copyright (C) 2006-2025 NV Access Limited, Yogesh Kumar, Manish Agrawal, Joseph Lee, Davy Kager,
# Babbage B.V., Leonard de Ruijter
# This file is covered by the GNU General Public License.
# See the file COPYING for more details.
Expand All @@ -9,7 +9,6 @@
import comtypes.client
import comtypes.automation
import ctypes
import winVersion
from scriptHandler import script
import winKernel
import comHelper
Expand Down Expand Up @@ -114,7 +113,7 @@ class AppModule(appModuleHandler.AppModule):
def isGoodUIAWindow(self, hwnd: int) -> bool:
windowClass = winUser.getClassName(hwnd)
versionMajor = int(self.productVersion.split(".")[0])
if versionMajor >= 16 and windowClass == "RICHEDIT60W" and winVersion.getWinVer() >= winVersion.WIN10:
if versionMajor >= 16 and windowClass == "RICHEDIT60W":
# #12726: RICHEDIT60W In Outlook 2016+ on Windows 10+
# has a very good UI Automation implementation,
# Though oddly IsServerSideProvider returns false for these windows.
Expand Down
8 changes: 2 additions & 6 deletions source/synthDriverHandler.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,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,
# Copyright (C) 2006-2025 NV Access Limited, Peter Vágner, Aleksey Sadovoy,
# Joseph Lee, Arnold Loubriat, Leonard de Ruijter

import pkgutil
Expand All @@ -18,7 +18,6 @@
from locale import strxfrm

import config
import winVersion
import globalVars
from logHandler import log
from synthSettingsRing import SynthSettingsRing
Expand Down Expand Up @@ -484,10 +483,7 @@ def getSynthInstance(name, asDefault=False):

# The synthDrivers that should be used by default.
# The first that successfully initializes will be used when config is set to auto (I.e. new installs of NVDA).
defaultSynthPriorityList = ["espeak", "silence"]
if winVersion.getWinVer() >= winVersion.WIN10:
# Default to OneCore on Windows 10 and above
defaultSynthPriorityList.insert(0, "oneCore")
defaultSynthPriorityList = ["oneCore", "espeak", "silence"]


def setSynth(name: Optional[str], isFallback: bool = False):
Expand Down
5 changes: 2 additions & 3 deletions source/synthDrivers/oneCore.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# A part of NonVisual Desktop Access (NVDA)
# Copyright (C) 2016-2024 Tyler Spivey, NV Access Limited, James Teh, Leonard de Ruijter
# Copyright (C) 2016-2025 Tyler Spivey, NV Access Limited, James Teh, Leonard de Ruijter
# This file is covered by the GNU General Public License.
# See the file COPYING for more details.

Expand Down Expand Up @@ -36,7 +36,6 @@
from speech.types import SpeechSequence
import speechXml
import languageHandler
import winVersion
import NVDAHelper

from speech.commands import (
Expand Down Expand Up @@ -194,7 +193,7 @@ class OneCoreSynthDriver(SynthDriver):
@classmethod
def check(cls):
# Only present this as an available synth if this is Windows 10.
return winVersion.getWinVer() >= winVersion.WIN10
return True

def _get_supportsProsodyOptions(self):
self.supportsProsodyOptions = self._dll.ocSpeech_supportsProsodyOptions()
Expand Down
10 changes: 1 addition & 9 deletions source/winAPI/sessionTracking.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# A part of NonVisual Desktop Access (NVDA)
# Copyright (C) 2022 NV Access Limited
# Copyright (C) 2022-2025 NV Access Limited
# This file may be used under the terms of the GNU General Public License, version 2 or later.
# For more details see: https://www.gnu.org/licenses/gpl-2.0.html

Expand Down Expand Up @@ -164,14 +164,6 @@ def isLockScreenModeActive() -> bool:
# Use secure mode instead if on the secure desktop
return False

import winVersion

if winVersion.getWinVer() < winVersion.WIN10:
# On Windows 8 and Earlier, the lock screen runs on
# the secure desktop.
# Lock screen mode is not supported on these Windows versions.
return False

return _isWindowsLocked()


Expand Down
21 changes: 10 additions & 11 deletions source/winVersion.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,15 +104,12 @@ def __init__(

def _getWindowsReleaseName(self) -> str:
"""Returns the public release name for a given Windows release based on major, minor, and build.
This also includes feature update release name.
This is useful if release names are not defined when constructing this class.
For example, 6.3 will return 'Windows 8.1'.
For Windows 10 and later, feature update release name will be included.
On server systems, unless noted otherwise, client release names will be returned.
For example, 'Windows 10 1809' will be returned on Server 2019 systems.
For example, 'Windows 11 24H2' will be returned on Server 2025 systems.
"""
match (self.major, self.minor):
case (6, 3):
return "Windows 8.1"
# From Windows 10 1511 (build 10586), release Id/display version comes from Windows Registry.
# However there are builds with no release name (Version 1507/10240)
# or releases with different builds.
Expand Down Expand Up @@ -146,7 +143,6 @@ def __ge__(self, other):


# Windows releases to WinVersion instances for easing comparisons.
WIN81 = WinVersion(major=6, minor=3, build=9600)
WIN10 = WIN10_1507 = WinVersion(major=10, minor=0, build=10240)
WIN10_1511 = WinVersion(major=10, minor=0, build=10586)
WIN10_1607 = WinVersion(major=10, minor=0, build=14393)
Expand All @@ -169,7 +165,7 @@ def __ge__(self, other):


@functools.lru_cache(maxsize=1)
def getWinVer():
def getWinVer() -> WinVersion:
"""Returns a record of current Windows version NVDA is running on."""
winVer = sys.getwindowsversion()
# #12509: on Windows 10, fetch whatever Windows Registry says for the current build.
Expand Down Expand Up @@ -213,15 +209,15 @@ def getWinVer():
)


def isSupportedOS():
# NVDA can only run on Windows 8.1 (Blue) and above
return getWinVer() >= WIN81
def isSupportedOS() -> bool:
# NVDA can only run on Windows 10 and above
return getWinVer() >= WIN10


UWP_OCR_DATA_PATH = os.path.expandvars(r"$windir\OCR")


def isUwpOcrAvailable():
def isUwpOcrAvailable() -> bool:
return os.path.isdir(UWP_OCR_DATA_PATH)


Expand Down Expand Up @@ -252,4 +248,7 @@ def __getattr__(attrName: str) -> Any:
if attrName == "WIN8" and NVDAState._allowDeprecatedAPI():
log.warning("WIN8 is deprecated.")
return WinVersion(major=6, minor=2, build=9200, releaseName="Windows 8")
if attrName == "WIN81" and NVDAState._allowDeprecatedAPI():
log.warning("WIN81 is deprecated.")
return WinVersion(major=6, minor=3, build=9600, releaseName="Windows 8.1")
raise AttributeError(f"module {repr(__name__)} has no attribute {repr(attrName)}")
10 changes: 9 additions & 1 deletion user_docs/en/changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,17 @@

* This release breaks compatibility with existing add-ons.
* Windows 8.1 is no longer supported.
Windows 10 is the minimum Windows version supported.
Windows 10 (Version 1507) is the minimum Windows version supported.
Comment thread
seanbudd marked this conversation as resolved.
Outdated
Comment thread
seanbudd marked this conversation as resolved.
Outdated
We recommend updating to Windows 11, or when that's not possible, to the latest Windows 10 version (22H2).
* 32-bit Windows is no longer supported.

### New Features

### Changes

* NVDA no longer supports Windows 8.1.
Windows 10 (Version 1507) is the minimum Windows version supported. (#18684, @josephsl)
Comment thread
seanbudd marked this conversation as resolved.
Outdated

### Bug Fixes

### Changes for Developers
Expand All @@ -27,8 +31,12 @@ Add-ons will need to be re-tested and have their manifest updated.
These are breaking API changes.
Please open a GitHub issue if your add-on has an issue with updating to the new API.

* `UIAHandler.autoSelectDetectionAvailable` is removed with no replacement. (#18684, @josephsl)

#### Deprecations

* `winVersion.WIN81` constant has been deprecated from winVersion module. (#18684, @josephsl):
Comment thread
seanbudd marked this conversation as resolved.
Outdated

## 2025.3

### Important notes
Expand Down
13 changes: 5 additions & 8 deletions user_docs/en/userGuide.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,15 @@ Major highlights include:

#### Minimum System Requirements {#MinimumSystemRequirements}

* Operating Systems: all 32-bit and 64-bit editions of Windows 8.1, Windows 10, Windows 11, and all Server Operating Systems starting from Windows Server 2012 R2.
* Operating Systems: 64-bit editions of Windows 10 and Windows 11.
Windows Server 2016, 2019, 2022 and 2025.
* both AMD64 and ARM64 variants of Windows are supported, including Copilot+ PCs.
* Note that 32-bit operating systems are no longer under active support.
* Note that Windows 8.1 and Windows Server versions older than 2022 are no longer under active support.
* Note that Windows 10 and Windows Server versions older than 2025 are no longer under active support.
Comment thread
seanbudd marked this conversation as resolved.
Outdated
* at least 500 MB of storage space.

#### Recommended System Requirements {#RecommendedSystemRequirements}

* Operating Systems: 64-bit editions of Windows 10, Windows 11, and Windows Server 2022.
* Operating Systems: Windows 11 and Windows Server 2025.
* both AMD64 and ARM64 variants of Windows are supported, including Copilot+ PCs.
* at least 500 MB of storage space.
* at least 4 GB of RAM.
Expand Down Expand Up @@ -4145,7 +4145,6 @@ For an even more extensive list of free and commercial synthesizers that you can
### eSpeak NG {#eSpeakNG}

The [eSpeak NG](https://github.com/espeak-ng/espeak-ng) synthesizer is built directly into NVDA and does not require any other special drivers or components to be installed.
On Windows 8.1 NVDA uses eSpeak NG by default ([Windows OneCore](#OneCore) is used in Windows 10 and later by default).
As this synthesizer is built into NVDA, this is a great choice for when running NVDA off a USB thumb drive on other systems.

Each voice that comes with eSpeak NG speaks a different language.
Expand Down Expand Up @@ -4184,7 +4183,7 @@ To use these voices, you will need to install two components:

Windows 10 and later includes voices known as "OneCore" or "mobile" voices.
Voices are provided for many languages, and they are more responsive than the Microsoft voices available using Microsoft Speech API version 5.
On Windows 10 and later, NVDA uses Windows OneCore voices by default ([eSpeak NG](#eSpeakNG) is used in other releases).
NVDA uses Windows OneCore voices by default.

To add new Windows OneCore voices, go to "Speech Settings", within Windows system settings.
Use the "Add voices" option and search for the desired language.
Expand Down Expand Up @@ -5278,8 +5277,6 @@ The braille keyboard functions described directly below is when "HID Keyboard si
### Nattiq nBraille Displays {#NattiqTechnologies}

NVDA supports displays from [Nattiq Technologies](https://www.nattiq.com/) when connected via USB.
Windows 10 and later detects the Braille Displays once connected, you may need to install USB drivers if using older versions of Windows (below Win10).
You can get them from the manufacturer's website.

Following are the key assignments for Nattiq Technologies displays with NVDA.
Please see the display's documentation for descriptions of where these keys can be found.
Expand Down