Exemplo n.º 1
0
    def makeSettings(self, settingsSizer):
        sHelper = gui.guiHelper.BoxSizerHelper(self, sizer=settingsSizer)
        self.autoUpdateCheckBox = sHelper.addItem(
            # Translators: This is the label for a checkbox in the
            # Add-on Updater settings panel.
            wx.CheckBox(self,
                        label=_("Automatically check for add-on &updates")))
        self.autoUpdateCheckBox.SetValue(addonUtils.updateState["autoUpdate"])

        if (winVersion.getWinVer() >= winVersion.WIN10
                and winVersion.getWinVer().productType == "workstation"):
            updateNotificationChoices = [
                # Translators: one of the add-on update notification choices.
                ("toast", _("toast")),
                # Translators: one of the add-on update notification choices.
                ("dialog", _("dialog")),
            ]
            self.updateNotification = sHelper.addLabeledControl(
                # Translators: This is the label for a combo box in the
                # Add-on Updater settings panel.
                _("&Add-on update notification:"),
                wx.Choice,
                choices=[x[1] for x in updateNotificationChoices])
            self.updateNotification.SetSelection(
                next(
                    (x for x, y in enumerate(updateNotificationChoices)
                     if y[0] == addonUtils.updateState["updateNotification"])))

        # Checkable list comes from NVDA Core issue 7491 (credit: Derek Riemer and Babbage B.V.).
        # Some add-ons come with pretty badly formatted summary text,
        # so try catching them and exclude them from this list.
        # Also, Vocalizer add-on family should be excluded from this list (requested by add-on author).
        self.noAddonUpdates = sHelper.addLabeledControl(
            _("Do &not update add-ons:"),
            CustomCheckListBox,
            choices=[
                addon.manifest["summary"]
                for addon in addonHandler.getAvailableAddons()
                if isinstance(addon.manifest['summary'], str)
                and "vocalizer" not in addon.name
            ])
        self.noAddonUpdates.SetCheckedStrings(addonHandlerEx.shouldNotUpdate())
        self.noAddonUpdates.SetSelection(0)

        self.devAddonUpdates = sHelper.addLabeledControl(
            _("Prefer &development releases:"),
            CustomCheckListBox,
            choices=[
                addon.manifest["summary"]
                for addon in addonHandler.getAvailableAddons()
                if isinstance(addon.manifest['summary'], str)
                and "vocalizer" not in addon.name
            ])
        self.devAddonUpdates.SetCheckedStrings(
            addonHandlerEx.preferDevUpdates())
        self.devAddonUpdates.SetSelection(0)
Exemplo n.º 2
0
def fixCOMRegistrations():
    """Registers most common COM proxies, in case they have accidentally been unregistered or overwritten by
	3rd party software installs or uninstalls.
	"""
    is64bit = os.environ.get("PROCESSOR_ARCHITEW6432", "").endswith("64")
    winVer = winVersion.getWinVer()
    OSMajorMinor = (winVer.major, winVer.minor)
    log.debug(
        f"Fixing COM registrations for Windows {OSMajorMinor[0]}.{OSMajorMinor[1]}, "
        "{} bit.".format("64" if is64bit else "32"))
    # OLEACC (MSAA) proxies
    apply32bitRegistryPatch(OLEACC_REG_FILE_PATH)
    if is64bit:
        apply64bitRegistryPatch(OLEACC_REG_FILE_PATH)
    # IDispatch and other common OLE interfaces
    register32bitServer(os.path.join(SYSTEM32, "oleaut32.dll"))
    register32bitServer(os.path.join(SYSTEM32, "actxprxy.dll"))
    if is64bit:
        register64bitServer(os.path.join(SYSTEM32, "oleaut32.dll"))
        register64bitServer(os.path.join(SYSTEM32, "actxprxy.dll"))
    # IServiceProvider on windows 7 can become unregistered
    if OSMajorMinor == (6, 1):  # Windows 7
        # There was no "Program Files (x86)" in Windows 7 32-bit, so we cover both cases
        register32bitServer(
            os.path.join(PROGRAM_FILES_X86 if is64bit else PROGRAM_FILES,
                         "Internet Explorer", "ieproxy.dll"))
        if is64bit:
            register64bitServer(
                os.path.join(PROGRAM_FILES, "Internet Explorer",
                             "ieproxy.dll"))
Exemplo n.º 3
0
	def script_reportComment(self, gesture):
		if winVersion.getWinVer() >= winVersion.WIN11:
			noteElement = self.UIAAnnotationObjects.get(self._UIAExcelCustomAnnotationTypes.note.id)
			if noteElement:
				name = noteElement.CurrentName
				desc = noteElement.GetCurrentPropertyValue(UIAHandler.UIA_FullDescriptionPropertyId)
				# Translators: a note on a cell in Microsoft excel.
				text = _("{name}: {desc}").format(name=name, desc=desc)
				ui.message(text)
			else:
				# Translators: message when a cell in Excel contains no note
				ui.message(_("No note on this cell"))
		commentsElement = self.UIAAnnotationObjects.get(UIAHandler.AnnotationType_Comment)
		if commentsElement:
			comment = commentsElement.GetCurrentPropertyValue(UIAHandler.UIA_FullDescriptionPropertyId)
			author = commentsElement.GetCurrentPropertyValue(UIAHandler.UIA_AnnotationAuthorPropertyId)
			numReplies = commentsElement.GetCurrentPropertyValue(self._UIAExcelCustomProps.commentReplyCount.id)
			if numReplies == 0:
				# Translators: a comment on a cell in Microsoft excel.
				text = _("Comment thread: {comment}  by {author}").format(
					comment=comment,
					author=author
				)
			else:
				# Translators: a comment on a cell in Microsoft excel.
				text = _("Comment thread: {comment}  by {author} with {numReplies} replies").format(
					comment=comment,
					author=author,
					numReplies=numReplies
				)
			ui.message(text)
		else:
			# Translators: A message in Excel when there is no comment thread
			ui.message(_("No comment thread on this cell"))
Exemplo n.º 4
0
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')
    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
    applyRegistryPatch(OLEACC_REG_FILE_PATH)
    if is64bit:
        applyRegistryPatch(OLEACC_REG_FILE_PATH, wow64=True)
    # IDispatch and other common OLE interfaces
    registerServer(os.path.join(system32, 'oleaut32.dll'))
    registerServer(os.path.join(system32, 'actxprxy.dll'))
    if is64bit:
        registerServer(os.path.join(sysWow64, 'oleaut32.dll'), wow64=True)
        registerServer(os.path.join(sysWow64, 'actxprxy.dll'), wow64=True)
    # IServiceProvider on windows 7 can become unregistered
    if OSMajorMinor == (6, 1):  # Windows 7
        registerServer(
            os.path.join(programFiles, 'Internet Explorer', 'ieproxy.dll'))
        if is64bit:
            registerServer(os.path.join(programFilesX86, 'Internet Explorer',
                                        'ieproxy.dll'),
                           wow64=True)
Exemplo n.º 5
0
 def _getFormatFieldAtRange(self,
                            textRange,
                            formatConfig,
                            ignoreMixedValues=False):
     formatField = super()._getFormatFieldAtRange(
         textRange, formatConfig, ignoreMixedValues=ignoreMixedValues)
     if not formatField:
         return formatField
     if winVersion.getWinVer() >= winVersion.WIN11:
         docElement = self.obj.UIAElement
         if formatConfig['reportLineNumber']:
             lineNumber = UIARemote.msWord_getCustomAttributeValue(
                 docElement, textRange, UIACustomAttributeID.LINE_NUMBER)
             if isinstance(lineNumber, int):
                 formatField.field['line-number'] = lineNumber
         if formatConfig['reportPage']:
             sectionNumber = UIARemote.msWord_getCustomAttributeValue(
                 docElement, textRange, UIACustomAttributeID.SECTION_NUMBER)
             if isinstance(sectionNumber, int):
                 formatField.field['section-number'] = sectionNumber
             if False:
                 # #13511: Fetching of text-column-number is disabled
                 # as it causes Microsoft Word 16.0.1493 and newer to crash!!
                 # This should only be reenabled for versions identified not to crash.
                 textColumnNumber = UIARemote.msWord_getCustomAttributeValue(
                     docElement, textRange,
                     UIACustomAttributeID.COLUMN_NUMBER)
                 if isinstance(textColumnNumber, int):
                     formatField.field[
                         'text-column-number'] = textColumnNumber
     return formatField
Exemplo n.º 6
0
 def isGoodUIAWindow(self, hwnd):
     currentWinVer = winVersion.getWinVer()
     # #9204: shell raises window open event for emoji panel in build 18305 and later.
     if (currentWinVer >= winVersion.WIN10_1903
             and winUser.getClassName(hwnd) == "ApplicationFrameWindow"):
         return True
     # #13506: Windows 11 UI elements such as Taskbar should be reclassified as UIA windows,
     # letting NVDA announce shell elements when navigating with mouse and/or touch,
     # notably when interacting with windows labeled "DesktopWindowXamlSource".
     # WORKAROUND UNTIL A PERMANENT FIX IS FOUND ACROSS APPS
     if (currentWinVer >= winVersion.WIN11
             # Traverse parents until arriving at the top-level window with the below class names.
             # This is more so for the shell root (first class name), and for others, class name check would work
             # since they are top-level windows for windows shown on screen such as Task View.
             # However, look for the ancestor for consistency.
             and winUser.getClassName(
                 winUser.getAncestor(hwnd, winUser.GA_ROOT)) in
         (
             # Windows 11 shell UI root, housing various shell elements shown on screen if enabled.
             "Shell_TrayWnd",  # Start, Search, Widgets, other shell elements
             # Top-level window class names from Windows 11 shell features
             "Shell_InputSwitchTopLevelWindow",  # Language switcher
             "XamlExplorerHostIslandWindow",  # Task View and Snap Layouts
         )
             # #13717: on some systems, Windows 11 shell elements are reported as IAccessible,
             # notably Start button, causing IAccessible handler to report attribute error when handling events.
             and winUser.getClassName(hwnd) != "Start"):
         return True
     return False
Exemplo n.º 7
0
    def _setProductInfo(self):
        """Set productName and productVersion attributes.
		There are at least two ways of obtaining product info for an app:
		* Package info for hosted apps
		* File version info for other apps and for some hosted apps
		"""
        # Sometimes (I.E. when NVDA starts) handle is 0, so stop if it is the case
        if not self.processHandle:
            raise RuntimeError("processHandle is 0")
        # No need to worry about immersive (hosted) apps and friends until Windows 8.
        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,
            # yet returns an internal version anyway because they are converted desktop apps.
            # For immersive apps, default implementation is generic - returns Windows version information.
            # Thus probe package full name and parse the serialized representation of package info structure.
            packageInfo = self._getImmersivePackageInfo()
            if packageInfo is not None:
                # Product name is of the form publisher.name for a hosted app.
                productInfo = packageInfo.split("_")
            else:
                # File Explorer and friends which are really native aps.
                productInfo = self._getExecutableFileInfo()
        else:
            # Not only native apps, but also some converted desktop aps such as Office.
            productInfo = self._getExecutableFileInfo()
        self.productName = productInfo[0]
        self.productVersion = productInfo[1]
Exemplo n.º 8
0
	def _get_states(self):
		states = super().states
		if controlTypes.State.FOCUSED in states and self.selectionContainer.getSelectedItemsCount() == 0:
			# #12530: In some versions of Excel, the selection pattern reports 0 selected items,
			# even though the focused UIA element reports as selected.
			# NVDA only silences the positive SELECTED state when one item is selected.
			# Therefore, by discarding both the SELECTED and SELECTABLE states,
			# we eliminate the redundant selection announcement.
			states.discard(controlTypes.State.SELECTED)
			states.discard(controlTypes.State.SELECTABLE)
		if self._isContentTooLargeForCell:
			if not self._nextCellHasContent:
				states.add(controlTypes.State.OVERFLOWING)
			else:
				states.add(controlTypes.State.CROPPED)
		if self._getUIACacheablePropertyValue(self._UIAExcelCustomProps.cellFormula.id):
			states.add(controlTypes.State.HASFORMULA)
		if self._getUIACacheablePropertyValue(self._UIAExcelCustomProps.hasDataValidationDropdown.id):
			states.add(controlTypes.State.HASPOPUP)
		if winVersion.getWinVer() >= winVersion.WIN11:
			try:
				annotationTypes = self._getUIACacheablePropertyValue(UIAHandler.UIA_AnnotationTypesPropertyId)
			except COMError:
				# annotationTypes cannot be fetched on older Operating Systems such as Windows 7.
				annotationTypes = None
			if annotationTypes:
				if self._UIAExcelCustomAnnotationTypes.note.id in annotationTypes:
					states.add(controlTypes.State.HASNOTE)
		return states
	def event_nameChange(self, obj, nextHandler):
		# Logic for IME candidate items is handled all within its own object
		# Therefore pass these events straight on.
		if isinstance(obj, ImeCandidateItem):
			return nextHandler()
		elif isinstance(obj, ImeCandidateUI):
			return nextHandler()

		# On some systems, touch keyboard keys keeps firing name change event.
		# In build 17704, whenever skin tones are selected, name change is fired by emoji entries (GridViewItem).
		if ((obj.UIAElement.cachedClassName in ("CRootKey", "GridViewItem"))
		# Just ignore useless clipboard status.
		# Also top emoji search result must be announced for better user experience.
		or (obj.UIAElement.cachedAutomationID in ("TEMPLATE_PART_ClipboardItemsList", "TEMPLATE_PART_Search_TextBlock"))
		# And no, emoji entries should not be announced here.
		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.getWinVer() > winVersion.WIN10_1803:
			# 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
			except AttributeError:
				return
			if not self._emojiPanelJustOpened or obj.UIAElement.cachedAutomationID != "TEMPLATE_PART_ExpressionGroupedFullView": speech.cancelSpeech()
			self._emojiPanelJustOpened = False
		# Don't forget to add "Microsoft Candidate UI" as something that should be suppressed.
		if obj.UIAElement.cachedAutomationID not in ("TEMPLATE_PART_ExpressionFullViewItemsGrid", "TEMPLATE_PART_ClipboardItemIndex", "CandidateWindowControl"):
			ui.message(obj.name)
		nextHandler()
Exemplo n.º 10
0
 def test_getWinVer(self):
     # Test a 3-tuple consisting of version major, minor, build.
     # sys.getwindowsversion() internally returns a named tuple, so comparing tuples is possible.
     currentWinVer = winVersion.getWinVer()
     winVerPython = sys.getwindowsversion()
     self.assertTupleEqual(
         (currentWinVer.major, currentWinVer.minor, currentWinVer.build),
         winVerPython[:3])
Exemplo n.º 11
0
 def event_NVDAObject_init(self, obj):
     if isinstance(obj, UIA):
         # #10341: Build 18363 introduces modern search experience in File Explorer.
         # As part of this, suggestion count is part of a live region.
         # Although it is geared for Narrator, it is applicable to other screen readers as well.
         # The live region itself is a child of the one shown here.
         if (winVersion.getWinVer() >= winVersion.WIN10_1909
                 and obj.UIAAutomationId == "suggestionCountForNarrator"
                 and obj.firstChild is not None):
             obj.name = obj.firstChild.name
 def script_win10Dictation(self, gesture):
     # Press Windows+H on Windows 10 Version 1709 (Fall Creators Update) and later.
     import winVersion
     import keyboardHandler
     if winVersion.getWinVer() < winVersion.WIN10_1709:
         # Translators: message shown when dictation command is unavailable.
         ui.message(
             _("Dictation is supported on Windows 10 Version 1709 or later")
         )
     else:
         keyboardHandler.KeyboardInputGesture.fromName("windows+h").send()
    def event_UIA_window_windowOpen(self, obj, nextHandler):
        firstChild = obj.firstChild
        # Handle Ime Candidate UI being shown
        if isinstance(firstChild, ImeCandidateUI):
            eventHandler.queueEvent("show", firstChild)
            return

        # Make sure to announce most recently used emoji first in post-1709 builds.
        # Fake the announcement by locating 'most recently used" category and calling selected event on this.
        # However, in build 17666 and later, child count is the same for both emoji panel and hardware keyboard candidates list.
        # Thankfully first child automation ID's are different for each modern input technology.
        # However this event is raised when the input panel closes.
        if obj.firstChild is None:
            return
        # #9104: different aspects of modern input panel are represented by automation iD's.
        childAutomationID = obj.firstChild.UIAElement.cachedAutomationID
        # Emoji panel for 1709 (build 16299) and 1803 (17134).
        emojiPanelInitial = winVersion.WIN10_1709
        # This event is properly raised in build 17134.
        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.
        elif childAutomationID == "CandidateWindowControl" and config.conf[
                "inputComposition"]["autoReportAllCandidates"]:
            try:
                self.event_UIA_elementSelected(
                    obj.firstChild.firstChild.firstChild, nextHandler)
            except AttributeError:
                # Because this is dictation window.
                pass
        # Emoji panel in build 17666 and later (unless this changes).
        elif childAutomationID == "TEMPLATE_PART_ExpressionGroupedFullView":
            self._emojiPanelJustOpened = True
            try:
                self.event_UIA_elementSelected(
                    obj.firstChild.children[-2].firstChild.firstChild,
                    nextHandler)
            except AttributeError:
                # In build 18272's emoji panel, emoji list becomes empty in some situations.
                pass
        # Clipboard history.
        # Move to clipboard list so element selected event can pick it up.
        # #9103: if clipboard is empty, a status message is displayed instead, and luckily it is located where clipboard data items can be found.
        elif childAutomationID == "TEMPLATE_PART_ClipboardTitleBar":
            self.event_UIA_elementSelected(obj.children[-2], nextHandler)
        nextHandler()
Exemplo n.º 14
0
 def chooseNVDAObjectOverlayClasses(self, obj, clsList):
     if obj.windowClassName == self.TERMINAL_WINDOW_CLASS and isinstance(
             obj, IAccessible
     ) and obj.IAccessibleRole == oleacc.ROLE_SYSTEM_CLIENT:
         try:
             clsList.remove(DisplayModelEditableText)
         except ValueError:
             pass
         if getWinVer() >= WIN10_1607:
             clsList[0:0] = (KeyboardHandlerBasedTypedCharSupport,
                             DisplayModelLiveText)
         else:
             clsList[0:0] = (Terminal, DisplayModelLiveText)
Exemplo n.º 15
0
def onInstall():
    import winVersion
    import gui
    import wx
    if winVersion.getWinVer() < winVersion.WIN10:
        gui.messageBox(
            _(
                # Translators: Dialog text shown when trying to install the add-on on an older version of Windows.
                "You are using an older version of Windows. This add-on requires Windows 10 or later."
            ),
            # Translators: title of the dialog shown when trying to install the add-on on an old version of Windows.
            _("Old Windows version"),
            wx.OK | wx.ICON_WARNING)
        raise RuntimeError(
            "Attempting to install Enhanced Touch Gestures on Windows releases earlier than 10"
        )
Exemplo n.º 16
0
def shouldUseToUnicodeEx(focus=None):
    "Returns whether to use ToUnicodeEx to determine typed characters."
    if not focus:
        focus = api.getFocusObject()
    from NVDAObjects.behaviors import KeyboardHandlerBasedTypedCharSupport
    return (
        # This is only possible in Windows 10 1607 and above
        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.
            (not focus.appModule.helperLocalBindingHandle
             and focus.windowClassName != 'ConsoleWindowClass')
            # or the focus is within a UWP app, where WM_CHAR never gets sent
            or focus.windowClassName.startswith('Windows.UI.Core')
            # Or this is a console with keyboard support, where WM_CHAR messages are doubled
            or isinstance(focus, KeyboardHandlerBasedTypedCharSupport)))
Exemplo n.º 17
0
	def __post_init__(self) -> None:
		""" The id field must be initialised at runtime.
		A GUID uniquely identifies a custom annotation, but the UIA system relies on integer IDs.
		Any application (clients or providers) can register a custom annotation type, subsequent applications
		will get the same id for a given GUID.
		Registering custom annotations is only supported on Windows 11 and above.
		For any lesser version, id will be 0.

		"""
		if winVersion.getWinVer() >= winVersion.WIN11:
			import NVDAHelper
			self.id = NVDAHelper.localLib.registerUIAAnnotationType(
				byref(self.guid),
			)
		else:
			self.id = 0
Exemplo n.º 18
0
class EdgeNode(web.UIAWeb):

    _edgeIsPreGapRemoval = winVersion.getWinVer().build < 15048

    _TextInfo = EdgeTextInfo_preGapRemoval if _edgeIsPreGapRemoval else EdgeTextInfo

    def getNormalizedUIATextRangeFromElement(self, UIAElement):
        textRange = super().getNormalizedUIATextRangeFromElement(UIAElement)
        if not textRange or not self._edgeIsPreGapRemoval:
            return textRange
        # Move the start of a UIA text range past any element start character stops
        lastCharInfo = EdgeTextInfo_preGapRemoval(obj=self,
                                                  position=None,
                                                  _rangeObj=textRange)
        lastCharInfo._rangeObj = textRange
        charInfo = lastCharInfo.copy()
        charInfo.collapse()
        # charInfo is a EdgeTextInfo_preGapRemoval, so why is
        # EdgeTextInfo.move used instead of
        # EdgeTextInfo_preGapRemoval.move?
        while 0 != super(EdgeTextInfo, charInfo).move(textInfos.UNIT_CHARACTER,
                                                      1):
            charInfo.setEndPoint(lastCharInfo, "startToStart")
            if charInfo.text or charInfo._hasEmbedded():
                break
            lastCharInfo.setEndPoint(charInfo, "startToEnd")
            charInfo.collapse(True)
        return textRange

    def _get__isTextEmpty(self):
        # NOTE: we can not check the result of the EdgeTextInfo move implementation to determine if we added
        # any characters to the range, since it seems to return 1 even when the text property has not changed.
        # Also we can not move (repeatedly by one character) since this can overrun the end of the field in edge.
        # So instead, we use self to make a text info (which should have the right range) and then use the UIA
        # specific _rangeObj.getText function to get a subset of the full range of characters.
        ti = self.makeTextInfo(self)
        if ti.isCollapsed:
            # it is collapsed therefore it is empty.
            # exit early so we do not have to do not have to fetch `ti.text` which
            # is potentially costly to performance.
            return True
        numberOfCharacters = 2
        text = ti._rangeObj.getText(numberOfCharacters)
        # Edge can report newline for empty fields:
        if text == "\n":
            return True
        return False
Exemplo n.º 19
0
 def event_gainFocus(self):
     # #6671: Normally we do not allow WorkerW thread to send gain focus event,
     # 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 other than Win 7.
     if winVersion.getWinVer() > winVersion.WIN7_SP1:
         return
     if eventHandler.isPendingEvents("gainFocus"):
         return
     if self.simpleFirstChild:
         # If focus is not going to be moved autotically
         # we need to forcefully move it to the focused desktop item.
         # As we are interested in the first focusable object below the pane use simpleFirstChild.
         self.simpleFirstChild.setFocus()
         return
     super().event_gainFocus()
Exemplo n.º 20
0
def touchSupported(debugLog: bool = False):
    """Returns if the system and current NVDA session supports touchscreen interaction.
	@param debugLog: Whether to log additional details about touch support to the NVDA log.
	"""
    if not config.isInstalledCopy() and not config.isAppX:
        if debugLog:
            log.debugWarning("Touch only supported on installed copies")
        return False
    if winVersion.getWinVer() < winVersion.WIN8:
        if debugLog:
            log.debugWarning("Touch only supported on Windows 8 and higher")
        return False
    maxTouches = windll.user32.GetSystemMetrics(SM_MAXIMUMTOUCHES)
    if maxTouches <= 0:
        if debugLog:
            log.debugWarning("No touch devices found")
        return False
    return True
Exemplo n.º 21
0
    def _get_isWindowsStoreApp(self):
        """Whether this process is a Windows Store (immersive) process.
		An immersive process is a Windows app that runs inside a Windows Runtime (WinRT) container.
		These include Windows store apps on Windows 8 and 8.1,
		and Universal Windows Platform (UWP) apps on Windows 10.
		A special case is a converted desktop app distributed on Microsoft Store.
		Not all immersive apps are packaged as a true Store app with a package info
		e.g. File Explorer reports itself as immersive when it is not.
		@rtype: bool
		"""
        if winVersion.getWinVer() < winVersion.WIN8:
            # Windows Store/UWP apps were introduced in Windows 8.
            self.isWindowsStoreApp = False
            return False
        # Package info is much more accurate than IsImmersiveProcess
        # because IsImmersive Process returns nonzero for File Explorer
        # and zero for Store version of Office.
        if self._getImmersivePackageInfo() is not None:
            self.isWindowsStoreApp = True
            return True
        self.isWindowsStoreApp = False
        return self.isWindowsStoreApp
Exemplo n.º 22
0
def shouldUseUIAInMSWord(appModule: appModuleHandler.AppModule) -> bool:
    allow = AllowUiaInMSWord.getConfig()
    if allow == AllowUiaInMSWord.ALWAYS:
        log.debug("User has requested UIA in MS Word always")
        return True
    canUseOlderInProcessApproach = bool(appModule.helperLocalBindingHandle)
    if not canUseOlderInProcessApproach:
        log.debug(
            "Using UIA in MS Word as no alternative object model available")
        return True
    if winVersion.getWinVer() < winVersion.WIN11:
        log.debug(
            "Not using UIA in MS Word on pre Windows 11 OS due to missing custom extensions"
        )
        return False
    if allow != AllowUiaInMSWord.WHERE_SUITABLE:
        log.debug("User does not want UIA in MS Word unless necessary")
        return False
    isOfficeApp = appModule.productName.startswith(
        ("Microsoft Office", "Microsoft Outlook"))
    if not isOfficeApp:
        log.debug(f"Unknown Office app: {appModule.productName}")
        return False
    try:
        officeVersion = tuple(
            int(x) for x in appModule.productVersion.split('.')[:3])
    except Exception:
        log.debugWarning(
            f"Unable to parse office version: {appModule.productVersion}",
            exc_info=True)
        return False
    if officeVersion < (16, 0, 15000):
        log.debug(
            f"MS word too old for suitable UIA, Office version: {officeVersion}"
        )
        return False
    log.debug(f"Using UIA due to suitable Office version: {officeVersion}")
    return True
Exemplo n.º 23
0
def _showAddonUpdateUI():
    def _showAddonUpdateUICallback(info):
        import gui
        from .addonGuiEx import AddonUpdatesDialog
        gui.mainFrame.prePopup()
        AddonUpdatesDialog(gui.mainFrame, info).Show()
        gui.mainFrame.postPopup()

    try:
        info = checkForAddonUpdates()
    except:
        info = None
        raise
    if info is not None:
        # Show either the update notification toast (Windows 10 and later)
        # or the results dialog (other Windows releases and server systems).
        # On Windows 10 and later (client versions), this behavior is configurable.
        # If toast is shown, checking for add-on updates from tools menu will merely show the results dialog.
        # wxPython 4.1.0 (and consequently, wxWidges 3.1.0) simplifies this by
        # allowing action handlers to be defined for toasts, which will then show the results dialog on the spot.
        # However it doesn't work for desktop apps such as NVDA.
        import winVersion
        winVer = winVersion.getWinVer()
        if (winVer >= winVersion.WIN10 and winVer.productType == "workstation"
                and addonUtils.updateState["updateNotification"] == "toast"):
            global _updateInfo
            updateMessage = _(
                # Translators: presented as part of add-on update notification message.
                "One or more add-on updates are available. "
                "Go to NVDA menu, Tools, Check for add-on updates to review them."
            )
            # Translators: title of the add-on update notification message.
            wx.adv.NotificationMessage(_("NVDA add-on updates"),
                                       updateMessage).Show(timeout=30)
            _updateInfo = info
        else:
            wx.CallAfter(_showAddonUpdateUICallback, info)
Exemplo n.º 24
0
 def check(cls):
     # Only present this as an available synth if this is Windows 10.
     return winVersion.getWinVer() >= winVersion.WIN10
Exemplo n.º 25
0
 def isGoodUIAWindow(self, hwnd):
     # #9204: shell raises window open event for emoji panel in build 18305 and later.
     if (winVersion.getWinVer() >= winVersion.WIN10_1903
             and winUser.getClassName(hwnd) == "ApplicationFrameWindow"):
         return True
     return False
Exemplo n.º 26
0
 def _get_TextInfo(cls):
     if winVersion.getWinVer() <= winVersion.WIN7_SP1:
         cls.TextInfo = EditTextInfo
     else:
         cls.TextInfo = super().TextInfo
     return cls.TextInfo
Exemplo n.º 27
0
# This file is covered by the GNU General Public License.
# See the file COPYING for more details.
"""Utilities for working with the Windows Ease of Access Center.
"""

from enum import Enum, IntEnum
from typing import Any, List

import globalVars
from logHandler import log
import winreg
import winUser
import winVersion

# Windows >= 8
canConfigTerminateOnDesktopSwitch: bool = winVersion.getWinVer(
) >= winVersion.WIN8
_APP_KEY_NAME = "nvda_nvda_v1"


def __getattr__(attrName: str) -> Any:
    """Module level `__getattr__` used to preserve backward compatibility."""
    if attrName == "ROOT_KEY" and globalVars._allowDeprecatedAPI:
        log.warning("ROOT_KEY is deprecated, use RegistryKey.ROOT instead.")
        return RegistryKey.ROOT.value
    if attrName == "APP_KEY_PATH" and globalVars._allowDeprecatedAPI:
        log.warning("APP_KEY_PATH is deprecated, use RegistryKey.APP instead.")
        return RegistryKey.APP.value
    if attrName == "APP_KEY_NAME" and globalVars._allowDeprecatedAPI:
        log.warning("APP_KEY_NAME is deprecated.")
        return _APP_KEY_NAME
    raise AttributeError(
Exemplo n.º 28
0
def findExtraOverlayClasses(obj, clsList):
    if getWinVer(
    ) >= WIN10_1607 and config.conf['terminals']['keyboardSupportInLegacy']:
        clsList.append(EnhancedLegacyWinConsole)
    else:
        clsList.append(LegacyWinConsole)
Exemplo n.º 29
0
#easeOfAccess.py
#A part of NonVisual Desktop Access (NVDA)
#Copyright (C) 2014 NV Access Limited
#This file is covered by the GNU General Public License.
#See the file COPYING for more details.
"""Utilities for working with the Windows Ease of Access Center.
"""

import winreg
import ctypes
import winUser
import winVersion

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

ROOT_KEY = r"Software\Microsoft\Windows NT\CurrentVersion\Accessibility"
APP_KEY_NAME = "nvda_nvda_v1"
APP_KEY_PATH = r"%s\ATs\%s" % (ROOT_KEY, APP_KEY_NAME)


def isRegistered():
    try:
        winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, APP_KEY_PATH, 0,
                       winreg.KEY_READ | winreg.KEY_WOW64_64KEY)
        return True
    except WindowsError:
        return False
Exemplo n.º 30
0
    return _curSynth


def getSynthInstance(name, asDefault=False):
    newSynth: SynthDriver = _getSynthDriver(name)()
    if asDefault and newSynth.name == 'oneCore':
        # Will raise an exception if oneCore does not support the system language
        newSynth._getDefaultVoice(pickAny=False)
    newSynth.initSettings()
    return newSynth


# 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')


def setSynth(name: Optional[str], isFallback: bool = False):
    asDefault = False
    global _curSynth, _audioOutputDevice
    if name is None:
        _curSynth.terminate()
        _curSynth = None
        return True
    if name == 'auto':
        asDefault = True
        name = defaultSynthPriorityList[0]
    if _curSynth: