We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Windows 10: NVDA announces "unknown" when opening and closing quick link menu (Windows+X)
Hi,

Reported by several people: in Windows 10, when one opens quick link menu (Windows+X), NVDA announces "unknown".

STR:

1. Press Windows+X to open quick link menu.
2. Select an item.

Expected: no "unknown".
Actual: "unknown" is announced.
Cause: an app launcher or an unknown window gains focus.

Related to: #5116, #6671.

Thanks.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `source/appModules/explorer.py`
Content:
```
1 #appModules/explorer.py
2 #A part of NonVisual Desktop Access (NVDA)
3 #Copyright (C) 2006-2017 NV Access Limited, Joseph Lee
4 #This file is covered by the GNU General Public License.
5 #See the file COPYING for more details.
6 
7 """App module for Windows Explorer (aka Windows shell).
8 Provides workarounds for controls such as identifying Start button, notification area and others.
9 """
10 
11 from comtypes import COMError
12 import time
13 import appModuleHandler
14 import controlTypes
15 import winUser
16 import api
17 import speech
18 import eventHandler
19 import mouseHandler
20 from NVDAObjects.window import Window
21 from NVDAObjects.IAccessible import sysListView32, IAccessible, List
22 from NVDAObjects.UIA import UIA
23 
24 # Suppress incorrect Win 10 Task switching window focus
25 class MultitaskingViewFrameWindow(UIA):
26 	shouldAllowUIAFocusEvent=False
27 
28 
29 # Suppress focus ancestry for task switching list items if alt is held down (alt+tab)
30 class MultitaskingViewFrameListItem(UIA):
31 
32 	def _get_container(self):
33 		if winUser.getAsyncKeyState(winUser.VK_MENU)&32768:
34 			return api.getDesktopObject()
35 		else:
36 			return super(MultitaskingViewFrameListItem,self).container
37 
38 
39 # Support for Win8 start screen search suggestions.
40 class SuggestionListItem(UIA):
41 
42 	def event_UIA_elementSelected(self):
43 		speech.cancelSpeech()
44 		api.setNavigatorObject(self, isFocus=True)
45 		self.reportFocus()
46 		super(SuggestionListItem,self).event_UIA_elementSelected()
47 
48 
49 # Windows 8 hack: Class to disable incorrect focus on windows 8 search box (containing the already correctly focused edit field)
50 class SearchBoxClient(IAccessible):
51 	shouldAllowIAccessibleFocusEvent=False
52 
53 
54 # Class for menu items  for Windows Places and Frequently used Programs (in start menu)
55 class SysListView32MenuItem(sysListView32.ListItemWithoutColumnSupport):
56 
57 	# #474: When focus moves to these items, an extra focus is fired on the parent
58 	# However NVDA redirects it to the real focus.
59 	# But this means double focus events on the item, so filter the second one out
60 	def _get_shouldAllowIAccessibleFocusEvent(self):
61 		res=super(SysListView32MenuItem,self).shouldAllowIAccessibleFocusEvent
62 		if not res:
63 			return False
64 		focus=eventHandler.lastQueuedFocusObject
65 		if type(focus)!=type(self) or (self.event_windowHandle,self.event_objectID,self.event_childID)!=(focus.event_windowHandle,focus.event_objectID,focus.event_childID):
66 			return True
67 		return False
68 
69 
70 class ClassicStartMenu(Window):
71 	# Override the name, as Windows names this the "Application" menu contrary to all documentation.
72 	# Translators: The title of Start menu/screen in your language (only the word start).
73 	name = _("Start")
74 
75 	def event_gainFocus(self):
76 		# In Windows XP, the Start button will get focus first, so silence this.
77 		speech.cancelSpeech()
78 		super(ClassicStartMenu, self).event_gainFocus()
79 
80 
81 class NotificationArea(IAccessible):
82 	"""The Windows notification area, a.k.a. system tray.
83 	"""
84 
85 	def event_gainFocus(self):
86 		if mouseHandler.lastMouseEventTime < time.time() - 0.2:
87 			# This focus change was not caused by a mouse event.
88 			# If the mouse is on another toolbar control, the notification area toolbar will rudely
89 			# bounce the focus back to the object under the mouse after a brief pause.
90 			# Moving the mouse to the focus object isn't a good solution because
91 			# sometimes, the focus can't be moved away from the object under the mouse.
92 			# Therefore, move the mouse out of the way.
93 			winUser.setCursorPos(0, 0)
94 
95 		if self.role == controlTypes.ROLE_TOOLBAR:
96 			# Sometimes, the toolbar itself receives the focus instead of the focused child.
97 			# However, the focused child still has the focused state.
98 			for child in self.children:
99 				if child.hasFocus:
100 					# Redirect the focus to the focused child.
101 					eventHandler.executeEvent("gainFocus", child)
102 					return
103 			# We've really landed on the toolbar itself.
104 			# This was probably caused by moving the mouse out of the way in a previous focus event.
105 			# This previous focus event is no longer useful, so cancel speech.
106 			speech.cancelSpeech()
107 
108 		if eventHandler.isPendingEvents("gainFocus"):
109 			return
110 		super(NotificationArea, self).event_gainFocus()
111 
112 
113 class GridTileElement(UIA):
114 
115 	role=controlTypes.ROLE_TABLECELL
116 
117 	def _get_description(self):
118 		name=self.name
119 		descriptionStrings=[]
120 		for child in self.children:
121 			description=child.basicText
122 			if not description or description==name: continue
123 			descriptionStrings.append(description)
124 		return " ".join(descriptionStrings)
125 		return description
126 
127 
128 class GridListTileElement(UIA):
129 	role=controlTypes.ROLE_TABLECELL
130 	description=None
131 
132 
133 class GridGroup(UIA):
134 	"""A group in the Windows 8 Start Menu.
135 	"""
136 	presentationType=UIA.presType_content
137 
138 	# Normally the name is the first tile which is rather redundant
139 	# However some groups have custom header text which should be read instead
140 	def _get_name(self):
141 		child=self.firstChild
142 		if isinstance(child,UIA):
143 			try:
144 				automationID=child.UIAElement.currentAutomationID
145 			except COMError:
146 				automationID=None
147 			if automationID=="GridListGroupHeader":
148 				return child.name
149 
150 
151 class ImmersiveLauncher(UIA):
152 	# When the Windows 8 start screen opens, focus correctly goes to the first tile, but then incorrectly back to the root of the window.
153 	# Ignore focus events on this object.
154 	shouldAllowUIAFocusEvent=False
155 
156 
157 class StartButton(IAccessible):
158 	"""For Windows 8.1 and 10 Start buttons to be recognized as proper buttons and to suppress selection announcement."""
159 
160 	role = controlTypes.ROLE_BUTTON
161 
162 	def _get_states(self):
163 		# #5178: Selection announcement should be suppressed.
164 		# Borrowed from Mozilla objects in NVDAObjects/IAccessible/Mozilla.py.
165 		states = super(StartButton, self).states
166 		states.discard(controlTypes.STATE_SELECTED)
167 		return states
168 
169 
170 class AppModule(appModuleHandler.AppModule):
171 
172 	def chooseNVDAObjectOverlayClasses(self, obj, clsList):
173 		windowClass = obj.windowClassName
174 		role = obj.role
175 
176 		if windowClass in ("Search Box","UniversalSearchBand") and role==controlTypes.ROLE_PANE and isinstance(obj,IAccessible):
177 			clsList.insert(0,SearchBoxClient)
178 			return
179 
180 		if windowClass == "ToolbarWindow32" and role == controlTypes.ROLE_POPUPMENU:
181 			parent = obj.parent
182 			if parent and parent.windowClassName == "SysPager" and obj.windowStyle & 0x80:
183 				clsList.insert(0, ClassicStartMenu)
184 			return
185 
186 		if windowClass == "SysListView32" and role == controlTypes.ROLE_MENUITEM:
187 			clsList.insert(0, SysListView32MenuItem)
188 			return
189 
190 		if windowClass == "ToolbarWindow32":
191 			# Check whether this is the notification area, a.k.a. system tray.
192 			if isinstance(obj.parent, ClassicStartMenu):
193 				return # This can't be a notification area
194 			try:
195 				# The toolbar's immediate parent is its window object, so we need to go one further.
196 				toolbarParent = obj.parent.parent
197 				if role != controlTypes.ROLE_TOOLBAR:
198 					# Toolbar item.
199 					toolbarParent = toolbarParent.parent
200 			except AttributeError:
201 				toolbarParent = None
202 			if toolbarParent and toolbarParent.windowClassName == "SysPager":
203 				clsList.insert(0, NotificationArea)
204 				return
205 
206 		# #5178: Start button in Windows 8.1 and 10 should not have been a list in the first place.
207 		if windowClass == "Start" and role in (controlTypes.ROLE_LIST, controlTypes.ROLE_BUTTON):
208 			if role == controlTypes.ROLE_LIST:
209 				clsList.remove(List)
210 			clsList.insert(0, StartButton)
211 
212 		if isinstance(obj, UIA):
213 			uiaClassName = obj.UIAElement.cachedClassName
214 			if uiaClassName == "GridTileElement":
215 				clsList.insert(0, GridTileElement)
216 			elif uiaClassName == "GridListTileElement":
217 				clsList.insert(0, GridListTileElement)
218 			elif uiaClassName == "GridGroup":
219 				clsList.insert(0, GridGroup)
220 			elif uiaClassName == "ImmersiveLauncher" and role == controlTypes.ROLE_PANE:
221 				clsList.insert(0, ImmersiveLauncher)
222 			elif uiaClassName=="ListViewItem" and obj.UIAElement.cachedAutomationId.startswith('Suggestion_'):
223 				clsList.insert(0,SuggestionListItem)
224 			elif uiaClassName=="MultitaskingViewFrame" and role==controlTypes.ROLE_WINDOW:
225 				clsList.insert(0,MultitaskingViewFrameWindow)
226 			elif obj.windowClassName=="MultitaskingViewFrame" and role==controlTypes.ROLE_LISTITEM:
227 				clsList.insert(0,MultitaskingViewFrameListItem)
228 
229 	def event_NVDAObject_init(self, obj):
230 		windowClass = obj.windowClassName
231 		role = obj.role
232 
233 		if windowClass == "ToolbarWindow32" and role == controlTypes.ROLE_POPUPMENU:
234 			parent = obj.parent
235 			if parent and parent.windowClassName == "SysPager" and not (obj.windowStyle & 0x80):
236 				# This is the menu for a group of icons on the task bar, which Windows stupidly names "Application".
237 				obj.name = None
238 			return
239 
240 		if windowClass == "#32768":
241 			# Standard menu.
242 			parent = obj.parent
243 			if parent and not parent.parent:
244 				# Context menu.
245 				# We don't trust the names that Explorer gives to context menus, so better to have no name at all.
246 				obj.name = None
247 			return
248 
249 		if windowClass == "DV2ControlHost" and role == controlTypes.ROLE_PANE:
250 			# Windows Vista/7 start menu.
251 			obj.presentationType=obj.presType_content
252 			obj.isPresentableFocusAncestor = True
253 			# In Windows 7, the description of this pane is extremely verbose help text, so nuke it.
254 			obj.description = None
255 			return
256 
257 		# The Address bar is embedded inside a progressbar, how strange.
258 		# Lets hide that
259 		if windowClass=="msctls_progress32" and winUser.getClassName(winUser.getAncestor(obj.windowHandle,winUser.GA_PARENT))=="Address Band Root":
260 			obj.presentationType=obj.presType_layout
261 
262 	def event_gainFocus(self, obj, nextHandler):
263 		wClass = obj.windowClassName
264 		if wClass == "ToolbarWindow32" and obj.role == controlTypes.ROLE_MENUITEM and obj.parent.role == controlTypes.ROLE_MENUBAR and eventHandler.isPendingEvents("gainFocus"):
265 			# When exiting a menu, Explorer fires focus on the top level menu item before it returns to the previous focus.
266 			# Unfortunately, this focus event always occurs in a subsequent cycle, so the event limiter doesn't eliminate it.
267 			# Therefore, if there is a pending focus event, don't bother handling this event.
268 			return
269 
270 		if wClass == "ForegroundStaging":
271 			# #5116: The Windows 10 Task View fires foreground/focus on this weird invisible window before and after it appears.
272 			# This causes NVDA to report "unknown", so ignore it.
273 			# We can't do this using shouldAllowIAccessibleFocusEvent because this isn't checked for foreground.
274 			return
275 
276 		if wClass == "WorkerW" and obj.role == controlTypes.ROLE_PANE and obj.name is None:
277 			# #6671: Never allow WorkerW thread to send gain focus event, as it causes 'pane" to be announced when minimizing windows or moving to desktop.
278 			return
279 
280 		nextHandler()
281
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/source/appModules/explorer.py b/source/appModules/explorer.py
--- a/source/appModules/explorer.py
+++ b/source/appModules/explorer.py
@@ -1,6 +1,6 @@
 #appModules/explorer.py
 #A part of NonVisual Desktop Access (NVDA)
-#Copyright (C) 2006-2017 NV Access Limited, Joseph Lee
+#Copyright (C) 2006-2018 NV Access Limited, Joseph Lee
 #This file is covered by the GNU General Public License.
 #See the file COPYING for more details.
 
@@ -267,10 +267,11 @@
 			# Therefore, if there is a pending focus event, don't bother handling this event.
 			return
 
-		if wClass == "ForegroundStaging":
-			# #5116: The Windows 10 Task View fires foreground/focus on this weird invisible window before and after it appears.
+		if wClass in ("ForegroundStaging", "LauncherTipWnd", "ApplicationManager_DesktopShellWindow"):
+			# #5116: The Windows 10 Task View fires foreground/focus on this weird invisible window and foreground staging screen before and after it appears.
 			# This causes NVDA to report "unknown", so ignore it.
 			# We can't do this using shouldAllowIAccessibleFocusEvent because this isn't checked for foreground.
+			# #8137: also seen when opening quick link menu (Windows+X) on Windows 8 and later.
 			return
 
 		if wClass == "WorkerW" and obj.role == controlTypes.ROLE_PANE and obj.name is None:

{"golden_diff": "diff --git a/source/appModules/explorer.py b/source/appModules/explorer.py\n--- a/source/appModules/explorer.py\n+++ b/source/appModules/explorer.py\n@@ -1,6 +1,6 @@\n #appModules/explorer.py\r\n #A part of NonVisual Desktop Access (NVDA)\r\n-#Copyright (C) 2006-2017 NV Access Limited, Joseph Lee\r\n+#Copyright (C) 2006-2018 NV Access Limited, Joseph Lee\r\n #This file is covered by the GNU General Public License.\r\n #See the file COPYING for more details.\r\n \r\n@@ -267,10 +267,11 @@\n \t\t\t# Therefore, if there is a pending focus event, don't bother handling this event.\r\n \t\t\treturn\r\n \r\n-\t\tif wClass == \"ForegroundStaging\":\r\n-\t\t\t# #5116: The Windows 10 Task View fires foreground/focus on this weird invisible window before and after it appears.\r\n+\t\tif wClass in (\"ForegroundStaging\", \"LauncherTipWnd\", \"ApplicationManager_DesktopShellWindow\"):\r\n+\t\t\t# #5116: The Windows 10 Task View fires foreground/focus on this weird invisible window and foreground staging screen before and after it appears.\r\n \t\t\t# This causes NVDA to report \"unknown\", so ignore it.\r\n \t\t\t# We can't do this using shouldAllowIAccessibleFocusEvent because this isn't checked for foreground.\r\n+\t\t\t# #8137: also seen when opening quick link menu (Windows+X) on Windows 8 and later.\r\n \t\t\treturn\r\n \r\n \t\tif wClass == \"WorkerW\" and obj.role == controlTypes.ROLE_PANE and obj.name is None:\n", "issue": "Windows 10: NVDA announces \"unknown\" when opening and closing quick link menu (Windows+X)\nHi,\r\n\r\nReported by several people: in Windows 10, when one opens quick link menu (Windows+X), NVDA announces \"unknown\".\r\n\r\nSTR:\r\n\r\n1. Press Windows+X to open quick link menu.\r\n2. Select an item.\r\n\r\nExpected: no \"unknown\".\r\nActual: \"unknown\" is announced.\r\nCause: an app launcher or an unknown window gains focus.\r\n\r\nRelated to: #5116, #6671.\r\n\r\nThanks.\n", "before_files": [{"content": "#appModules/explorer.py\r\n#A part of NonVisual Desktop Access (NVDA)\r\n#Copyright (C) 2006-2017 NV Access Limited, Joseph Lee\r\n#This file is covered by the GNU General Public License.\r\n#See the file COPYING for more details.\r\n\r\n\"\"\"App module for Windows Explorer (aka Windows shell).\r\nProvides workarounds for controls such as identifying Start button, notification area and others.\r\n\"\"\"\r\n\r\nfrom comtypes import COMError\r\nimport time\r\nimport appModuleHandler\r\nimport controlTypes\r\nimport winUser\r\nimport api\r\nimport speech\r\nimport eventHandler\r\nimport mouseHandler\r\nfrom NVDAObjects.window import Window\r\nfrom NVDAObjects.IAccessible import sysListView32, IAccessible, List\r\nfrom NVDAObjects.UIA import UIA\r\n\r\n# Suppress incorrect Win 10 Task switching window focus\r\nclass MultitaskingViewFrameWindow(UIA):\r\n\tshouldAllowUIAFocusEvent=False\r\n\r\n\r\n# Suppress focus ancestry for task switching list items if alt is held down (alt+tab)\r\nclass MultitaskingViewFrameListItem(UIA):\r\n\r\n\tdef _get_container(self):\r\n\t\tif winUser.getAsyncKeyState(winUser.VK_MENU)&32768:\r\n\t\t\treturn api.getDesktopObject()\r\n\t\telse:\r\n\t\t\treturn super(MultitaskingViewFrameListItem,self).container\r\n\r\n\r\n# Support for Win8 start screen search suggestions.\r\nclass SuggestionListItem(UIA):\r\n\r\n\tdef event_UIA_elementSelected(self):\r\n\t\tspeech.cancelSpeech()\r\n\t\tapi.setNavigatorObject(self, isFocus=True)\r\n\t\tself.reportFocus()\r\n\t\tsuper(SuggestionListItem,self).event_UIA_elementSelected()\r\n\r\n\r\n# Windows 8 hack: Class to disable incorrect focus on windows 8 search box (containing the already correctly focused edit field)\r\nclass SearchBoxClient(IAccessible):\r\n\tshouldAllowIAccessibleFocusEvent=False\r\n\r\n\r\n# Class for menu items  for Windows Places and Frequently used Programs (in start menu)\r\nclass SysListView32MenuItem(sysListView32.ListItemWithoutColumnSupport):\r\n\r\n\t# #474: When focus moves to these items, an extra focus is fired on the parent\r\n\t# However NVDA redirects it to the real focus.\r\n\t# But this means double focus events on the item, so filter the second one out\r\n\tdef _get_shouldAllowIAccessibleFocusEvent(self):\r\n\t\tres=super(SysListView32MenuItem,self).shouldAllowIAccessibleFocusEvent\r\n\t\tif not res:\r\n\t\t\treturn False\r\n\t\tfocus=eventHandler.lastQueuedFocusObject\r\n\t\tif type(focus)!=type(self) or (self.event_windowHandle,self.event_objectID,self.event_childID)!=(focus.event_windowHandle,focus.event_objectID,focus.event_childID):\r\n\t\t\treturn True\r\n\t\treturn False\r\n\r\n\r\nclass ClassicStartMenu(Window):\r\n\t# Override the name, as Windows names this the \"Application\" menu contrary to all documentation.\r\n\t# Translators: The title of Start menu/screen in your language (only the word start).\r\n\tname = _(\"Start\")\r\n\r\n\tdef event_gainFocus(self):\r\n\t\t# In Windows XP, the Start button will get focus first, so silence this.\r\n\t\tspeech.cancelSpeech()\r\n\t\tsuper(ClassicStartMenu, self).event_gainFocus()\r\n\r\n\r\nclass NotificationArea(IAccessible):\r\n\t\"\"\"The Windows notification area, a.k.a. system tray.\r\n\t\"\"\"\r\n\r\n\tdef event_gainFocus(self):\r\n\t\tif mouseHandler.lastMouseEventTime < time.time() - 0.2:\r\n\t\t\t# This focus change was not caused by a mouse event.\r\n\t\t\t# If the mouse is on another toolbar control, the notification area toolbar will rudely\r\n\t\t\t# bounce the focus back to the object under the mouse after a brief pause.\r\n\t\t\t# Moving the mouse to the focus object isn't a good solution because\r\n\t\t\t# sometimes, the focus can't be moved away from the object under the mouse.\r\n\t\t\t# Therefore, move the mouse out of the way.\r\n\t\t\twinUser.setCursorPos(0, 0)\r\n\r\n\t\tif self.role == controlTypes.ROLE_TOOLBAR:\r\n\t\t\t# Sometimes, the toolbar itself receives the focus instead of the focused child.\r\n\t\t\t# However, the focused child still has the focused state.\r\n\t\t\tfor child in self.children:\r\n\t\t\t\tif child.hasFocus:\r\n\t\t\t\t\t# Redirect the focus to the focused child.\r\n\t\t\t\t\teventHandler.executeEvent(\"gainFocus\", child)\r\n\t\t\t\t\treturn\r\n\t\t\t# We've really landed on the toolbar itself.\r\n\t\t\t# This was probably caused by moving the mouse out of the way in a previous focus event.\r\n\t\t\t# This previous focus event is no longer useful, so cancel speech.\r\n\t\t\tspeech.cancelSpeech()\r\n\r\n\t\tif eventHandler.isPendingEvents(\"gainFocus\"):\r\n\t\t\treturn\r\n\t\tsuper(NotificationArea, self).event_gainFocus()\r\n\r\n\r\nclass GridTileElement(UIA):\r\n\r\n\trole=controlTypes.ROLE_TABLECELL\r\n\r\n\tdef _get_description(self):\r\n\t\tname=self.name\r\n\t\tdescriptionStrings=[]\r\n\t\tfor child in self.children:\r\n\t\t\tdescription=child.basicText\r\n\t\t\tif not description or description==name: continue\r\n\t\t\tdescriptionStrings.append(description)\r\n\t\treturn \" \".join(descriptionStrings)\r\n\t\treturn description\r\n\r\n\r\nclass GridListTileElement(UIA):\r\n\trole=controlTypes.ROLE_TABLECELL\r\n\tdescription=None\r\n\r\n\r\nclass GridGroup(UIA):\r\n\t\"\"\"A group in the Windows 8 Start Menu.\r\n\t\"\"\"\r\n\tpresentationType=UIA.presType_content\r\n\r\n\t# Normally the name is the first tile which is rather redundant\r\n\t# However some groups have custom header text which should be read instead\r\n\tdef _get_name(self):\r\n\t\tchild=self.firstChild\r\n\t\tif isinstance(child,UIA):\r\n\t\t\ttry:\r\n\t\t\t\tautomationID=child.UIAElement.currentAutomationID\r\n\t\t\texcept COMError:\r\n\t\t\t\tautomationID=None\r\n\t\t\tif automationID==\"GridListGroupHeader\":\r\n\t\t\t\treturn child.name\r\n\r\n\r\nclass ImmersiveLauncher(UIA):\r\n\t# When the Windows 8 start screen opens, focus correctly goes to the first tile, but then incorrectly back to the root of the window.\r\n\t# Ignore focus events on this object.\r\n\tshouldAllowUIAFocusEvent=False\r\n\r\n\r\nclass StartButton(IAccessible):\r\n\t\"\"\"For Windows 8.1 and 10 Start buttons to be recognized as proper buttons and to suppress selection announcement.\"\"\"\r\n\r\n\trole = controlTypes.ROLE_BUTTON\r\n\r\n\tdef _get_states(self):\r\n\t\t# #5178: Selection announcement should be suppressed.\r\n\t\t# Borrowed from Mozilla objects in NVDAObjects/IAccessible/Mozilla.py.\r\n\t\tstates = super(StartButton, self).states\r\n\t\tstates.discard(controlTypes.STATE_SELECTED)\r\n\t\treturn states\r\n\r\n\r\nclass AppModule(appModuleHandler.AppModule):\r\n\r\n\tdef chooseNVDAObjectOverlayClasses(self, obj, clsList):\r\n\t\twindowClass = obj.windowClassName\r\n\t\trole = obj.role\r\n\r\n\t\tif windowClass in (\"Search Box\",\"UniversalSearchBand\") and role==controlTypes.ROLE_PANE and isinstance(obj,IAccessible):\r\n\t\t\tclsList.insert(0,SearchBoxClient)\r\n\t\t\treturn\r\n\r\n\t\tif windowClass == \"ToolbarWindow32\" and role == controlTypes.ROLE_POPUPMENU:\r\n\t\t\tparent = obj.parent\r\n\t\t\tif parent and parent.windowClassName == \"SysPager\" and obj.windowStyle & 0x80:\r\n\t\t\t\tclsList.insert(0, ClassicStartMenu)\r\n\t\t\treturn\r\n\r\n\t\tif windowClass == \"SysListView32\" and role == controlTypes.ROLE_MENUITEM:\r\n\t\t\tclsList.insert(0, SysListView32MenuItem)\r\n\t\t\treturn\r\n\r\n\t\tif windowClass == \"ToolbarWindow32\":\r\n\t\t\t# Check whether this is the notification area, a.k.a. system tray.\r\n\t\t\tif isinstance(obj.parent, ClassicStartMenu):\r\n\t\t\t\treturn # This can't be a notification area\r\n\t\t\ttry:\r\n\t\t\t\t# The toolbar's immediate parent is its window object, so we need to go one further.\r\n\t\t\t\ttoolbarParent = obj.parent.parent\r\n\t\t\t\tif role != controlTypes.ROLE_TOOLBAR:\r\n\t\t\t\t\t# Toolbar item.\r\n\t\t\t\t\ttoolbarParent = toolbarParent.parent\r\n\t\t\texcept AttributeError:\r\n\t\t\t\ttoolbarParent = None\r\n\t\t\tif toolbarParent and toolbarParent.windowClassName == \"SysPager\":\r\n\t\t\t\tclsList.insert(0, NotificationArea)\r\n\t\t\t\treturn\r\n\r\n\t\t# #5178: Start button in Windows 8.1 and 10 should not have been a list in the first place.\r\n\t\tif windowClass == \"Start\" and role in (controlTypes.ROLE_LIST, controlTypes.ROLE_BUTTON):\r\n\t\t\tif role == controlTypes.ROLE_LIST:\r\n\t\t\t\tclsList.remove(List)\r\n\t\t\tclsList.insert(0, StartButton)\r\n\r\n\t\tif isinstance(obj, UIA):\r\n\t\t\tuiaClassName = obj.UIAElement.cachedClassName\r\n\t\t\tif uiaClassName == \"GridTileElement\":\r\n\t\t\t\tclsList.insert(0, GridTileElement)\r\n\t\t\telif uiaClassName == \"GridListTileElement\":\r\n\t\t\t\tclsList.insert(0, GridListTileElement)\r\n\t\t\telif uiaClassName == \"GridGroup\":\r\n\t\t\t\tclsList.insert(0, GridGroup)\r\n\t\t\telif uiaClassName == \"ImmersiveLauncher\" and role == controlTypes.ROLE_PANE:\r\n\t\t\t\tclsList.insert(0, ImmersiveLauncher)\r\n\t\t\telif uiaClassName==\"ListViewItem\" and obj.UIAElement.cachedAutomationId.startswith('Suggestion_'):\r\n\t\t\t\tclsList.insert(0,SuggestionListItem)\r\n\t\t\telif uiaClassName==\"MultitaskingViewFrame\" and role==controlTypes.ROLE_WINDOW:\r\n\t\t\t\tclsList.insert(0,MultitaskingViewFrameWindow)\r\n\t\t\telif obj.windowClassName==\"MultitaskingViewFrame\" and role==controlTypes.ROLE_LISTITEM:\r\n\t\t\t\tclsList.insert(0,MultitaskingViewFrameListItem)\r\n\r\n\tdef event_NVDAObject_init(self, obj):\r\n\t\twindowClass = obj.windowClassName\r\n\t\trole = obj.role\r\n\r\n\t\tif windowClass == \"ToolbarWindow32\" and role == controlTypes.ROLE_POPUPMENU:\r\n\t\t\tparent = obj.parent\r\n\t\t\tif parent and parent.windowClassName == \"SysPager\" and not (obj.windowStyle & 0x80):\r\n\t\t\t\t# This is the menu for a group of icons on the task bar, which Windows stupidly names \"Application\".\r\n\t\t\t\tobj.name = None\r\n\t\t\treturn\r\n\r\n\t\tif windowClass == \"#32768\":\r\n\t\t\t# Standard menu.\r\n\t\t\tparent = obj.parent\r\n\t\t\tif parent and not parent.parent:\r\n\t\t\t\t# Context menu.\r\n\t\t\t\t# We don't trust the names that Explorer gives to context menus, so better to have no name at all.\r\n\t\t\t\tobj.name = None\r\n\t\t\treturn\r\n\r\n\t\tif windowClass == \"DV2ControlHost\" and role == controlTypes.ROLE_PANE:\r\n\t\t\t# Windows Vista/7 start menu.\r\n\t\t\tobj.presentationType=obj.presType_content\r\n\t\t\tobj.isPresentableFocusAncestor = True\r\n\t\t\t# In Windows 7, the description of this pane is extremely verbose help text, so nuke it.\r\n\t\t\tobj.description = None\r\n\t\t\treturn\r\n\r\n\t\t# The Address bar is embedded inside a progressbar, how strange.\r\n\t\t# Lets hide that\r\n\t\tif windowClass==\"msctls_progress32\" and winUser.getClassName(winUser.getAncestor(obj.windowHandle,winUser.GA_PARENT))==\"Address Band Root\":\r\n\t\t\tobj.presentationType=obj.presType_layout\r\n\r\n\tdef event_gainFocus(self, obj, nextHandler):\r\n\t\twClass = obj.windowClassName\r\n\t\tif wClass == \"ToolbarWindow32\" and obj.role == controlTypes.ROLE_MENUITEM and obj.parent.role == controlTypes.ROLE_MENUBAR and eventHandler.isPendingEvents(\"gainFocus\"):\r\n\t\t\t# When exiting a menu, Explorer fires focus on the top level menu item before it returns to the previous focus.\r\n\t\t\t# Unfortunately, this focus event always occurs in a subsequent cycle, so the event limiter doesn't eliminate it.\r\n\t\t\t# Therefore, if there is a pending focus event, don't bother handling this event.\r\n\t\t\treturn\r\n\r\n\t\tif wClass == \"ForegroundStaging\":\r\n\t\t\t# #5116: The Windows 10 Task View fires foreground/focus on this weird invisible window before and after it appears.\r\n\t\t\t# This causes NVDA to report \"unknown\", so ignore it.\r\n\t\t\t# We can't do this using shouldAllowIAccessibleFocusEvent because this isn't checked for foreground.\r\n\t\t\treturn\r\n\r\n\t\tif wClass == \"WorkerW\" and obj.role == controlTypes.ROLE_PANE and obj.name is None:\r\n\t\t\t# #6671: Never allow WorkerW thread to send gain focus event, as it causes 'pane\" to be announced when minimizing windows or moving to desktop.\r\n\t\t\treturn\r\n\r\n\t\tnextHandler()\r\n", "path": "source/appModules/explorer.py"}], "after_files": [{"content": "#appModules/explorer.py\r\n#A part of NonVisual Desktop Access (NVDA)\r\n#Copyright (C) 2006-2018 NV Access Limited, Joseph Lee\r\n#This file is covered by the GNU General Public License.\r\n#See the file COPYING for more details.\r\n\r\n\"\"\"App module for Windows Explorer (aka Windows shell).\r\nProvides workarounds for controls such as identifying Start button, notification area and others.\r\n\"\"\"\r\n\r\nfrom comtypes import COMError\r\nimport time\r\nimport appModuleHandler\r\nimport controlTypes\r\nimport winUser\r\nimport api\r\nimport speech\r\nimport eventHandler\r\nimport mouseHandler\r\nfrom NVDAObjects.window import Window\r\nfrom NVDAObjects.IAccessible import sysListView32, IAccessible, List\r\nfrom NVDAObjects.UIA import UIA\r\n\r\n# Suppress incorrect Win 10 Task switching window focus\r\nclass MultitaskingViewFrameWindow(UIA):\r\n\tshouldAllowUIAFocusEvent=False\r\n\r\n\r\n# Suppress focus ancestry for task switching list items if alt is held down (alt+tab)\r\nclass MultitaskingViewFrameListItem(UIA):\r\n\r\n\tdef _get_container(self):\r\n\t\tif winUser.getAsyncKeyState(winUser.VK_MENU)&32768:\r\n\t\t\treturn api.getDesktopObject()\r\n\t\telse:\r\n\t\t\treturn super(MultitaskingViewFrameListItem,self).container\r\n\r\n\r\n# Support for Win8 start screen search suggestions.\r\nclass SuggestionListItem(UIA):\r\n\r\n\tdef event_UIA_elementSelected(self):\r\n\t\tspeech.cancelSpeech()\r\n\t\tapi.setNavigatorObject(self, isFocus=True)\r\n\t\tself.reportFocus()\r\n\t\tsuper(SuggestionListItem,self).event_UIA_elementSelected()\r\n\r\n\r\n# Windows 8 hack: Class to disable incorrect focus on windows 8 search box (containing the already correctly focused edit field)\r\nclass SearchBoxClient(IAccessible):\r\n\tshouldAllowIAccessibleFocusEvent=False\r\n\r\n\r\n# Class for menu items  for Windows Places and Frequently used Programs (in start menu)\r\nclass SysListView32MenuItem(sysListView32.ListItemWithoutColumnSupport):\r\n\r\n\t# #474: When focus moves to these items, an extra focus is fired on the parent\r\n\t# However NVDA redirects it to the real focus.\r\n\t# But this means double focus events on the item, so filter the second one out\r\n\tdef _get_shouldAllowIAccessibleFocusEvent(self):\r\n\t\tres=super(SysListView32MenuItem,self).shouldAllowIAccessibleFocusEvent\r\n\t\tif not res:\r\n\t\t\treturn False\r\n\t\tfocus=eventHandler.lastQueuedFocusObject\r\n\t\tif type(focus)!=type(self) or (self.event_windowHandle,self.event_objectID,self.event_childID)!=(focus.event_windowHandle,focus.event_objectID,focus.event_childID):\r\n\t\t\treturn True\r\n\t\treturn False\r\n\r\n\r\nclass ClassicStartMenu(Window):\r\n\t# Override the name, as Windows names this the \"Application\" menu contrary to all documentation.\r\n\t# Translators: The title of Start menu/screen in your language (only the word start).\r\n\tname = _(\"Start\")\r\n\r\n\tdef event_gainFocus(self):\r\n\t\t# In Windows XP, the Start button will get focus first, so silence this.\r\n\t\tspeech.cancelSpeech()\r\n\t\tsuper(ClassicStartMenu, self).event_gainFocus()\r\n\r\n\r\nclass NotificationArea(IAccessible):\r\n\t\"\"\"The Windows notification area, a.k.a. system tray.\r\n\t\"\"\"\r\n\r\n\tdef event_gainFocus(self):\r\n\t\tif mouseHandler.lastMouseEventTime < time.time() - 0.2:\r\n\t\t\t# This focus change was not caused by a mouse event.\r\n\t\t\t# If the mouse is on another toolbar control, the notification area toolbar will rudely\r\n\t\t\t# bounce the focus back to the object under the mouse after a brief pause.\r\n\t\t\t# Moving the mouse to the focus object isn't a good solution because\r\n\t\t\t# sometimes, the focus can't be moved away from the object under the mouse.\r\n\t\t\t# Therefore, move the mouse out of the way.\r\n\t\t\twinUser.setCursorPos(0, 0)\r\n\r\n\t\tif self.role == controlTypes.ROLE_TOOLBAR:\r\n\t\t\t# Sometimes, the toolbar itself receives the focus instead of the focused child.\r\n\t\t\t# However, the focused child still has the focused state.\r\n\t\t\tfor child in self.children:\r\n\t\t\t\tif child.hasFocus:\r\n\t\t\t\t\t# Redirect the focus to the focused child.\r\n\t\t\t\t\teventHandler.executeEvent(\"gainFocus\", child)\r\n\t\t\t\t\treturn\r\n\t\t\t# We've really landed on the toolbar itself.\r\n\t\t\t# This was probably caused by moving the mouse out of the way in a previous focus event.\r\n\t\t\t# This previous focus event is no longer useful, so cancel speech.\r\n\t\t\tspeech.cancelSpeech()\r\n\r\n\t\tif eventHandler.isPendingEvents(\"gainFocus\"):\r\n\t\t\treturn\r\n\t\tsuper(NotificationArea, self).event_gainFocus()\r\n\r\n\r\nclass GridTileElement(UIA):\r\n\r\n\trole=controlTypes.ROLE_TABLECELL\r\n\r\n\tdef _get_description(self):\r\n\t\tname=self.name\r\n\t\tdescriptionStrings=[]\r\n\t\tfor child in self.children:\r\n\t\t\tdescription=child.basicText\r\n\t\t\tif not description or description==name: continue\r\n\t\t\tdescriptionStrings.append(description)\r\n\t\treturn \" \".join(descriptionStrings)\r\n\t\treturn description\r\n\r\n\r\nclass GridListTileElement(UIA):\r\n\trole=controlTypes.ROLE_TABLECELL\r\n\tdescription=None\r\n\r\n\r\nclass GridGroup(UIA):\r\n\t\"\"\"A group in the Windows 8 Start Menu.\r\n\t\"\"\"\r\n\tpresentationType=UIA.presType_content\r\n\r\n\t# Normally the name is the first tile which is rather redundant\r\n\t# However some groups have custom header text which should be read instead\r\n\tdef _get_name(self):\r\n\t\tchild=self.firstChild\r\n\t\tif isinstance(child,UIA):\r\n\t\t\ttry:\r\n\t\t\t\tautomationID=child.UIAElement.currentAutomationID\r\n\t\t\texcept COMError:\r\n\t\t\t\tautomationID=None\r\n\t\t\tif automationID==\"GridListGroupHeader\":\r\n\t\t\t\treturn child.name\r\n\r\n\r\nclass ImmersiveLauncher(UIA):\r\n\t# When the Windows 8 start screen opens, focus correctly goes to the first tile, but then incorrectly back to the root of the window.\r\n\t# Ignore focus events on this object.\r\n\tshouldAllowUIAFocusEvent=False\r\n\r\n\r\nclass StartButton(IAccessible):\r\n\t\"\"\"For Windows 8.1 and 10 Start buttons to be recognized as proper buttons and to suppress selection announcement.\"\"\"\r\n\r\n\trole = controlTypes.ROLE_BUTTON\r\n\r\n\tdef _get_states(self):\r\n\t\t# #5178: Selection announcement should be suppressed.\r\n\t\t# Borrowed from Mozilla objects in NVDAObjects/IAccessible/Mozilla.py.\r\n\t\tstates = super(StartButton, self).states\r\n\t\tstates.discard(controlTypes.STATE_SELECTED)\r\n\t\treturn states\r\n\r\n\r\nclass AppModule(appModuleHandler.AppModule):\r\n\r\n\tdef chooseNVDAObjectOverlayClasses(self, obj, clsList):\r\n\t\twindowClass = obj.windowClassName\r\n\t\trole = obj.role\r\n\r\n\t\tif windowClass in (\"Search Box\",\"UniversalSearchBand\") and role==controlTypes.ROLE_PANE and isinstance(obj,IAccessible):\r\n\t\t\tclsList.insert(0,SearchBoxClient)\r\n\t\t\treturn\r\n\r\n\t\tif windowClass == \"ToolbarWindow32\" and role == controlTypes.ROLE_POPUPMENU:\r\n\t\t\tparent = obj.parent\r\n\t\t\tif parent and parent.windowClassName == \"SysPager\" and obj.windowStyle & 0x80:\r\n\t\t\t\tclsList.insert(0, ClassicStartMenu)\r\n\t\t\treturn\r\n\r\n\t\tif windowClass == \"SysListView32\" and role == controlTypes.ROLE_MENUITEM:\r\n\t\t\tclsList.insert(0, SysListView32MenuItem)\r\n\t\t\treturn\r\n\r\n\t\tif windowClass == \"ToolbarWindow32\":\r\n\t\t\t# Check whether this is the notification area, a.k.a. system tray.\r\n\t\t\tif isinstance(obj.parent, ClassicStartMenu):\r\n\t\t\t\treturn # This can't be a notification area\r\n\t\t\ttry:\r\n\t\t\t\t# The toolbar's immediate parent is its window object, so we need to go one further.\r\n\t\t\t\ttoolbarParent = obj.parent.parent\r\n\t\t\t\tif role != controlTypes.ROLE_TOOLBAR:\r\n\t\t\t\t\t# Toolbar item.\r\n\t\t\t\t\ttoolbarParent = toolbarParent.parent\r\n\t\t\texcept AttributeError:\r\n\t\t\t\ttoolbarParent = None\r\n\t\t\tif toolbarParent and toolbarParent.windowClassName == \"SysPager\":\r\n\t\t\t\tclsList.insert(0, NotificationArea)\r\n\t\t\t\treturn\r\n\r\n\t\t# #5178: Start button in Windows 8.1 and 10 should not have been a list in the first place.\r\n\t\tif windowClass == \"Start\" and role in (controlTypes.ROLE_LIST, controlTypes.ROLE_BUTTON):\r\n\t\t\tif role == controlTypes.ROLE_LIST:\r\n\t\t\t\tclsList.remove(List)\r\n\t\t\tclsList.insert(0, StartButton)\r\n\r\n\t\tif isinstance(obj, UIA):\r\n\t\t\tuiaClassName = obj.UIAElement.cachedClassName\r\n\t\t\tif uiaClassName == \"GridTileElement\":\r\n\t\t\t\tclsList.insert(0, GridTileElement)\r\n\t\t\telif uiaClassName == \"GridListTileElement\":\r\n\t\t\t\tclsList.insert(0, GridListTileElement)\r\n\t\t\telif uiaClassName == \"GridGroup\":\r\n\t\t\t\tclsList.insert(0, GridGroup)\r\n\t\t\telif uiaClassName == \"ImmersiveLauncher\" and role == controlTypes.ROLE_PANE:\r\n\t\t\t\tclsList.insert(0, ImmersiveLauncher)\r\n\t\t\telif uiaClassName==\"ListViewItem\" and obj.UIAElement.cachedAutomationId.startswith('Suggestion_'):\r\n\t\t\t\tclsList.insert(0,SuggestionListItem)\r\n\t\t\telif uiaClassName==\"MultitaskingViewFrame\" and role==controlTypes.ROLE_WINDOW:\r\n\t\t\t\tclsList.insert(0,MultitaskingViewFrameWindow)\r\n\t\t\telif obj.windowClassName==\"MultitaskingViewFrame\" and role==controlTypes.ROLE_LISTITEM:\r\n\t\t\t\tclsList.insert(0,MultitaskingViewFrameListItem)\r\n\r\n\tdef event_NVDAObject_init(self, obj):\r\n\t\twindowClass = obj.windowClassName\r\n\t\trole = obj.role\r\n\r\n\t\tif windowClass == \"ToolbarWindow32\" and role == controlTypes.ROLE_POPUPMENU:\r\n\t\t\tparent = obj.parent\r\n\t\t\tif parent and parent.windowClassName == \"SysPager\" and not (obj.windowStyle & 0x80):\r\n\t\t\t\t# This is the menu for a group of icons on the task bar, which Windows stupidly names \"Application\".\r\n\t\t\t\tobj.name = None\r\n\t\t\treturn\r\n\r\n\t\tif windowClass == \"#32768\":\r\n\t\t\t# Standard menu.\r\n\t\t\tparent = obj.parent\r\n\t\t\tif parent and not parent.parent:\r\n\t\t\t\t# Context menu.\r\n\t\t\t\t# We don't trust the names that Explorer gives to context menus, so better to have no name at all.\r\n\t\t\t\tobj.name = None\r\n\t\t\treturn\r\n\r\n\t\tif windowClass == \"DV2ControlHost\" and role == controlTypes.ROLE_PANE:\r\n\t\t\t# Windows Vista/7 start menu.\r\n\t\t\tobj.presentationType=obj.presType_content\r\n\t\t\tobj.isPresentableFocusAncestor = True\r\n\t\t\t# In Windows 7, the description of this pane is extremely verbose help text, so nuke it.\r\n\t\t\tobj.description = None\r\n\t\t\treturn\r\n\r\n\t\t# The Address bar is embedded inside a progressbar, how strange.\r\n\t\t# Lets hide that\r\n\t\tif windowClass==\"msctls_progress32\" and winUser.getClassName(winUser.getAncestor(obj.windowHandle,winUser.GA_PARENT))==\"Address Band Root\":\r\n\t\t\tobj.presentationType=obj.presType_layout\r\n\r\n\tdef event_gainFocus(self, obj, nextHandler):\r\n\t\twClass = obj.windowClassName\r\n\t\tif wClass == \"ToolbarWindow32\" and obj.role == controlTypes.ROLE_MENUITEM and obj.parent.role == controlTypes.ROLE_MENUBAR and eventHandler.isPendingEvents(\"gainFocus\"):\r\n\t\t\t# When exiting a menu, Explorer fires focus on the top level menu item before it returns to the previous focus.\r\n\t\t\t# Unfortunately, this focus event always occurs in a subsequent cycle, so the event limiter doesn't eliminate it.\r\n\t\t\t# Therefore, if there is a pending focus event, don't bother handling this event.\r\n\t\t\treturn\r\n\r\n\t\tif wClass in (\"ForegroundStaging\", \"LauncherTipWnd\", \"ApplicationManager_DesktopShellWindow\"):\r\n\t\t\t# #5116: The Windows 10 Task View fires foreground/focus on this weird invisible window and foreground staging screen before and after it appears.\r\n\t\t\t# This causes NVDA to report \"unknown\", so ignore it.\r\n\t\t\t# We can't do this using shouldAllowIAccessibleFocusEvent because this isn't checked for foreground.\r\n\t\t\t# #8137: also seen when opening quick link menu (Windows+X) on Windows 8 and later.\r\n\t\t\treturn\r\n\r\n\t\tif wClass == \"WorkerW\" and obj.role == controlTypes.ROLE_PANE and obj.name is None:\r\n\t\t\t# #6671: Never allow WorkerW thread to send gain focus event, as it causes 'pane\" to be announced when minimizing windows or moving to desktop.\r\n\t\t\treturn\r\n\r\n\t\tnextHandler()\r\n", "path": "source/appModules/explorer.py"}]}