Skip to content

Commit 4fdf563

Browse files
authored
Merge b5cbe20 into 648a5d3
2 parents 648a5d3 + b5cbe20 commit 4fdf563

1 file changed

Lines changed: 58 additions & 19 deletions

File tree

source/eventHandler.py

Lines changed: 58 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# A part of NonVisual Desktop Access (NVDA)
22
# This file is covered by the GNU General Public License.
33
# See the file COPYING for more details.
4-
# Copyright (C) 2007-2022 NV Access Limited, Babbage B.V.
4+
# Copyright (C) 2007-2023 NV Access Limited, Babbage B.V., Joseph Lee
55

66
import threading
77
import typing
@@ -22,6 +22,7 @@
2222
import extensionPoints
2323
import oleacc
2424
from utils.security import objectBelowLockScreenAndWindowsIsLocked
25+
import winVersion
2526

2627
if typing.TYPE_CHECKING:
2728
import NVDAObjects
@@ -37,6 +38,12 @@
3738
#: the last object queued for a gainFocus event. Useful for code running outside NVDA's core queue
3839
lastQueuedFocusObject=None
3940

41+
42+
# Handle virtual desktop switch announcements in Windows 10 and later
43+
virtualDesktopName: Optional[str] = None
44+
canAnnounceVirtualDesktopNames: bool = winVersion.getWinVer() >= winVersion.WIN10_1903
45+
46+
4047
def queueEvent(eventName,obj,**kwargs):
4148
"""Queues an NVDA event to be executed.
4249
@param eventName: the name of the event type (e.g. 'gainFocus', 'nameChange')
@@ -287,19 +294,45 @@ def executeEvent(
287294
):
288295
return
289296
try:
297+
global virtualDesktopName
290298
isGainFocus = eventName == "gainFocus"
291299
# Allow NVDAObjects to redirect focus events to another object of their choosing.
292300
if isGainFocus and obj.focusRedirect:
293-
obj=obj.focusRedirect
294-
sleepMode=obj.sleepMode
301+
obj = obj.focusRedirect
302+
sleepMode = obj.sleepMode
303+
# Handle possible virtual desktop name change event.
304+
# More effective in Windows 10 Version 1903 and later.
305+
if (
306+
eventName == "nameChange"
307+
and obj.windowClassName == "#32769"
308+
and canAnnounceVirtualDesktopNames
309+
):
310+
import core
311+
virtualDesktopName = obj.name
312+
core.callLater(250, handlePossibleDesktopNameChange)
295313
if isGainFocus and not doPreGainFocus(obj, sleepMode=sleepMode):
296314
return
297-
elif not sleepMode and eventName=="documentLoadComplete" and not doPreDocumentLoadComplete(obj):
315+
elif not sleepMode and eventName == "documentLoadComplete" and not doPreDocumentLoadComplete(obj):
298316
return
299317
elif not sleepMode:
300-
_EventExecuter(eventName,obj,kwargs)
301-
except:
302-
log.exception("error executing event: %s on %s with extra args of %s"%(eventName,obj,kwargs))
318+
_EventExecuter(eventName, obj, kwargs)
319+
except Exception:
320+
log.exception(f"error executing event: {eventName} on {obj} with extra args of {kwargs}")
321+
322+
323+
def handlePossibleDesktopNameChange() -> None:
324+
"""
325+
Reports the new virtual desktop name if changed.
326+
On Windows versions lower than Windows 10, this function does nothing.
327+
"""
328+
global virtualDesktopName
329+
# Virtual desktop switch announcement works more effectively in Version 1903 and later.
330+
if not canAnnounceVirtualDesktopNames:
331+
return
332+
if virtualDesktopName:
333+
import ui
334+
ui.message(virtualDesktopName)
335+
virtualDesktopName = None
303336

304337

305338
def doPreGainFocus(obj: "NVDAObjects.NVDAObject", sleepMode: bool = False) -> bool:
@@ -310,8 +343,8 @@ def doPreGainFocus(obj: "NVDAObjects.NVDAObject", sleepMode: bool = False) -> bo
310343
shouldLog=config.conf["debugLog"]["events"],
311344
):
312345
return False
313-
oldFocus=api.getFocusObject()
314-
oldTreeInterceptor=oldFocus.treeInterceptor if oldFocus else None
346+
oldFocus = api.getFocusObject()
347+
oldTreeInterceptor = oldFocus.treeInterceptor if oldFocus else None
315348
if not api.setFocusObject(obj):
316349
return False
317350
if speech.manager._shouldCancelExpiredFocusEvents():
@@ -338,25 +371,31 @@ def doPreGainFocus(obj: "NVDAObjects.NVDAObject", sleepMode: bool = False) -> bo
338371
# not the secure desktop.
339372
and not isinstance(obj, SecureDesktopNVDAObject)
340373
):
341-
newForeground=api.getDesktopObject().objectInForeground()
374+
newForeground = api.getDesktopObject().objectInForeground()
342375
if not newForeground:
343376
log.debugWarning("Can not get real foreground, resorting to focus ancestors")
344-
ancestors=api.getFocusAncestors()
345-
if len(ancestors)>1:
346-
newForeground=ancestors[1]
377+
ancestors = api.getFocusAncestors()
378+
if len(ancestors) > 1:
379+
newForeground = ancestors[1]
347380
else:
348-
newForeground=obj
381+
newForeground = obj
349382
if not api.setForegroundObject(newForeground):
350383
return False
351384
executeEvent('foreground', newForeground)
352-
if sleepMode: return True
353-
#Fire focus entered events for all new ancestors of the focus if this is a gainFocus event
385+
handlePossibleDesktopNameChange()
386+
if sleepMode:
387+
return True
388+
# Fire focus entered events for all new ancestors of the focus if this is a gainFocus event
354389
for parent in api.getFocusAncestors()[api.getFocusDifferenceLevel():]:
355-
executeEvent("focusEntered",parent)
390+
executeEvent("focusEntered", parent)
356391
if obj.treeInterceptor is not oldTreeInterceptor:
357-
if hasattr(oldTreeInterceptor,"event_treeInterceptor_loseFocus"):
392+
if hasattr(oldTreeInterceptor, "event_treeInterceptor_loseFocus"):
358393
oldTreeInterceptor.event_treeInterceptor_loseFocus()
359-
if obj.treeInterceptor and obj.treeInterceptor.isReady and hasattr(obj.treeInterceptor,"event_treeInterceptor_gainFocus"):
394+
if (
395+
obj.treeInterceptor
396+
and obj.treeInterceptor.isReady
397+
and hasattr(obj.treeInterceptor, "event_treeInterceptor_gainFocus")
398+
):
360399
obj.treeInterceptor.event_treeInterceptor_gainFocus()
361400
return True
362401

0 commit comments

Comments
 (0)