diff --git a/source/eventHandler.py b/source/eventHandler.py index f322c45097f..d148e1d6cac 100755 --- a/source/eventHandler.py +++ b/source/eventHandler.py @@ -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) 2007-2022 NV Access Limited, Babbage B.V. +# Copyright (C) 2007-2023 NV Access Limited, Babbage B.V., Joseph Lee import threading import typing @@ -22,6 +22,7 @@ import extensionPoints import oleacc from utils.security import objectBelowLockScreenAndWindowsIsLocked +import winVersion if typing.TYPE_CHECKING: import NVDAObjects @@ -37,6 +38,12 @@ #: the last object queued for a gainFocus event. Useful for code running outside NVDA's core queue lastQueuedFocusObject=None + +# Handle virtual desktop switch announcements in Windows 10 and later +_virtualDesktopName: Optional[str] = None +_canAnnounceVirtualDesktopNames: bool = winVersion.getWinVer() >= winVersion.WIN10_1903 + + def queueEvent(eventName,obj,**kwargs): """Queues an NVDA event to be executed. @param eventName: the name of the event type (e.g. 'gainFocus', 'nameChange') @@ -287,19 +294,45 @@ def executeEvent( ): return try: + global _virtualDesktopName isGainFocus = eventName == "gainFocus" # Allow NVDAObjects to redirect focus events to another object of their choosing. if isGainFocus and obj.focusRedirect: - obj=obj.focusRedirect - sleepMode=obj.sleepMode + obj = obj.focusRedirect + sleepMode = obj.sleepMode + # Handle possible virtual desktop name change event. + # More effective in Windows 10 Version 1903 and later. + if ( + eventName == "nameChange" + and obj.windowClassName == "#32769" + and _canAnnounceVirtualDesktopNames + ): + import core + _virtualDesktopName = obj.name + core.callLater(250, handlePossibleDesktopNameChange) if isGainFocus and not doPreGainFocus(obj, sleepMode=sleepMode): return - elif not sleepMode and eventName=="documentLoadComplete" and not doPreDocumentLoadComplete(obj): + elif not sleepMode and eventName == "documentLoadComplete" and not doPreDocumentLoadComplete(obj): return elif not sleepMode: - _EventExecuter(eventName,obj,kwargs) - except: - log.exception("error executing event: %s on %s with extra args of %s"%(eventName,obj,kwargs)) + _EventExecuter(eventName, obj, kwargs) + except Exception: + log.exception(f"error executing event: {eventName} on {obj} with extra args of {kwargs}") + + +def handlePossibleDesktopNameChange() -> None: + """ + Reports the new virtual desktop name if changed. + On Windows versions lower than Windows 10, this function does nothing. + """ + global _virtualDesktopName + # Virtual desktop switch announcement works more effectively in Version 1903 and later. + if not _canAnnounceVirtualDesktopNames: + return + if _virtualDesktopName: + import ui + ui.message(_virtualDesktopName) + _virtualDesktopName = None def doPreGainFocus(obj: "NVDAObjects.NVDAObject", sleepMode: bool = False) -> bool: @@ -310,8 +343,8 @@ def doPreGainFocus(obj: "NVDAObjects.NVDAObject", sleepMode: bool = False) -> bo shouldLog=config.conf["debugLog"]["events"], ): return False - oldFocus=api.getFocusObject() - oldTreeInterceptor=oldFocus.treeInterceptor if oldFocus else None + oldFocus = api.getFocusObject() + oldTreeInterceptor = oldFocus.treeInterceptor if oldFocus else None if not api.setFocusObject(obj): return False if speech.manager._shouldCancelExpiredFocusEvents(): @@ -338,25 +371,31 @@ def doPreGainFocus(obj: "NVDAObjects.NVDAObject", sleepMode: bool = False) -> bo # not the secure desktop. and not isinstance(obj, SecureDesktopNVDAObject) ): - newForeground=api.getDesktopObject().objectInForeground() + newForeground = api.getDesktopObject().objectInForeground() if not newForeground: log.debugWarning("Can not get real foreground, resorting to focus ancestors") - ancestors=api.getFocusAncestors() - if len(ancestors)>1: - newForeground=ancestors[1] + ancestors = api.getFocusAncestors() + if len(ancestors) > 1: + newForeground = ancestors[1] else: - newForeground=obj + newForeground = obj if not api.setForegroundObject(newForeground): return False executeEvent('foreground', newForeground) - if sleepMode: return True - #Fire focus entered events for all new ancestors of the focus if this is a gainFocus event + handlePossibleDesktopNameChange() + if sleepMode: + return True + # Fire focus entered events for all new ancestors of the focus if this is a gainFocus event for parent in api.getFocusAncestors()[api.getFocusDifferenceLevel():]: - executeEvent("focusEntered",parent) + executeEvent("focusEntered", parent) if obj.treeInterceptor is not oldTreeInterceptor: - if hasattr(oldTreeInterceptor,"event_treeInterceptor_loseFocus"): + if hasattr(oldTreeInterceptor, "event_treeInterceptor_loseFocus"): oldTreeInterceptor.event_treeInterceptor_loseFocus() - if obj.treeInterceptor and obj.treeInterceptor.isReady and hasattr(obj.treeInterceptor,"event_treeInterceptor_gainFocus"): + if ( + obj.treeInterceptor + and obj.treeInterceptor.isReady + and hasattr(obj.treeInterceptor, "event_treeInterceptor_gainFocus") + ): obj.treeInterceptor.event_treeInterceptor_gainFocus() return True diff --git a/user_docs/en/changes.t2t b/user_docs/en/changes.t2t index 20bea4e1494..fe0a915f22d 100644 --- a/user_docs/en/changes.t2t +++ b/user_docs/en/changes.t2t @@ -26,6 +26,7 @@ There are now gestures for showing the braille settings dialog, accessing the st - NVDA now outputs audio via the Windows Audio Session API (WASAPI), which may improve the responsiveness, performance and stability of NVDA speech and sounds. This can be disabled in Advanced settings if audio problems are encountered. (#14697) - When using Excel shortcuts to toggle format such as bold, italic, underline and strike through of a cell in Excel, the result is now reported. (#14923) - Added support for the Help Tech Activator Braille display. (#14917) +- In Windows 10 May 2019 Update and later, NVDA can announe virtual desktop names when opening, changing, and closing them. (#5641) - @@ -39,7 +40,8 @@ There are now gestures for showing the braille settings dialog, accessing the st - - Distance reported in Microsoft Word will now honour the unit defined in Word's advanced options even when using UIA to access Word documents. (#14542) - NVDA responds faster when moving the cursor in edit controls. (#14708) -- Baum Braille driver: addes several Braille chord gestures for performing common keyboard commands such as windows+d, alt+tab etc. Please refer to the NVDA user guide for a full list. (#14714) +- Baum Braille driver: addes several Braille chord gestures for performing common keyboard commands such as ``windows+d``, ``alt+tab`` etc. +Please refer to the NVDA user guide for a full list. (#14714) - When using a Braille Display via the Standard HID braille driver, the dpad can be used to emulate the arrow keys and enter. Also space+dot1 and space+dot4 now map to up and down arrow respectively. (#14713) - Script for reporting the destination of a link now reports from the caret / focus position rather than the navigator object. (#14659) - Portable copy creation no longer requires that a drive letter be entered as part of the absolute path. (#14681)