Skip to content

Commit

Permalink
Replace isWin10 with more flexible Windows version checking (PR #11909)
Browse files Browse the repository at this point in the history
Convenience methods and types have been added to the winVersion module for getting and comparing Windows versions. 
  - isWin10 function found in winVersion module has been removed.
  - class winVersion.WinVersion is a comparable and order-able type encapsulating Windows version information.
  - Function winVersion.getWinVer has been added to get a winVersion.WinVersion representing the currently running OS.
  - Convenience constants have been added for known Windows releases, see winVersion.WIN* constants.

Closes #11795
Closes #11837
Closes #11933
Replaces #11796
Replaces #11799
  • Loading branch information
josephsl authored Mar 25, 2021
1 parent 8665526 commit ff79f51
Show file tree
Hide file tree
Showing 20 changed files with 218 additions and 80 deletions.
3 changes: 2 additions & 1 deletion source/COMRegistrationFixes/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ def fixCOMRegistrations():
Registers most common COM proxies, in case they had accidentally been unregistered or overwritten by 3rd party software installs/uninstalls.
"""
is64bit=os.environ.get("PROCESSOR_ARCHITEW6432","").endswith('64')
OSMajorMinor=winVersion.winVersion[:2]
winVer = winVersion.getWinVer()
OSMajorMinor = (winVer.major, winVer.minor)
log.debug("Fixing COM registration for Windows %s.%s, %s"%(OSMajorMinor[0],OSMajorMinor[1],"64 bit" if is64bit else "32 bit"))
# Commands taken from NVDA issue #2807 comment https://github.com/nvaccess/nvda/issues/2807#issuecomment-320149243
# OLEACC (MSAA) proxies
Expand Down
4 changes: 2 additions & 2 deletions source/NVDAObjects/IAccessible/winConsole.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import config

from NVDAObjects.behaviors import KeyboardHandlerBasedTypedCharSupport
from winVersion import isWin10
from winVersion import getWinVer, WIN10_1607

from . import IAccessible
from ..window import winConsole
Expand Down Expand Up @@ -39,7 +39,7 @@ def _get_diffAlgo(self):


def findExtraOverlayClasses(obj, clsList):
if isWin10(1607) and config.conf['terminals']['keyboardSupportInLegacy']:
if getWinVer() >= WIN10_1607 and config.conf['terminals']['keyboardSupportInLegacy']:
clsList.append(EnhancedLegacyWinConsole)
else:
clsList.append(LegacyWinConsole)
2 changes: 1 addition & 1 deletion source/NVDAObjects/UIA/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ def __init__(self,obj,position,_rangeObj=None):
# sometimes rangeFromChild can return a NULL range
if not self._rangeObj: raise LookupError
elif isinstance(position,locationHelper.Point):
if (winVersion.winVersion.major, winVersion.winVersion.minor) == (6, 1):
if winVersion.getWinVer() <= winVersion.WIN7_SP1:
# #9435: RangeFromPoint causes a freeze in UIA client library in the Windows 7 start menu!
raise NotImplementedError("RangeFromPoint not supported on Windows 7")
self._rangeObj=self.obj.UIATextPattern.RangeFromPoint(position.toPOINT())
Expand Down
2 changes: 1 addition & 1 deletion source/NVDAObjects/UIA/spartanEdge.py
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ def _getTextWithFieldsForUIARange( # noqa: C901

class EdgeNode(web.UIAWeb):

_edgeIsPreGapRemoval = winVersion.winVersion.build < 15048
_edgeIsPreGapRemoval = winVersion.getWinVer().build < 15048

_TextInfo = EdgeTextInfo_preGapRemoval if _edgeIsPreGapRemoval else EdgeTextInfo

Expand Down
2 changes: 1 addition & 1 deletion source/_UIAHandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@
localEventHandlerGroupUIAEventIds = set()

autoSelectDetectionAvailable = False
if winVersion.isWin10():
if winVersion.getWinVer() >= winVersion.WIN10:
UIAEventIdsToNVDAEventNames.update({
UIA.UIA_Text_TextChangedEventId: "textChange",
UIA.UIA_Text_TextSelectionChangedEventId: "caret",
Expand Down
6 changes: 2 additions & 4 deletions source/appModuleHandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -389,9 +389,7 @@ def _setProductInfo(self):
if not self.processHandle:
raise RuntimeError("processHandle is 0")
# No need to worry about immersive (hosted) apps and friends until Windows 8.
# Python 3.7 introduces platform_version to sys.getwindowsversion tuple,
# which returns major, minor, build.
if winVersion.winVersion.platform_version >= (6, 2, 9200):
if winVersion.getWinVer() >= winVersion.WIN8:
# Some apps such as File Explorer says it is an immersive process but error 15700 is shown.
# Therefore resort to file version info behavior because it is not a hosted app.
# Others such as Store version of Office are not truly hosted apps,
Expand Down Expand Up @@ -501,7 +499,7 @@ def _get_isWindowsStoreApp(self):
e.g. File Explorer reports itself as immersive when it is not.
@rtype: bool
"""
if winVersion.winVersion.platform_version < (6, 2, 9200):
if winVersion.getWinVer() < winVersion.WIN8:
# Windows Store/UWP apps were introduced in Windows 8.
self.isWindowsStoreApp = False
return False
Expand Down
11 changes: 7 additions & 4 deletions source/appModules/explorer.py
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ class MetadataEditField(RichEdit50):
but to avoid Windows Explorer crashes we need to use EditTextInfo here. """
@classmethod
def _get_TextInfo(cls):
if ((winVersion.winVersion.major, winVersion.winVersion.minor) == (6, 1)):
if winVersion.getWinVer() <= winVersion.WIN7_SP1:
cls.TextInfo = EditTextInfo
else:
cls.TextInfo = super().TextInfo
Expand All @@ -255,8 +255,8 @@ def event_gainFocus(self):
# as it causes 'pane" to be announced when minimizing windows or moving to desktop.
# However when closing Windows 7 Start Menu in some cases
# focus lands on it instead of the focused desktop item.
# Simply ignore the event if running on anything never than Win 7.
if ((winVersion.winVersion.major, winVersion.winVersion.minor) != (6, 1)):
# Simply ignore the event if running on anything other than Win 7.
if winVersion.getWinVer() > winVersion.WIN7_SP1:
return
if eventHandler.isPendingEvents("gainFocus"):
return
Expand Down Expand Up @@ -416,7 +416,10 @@ def event_gainFocus(self, obj, nextHandler):

def isGoodUIAWindow(self, hwnd):
# #9204: shell raises window open event for emoji panel in build 18305 and later.
if winVersion.isWin10(version=1903) and winUser.getClassName(hwnd) == "ApplicationFrameWindow":
if (
winVersion.getWinVer() >= winVersion.WIN10_1903
and winUser.getClassName(hwnd) == "ApplicationFrameWindow"
):
return True
return False

Expand Down
4 changes: 2 additions & 2 deletions source/appModules/putty.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from NVDAObjects.window import DisplayModelEditableText, DisplayModelLiveText
import appModuleHandler
from NVDAObjects.IAccessible import IAccessible
from winVersion import isWin10
from winVersion import getWinVer, WIN10_1607

class AppModule(appModuleHandler.AppModule):
# Allow this to be overridden for derived applications.
Expand All @@ -24,7 +24,7 @@ def chooseNVDAObjectOverlayClasses(self, obj, clsList):
clsList.remove(DisplayModelEditableText)
except ValueError:
pass
if isWin10(1607):
if getWinVer() >= WIN10_1607:
clsList[0:0] = (KeyboardHandlerBasedTypedCharSupport, DisplayModelLiveText)
else:
clsList[0:0] = (Terminal, DisplayModelLiveText)
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
# App module for Composable Shell (CShell) input panel
#A part of NonVisual Desktop Access (NVDA)
#Copyright (C) 2017-2018 NV Access Limited, Joseph Lee
#This file is covered by the GNU General Public License.
#See the file COPYING for more details.
# A part of NonVisual Desktop Access (NVDA)
# Copyright (C) 2017-2021 NV Access Limited, Joseph Lee
# This file is covered by the GNU General Public License.
# See the file COPYING for more details.

"""App module for Windows 10 Modern Keyboard aka new touch keyboard panel.
The chief feature is allowing NVDA to announce selected emoji when using the keyboard to search for and select one.
Expand Down Expand Up @@ -173,9 +172,17 @@ def event_UIA_window_windowOpen(self, obj, nextHandler):
return
# #9104: different aspects of modern input panel are represented by automation iD's.
childAutomationID = obj.firstChild.UIAElement.cachedAutomationID
# Emoji panel for build 16299 and 17134.
# Emoji panel for 1709 (build 16299) and 1803 (17134).
emojiPanelInitial = winVersion.WIN10_1709
# This event is properly raised in build 17134.
if winVersion.winVersion.build <= 17134 and childAutomationID in ("TEMPLATE_PART_ExpressiveInputFullViewFuntionBarItemControl", "TEMPLATE_PART_ExpressiveInputFullViewFuntionBarCloseButton"):
emojiPanelWindowOpenEvent = winVersion.WIN10_1803
if (
emojiPanelInitial <= winVersion.getWinVer() <= emojiPanelWindowOpenEvent
and childAutomationID in (
"TEMPLATE_PART_ExpressiveInputFullViewFuntionBarItemControl",
"TEMPLATE_PART_ExpressiveInputFullViewFuntionBarCloseButton"
)
):
self.event_UIA_elementSelected(obj.lastChild.firstChild, nextHandler)
# Handle hardware keyboard suggestions.
# Treat it the same as CJK composition list - don't announce this if candidate announcement setting is off.
Expand Down Expand Up @@ -221,8 +228,9 @@ def event_nameChange(self, obj, nextHandler):
or (self._recentlySelected is not None and self._recentlySelected in obj.name)):
return
# The word "blank" is kept announced, so suppress this on build 17666 and later.
if winVersion.winVersion.build > 17134:
# In build 17672 and later, return immediatley when element selected event on clipboard item was fired just prior to this.
if winVersion.getWinVer().build > 17134:
# In build 17672 and later,
# return immediately when element selected event on clipboard item was fired just prior to this.
# In some cases, parent will be None, as seen when emoji panel is closed in build 18267.
try:
if obj.UIAElement.cachedAutomationID == "TEMPLATE_PART_ClipboardItemIndex" or obj.parent.UIAElement.cachedAutomationID == "TEMPLATE_PART_ClipboardItemsList": return
Expand Down
2 changes: 1 addition & 1 deletion source/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ def main():
languageHandler.setLanguage(lang)
except:
log.warning("Could not set language to %s"%lang)
log.info("Using Windows version %s" % winVersion.winVersionText)
log.info(f"Windows version: {winVersion.getWinVer()}")
log.info("Using Python version %s"%sys.version)
log.info("Using comtypes version %s"%comtypes.__version__)
import configobj
Expand Down
6 changes: 3 additions & 3 deletions source/easeOfAccess.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@
import winreg
import ctypes
import winUser
from winVersion import winVersion
import winVersion

# Windows >= Vista
isSupported = winVersion.major >= 6
isSupported = winVersion.getWinVer().major >= 6
# Windows >= 8
canConfigTerminateOnDesktopSwitch = isSupported and (winVersion.major, winVersion.minor) >= (6, 2)
canConfigTerminateOnDesktopSwitch = isSupported and winVersion.getWinVer() >= winVersion.WIN8

ROOT_KEY = r"Software\Microsoft\Windows NT\CurrentVersion\Accessibility"
APP_KEY_NAME = "nvda_nvda_v1"
Expand Down
2 changes: 1 addition & 1 deletion source/gui/settingsDialogs.py
Original file line number Diff line number Diff line change
Expand Up @@ -2636,7 +2636,7 @@ def __init__(self, parent):
self.bindHelpEvent("AdvancedSettingsKeyboardSupportInLegacy", self.keyboardSupportInLegacyCheckBox)
self.keyboardSupportInLegacyCheckBox.SetValue(config.conf["terminals"]["keyboardSupportInLegacy"])
self.keyboardSupportInLegacyCheckBox.defaultValue = self._getDefaultValue(["terminals", "keyboardSupportInLegacy"])
self.keyboardSupportInLegacyCheckBox.Enable(winVersion.isWin10(1607))
self.keyboardSupportInLegacyCheckBox.Enable(winVersion.getWinVer() >= winVersion.WIN10_1607)

# Translators: This is the label for a combo box for selecting a
# method of detecting changed content in terminals in the advanced
Expand Down
2 changes: 1 addition & 1 deletion source/keyboardHandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ def shouldUseToUnicodeEx(focus=None):
from NVDAObjects.behaviors import KeyboardHandlerBasedTypedCharSupport
return (
# This is only possible in Windows 10 1607 and above
winVersion.isWin10(1607)
winVersion.getWinVer() >= winVersion.WIN10_1607
and ( # Either of
# We couldn't inject in-process, and its not a legacy console window without keyboard support.
# console windows have their own specific typed character support.
Expand Down
2 changes: 1 addition & 1 deletion source/synthDriverHandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,7 @@ def getSynthInstance(name):
# 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.winVersion.major >= 10:
if winVersion.getWinVer() >= winVersion.WIN10:
# Default to OneCore on Windows 10 and above
defaultSynthPriorityList.insert(0, 'oneCore')

Expand Down
2 changes: 1 addition & 1 deletion source/synthDrivers/oneCore.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ class SynthDriver(SynthDriver):
@classmethod
def check(cls):
# Only present this as an available synth if this is Windows 10.
return winVersion.isWin10()
return winVersion.getWinVer() >= winVersion.WIN10

def _get_supportsProsodyOptions(self):
self.supportsProsodyOptions = self._dll.ocSpeech_supportsProsodyOptions()
Expand Down
2 changes: 1 addition & 1 deletion source/touchHandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ def touchSupported(debugLog: bool = False):
if debugLog:
log.debugWarning("Touch only supported on installed copies")
return False
if winVersion.winVersion.platform_version < (6, 2, 9200):
if winVersion.getWinVer() < winVersion.WIN8:
if debugLog:
log.debugWarning("Touch only supported on Windows 8 and higher")
return False
Expand Down
13 changes: 11 additions & 2 deletions source/updateCheck.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
# Avoid a E402 'module level import not at top of file' warning, because several checks are performed above.
import gui.contextHelp # noqa: E402
from gui.dpiScalingHelper import DpiScalingHelperMixin, DpiScalingHelperMixinWithoutInit # noqa: E402
import winVersion
import sys # noqa: E402
import os
import inspect
import threading
Expand Down Expand Up @@ -105,12 +105,21 @@ def checkForUpdate(auto=False):
@raise RuntimeError: If there is an error checking for an update.
"""
allowUsageStats=config.conf["update"]['allowUsageStats']
# #11837: build version string, service pack, and product type manually
# because winVersion.getWinVer adds Windows release name.
winVersion = sys.getwindowsversion()
winVersionText = "{v.major}.{v.minor}.{v.build}".format(v=winVersion)
if winVersion.service_pack_major != 0:
winVersionText += " service pack %d" % winVersion.service_pack_major
if winVersion.service_pack_minor != 0:
winVersionText += ".%d" % winVersion.service_pack_minor
winVersionText += " %s" % ("workstation", "domain controller", "server")[winVersion.product_type - 1]
params = {
"autoCheck": auto,
"allowUsageStats":allowUsageStats,
"version": versionInfo.version,
"versionType": versionInfo.updateVersionType,
"osVersion": winVersion.winVersionText,
"osVersion": winVersionText,
"x64": os.environ.get("PROCESSOR_ARCHITEW6432") == "AMD64",
}
if auto and allowUsageStats:
Expand Down
Loading

0 comments on commit ff79f51

Please sign in to comment.