Repository: nvaccess/nvda

Issue:
Microsoft Teams: Menu focused when trying to read a message
### Steps to reproduce:
1. Install most recent Teams
2. Focus an incoming message in a chat or team channel.

### Actual behavior:
NVDA reads the incoming message.

### Expected behavior:
NVDA starts reading the incoming message, but this is suppressed by a menu getting focus. This is the menu that allows you to pick a reaction for a message (e.g. like). A focus triggers this menu. It doesn't strictly gain focus, however NVDA"s handling of the menuStart event redirects focus to it.

### System configuration
#### NVDA installed/portable/running from source:
Installed

#### NVDA version:
alpha-21324

#### Windows version:
Windows 10 20H2

#### Name and version of other software in use when reproducing the issue:
Microsoft Teams 1.3.00.28779
Builds like 1.3.00.26xxx don't suffer from this.

### Other questions
#### Does the issue still occur after restarting your computer?
Yes

#### Have you tried any other versions of NVDA? If so, please report their behaviors.
Yes

#### If addons are disabled, is your problem still occuring?
Yes

#### Did you try to run the COM registry fixing tool in NVDA menu / tools?
N/a


Discussion:
Relevant logging:

```
DEBUG - IAccessibleHandler.internalWinEventHandler.winEventCallback (09:52:40.166) - MainThread (15784):
Hook received winEvent: EVENT_OBJECT_SHOW, window 1967980 (Chrome_RenderWidgetHostHWND), objectID OBJID_CLIENT, childID -59951, process 2296 (teams), thread 19832
DEBUG - IAccessibleHandler.internalWinEventHandler.winEventCallback (09:52:40.166) - MainThread (15784):
Adding winEvent to limiter: EVENT_OBJECT_SHOW, window 1967980 (Chrome_RenderWidgetHostHWND), objectID OBJID_CLIENT, childID -59951, process 2296 (teams), thread 19832
DEBUG - IAccessibleHandler.internalWinEventHandler.winEventCallback (09:52:40.166) - MainThread (15784):
Hook received winEvent: EVENT_SYSTEM_MENUPOPUPSTART, window 1967980 (Chrome_RenderWidgetHostHWND), objectID OBJID_CLIENT, childID -59951, process 2296 (teams), thread 19832
DEBUG - IAccessibleHandler.internalWinEventHandler.winEventCallback (09:52:40.166) - MainThread (15784):
Adding winEvent to limiter: EVENT_SYSTEM_MENUPOPUPSTART, window 1967980 (Chrome_RenderWidgetHostHWND), objectID OBJID_CLIENT, childID -59951, process 2296 (teams), thread 19832
...
DEBUG - IAccessibleHandler.orderedWinEventLimiter.OrderedWinEventLimiter.flushEvents (09:52:40.191) - MainThread (15784):
Emitting winEvent EVENT_OBJECT_SHOW, window 1967980 (Chrome_RenderWidgetHostHWND), objectID OBJID_CLIENT, childID -59951, process 2296 (teams), thread 19832
DEBUG - IAccessibleHandler.orderedWinEventLimiter.OrderedWinEventLimiter.flushEvents (09:52:40.191) - MainThread (15784):
Emitting winEvent EVENT_SYSTEM_MENUPOPUPSTART, window 1967980 (Chrome_RenderWidgetHostHWND), objectID OBJID_CLIENT, childID -59951, process 2296 (teams), thread 19832
...
DEBUG - IAccessibleHandler.processMenuStartWinEvent (09:52:40.192) - MainThread (15784):
Processing menuStart winEvent: window 1967980 (Chrome_RenderWidgetHostHWND), objectID OBJID_CLIENT, childID -59951, process 2296 (teams), validFocus False
DEBUG - IAccessibleHandler.winEventToNVDAEvent (09:52:40.192) - MainThread (15784):
Creating NVDA event from winEvent: EVENT_SYSTEM_MENUPOPUPSTART, window 1967980 (Chrome_RenderWidgetHostHWND), objectID OBJID_CLIENT, childID -59951, process 2296 (teams), use cache True
DEBUG - IAccessibleHandler.winEventToNVDAEvent (09:52:40.192) - MainThread (15784):
winEvent mapped to NVDA event: menuStart
DEBUG - IAccessibleHandler.winEventToNVDAEvent (09:52:40.197) - MainThread (15784):
Successfully created NVDA event menuStart for <NVDAObjects.IAccessible.ia2Web.Ia2Web object at 0x06458E30> from winEvent EVENT_SYSTEM_MENUPOPUPSTART, window 1967980 (Chrome_RenderWidgetHostHWND), objectID OBJID_CLIENT, childID -59951, process 2296 (teams)
IO - speech.speak (09:52:40.237) - MainThread (15784):
Speaking ['menu', CancellableSpeech (still valid)]
```
Just tested with JAWS, also no issues there. Marking this P2.

Resolving patch:
diff --git a/source/IAccessibleHandler/__init__.py b/source/IAccessibleHandler/__init__.py
--- a/source/IAccessibleHandler/__init__.py
+++ b/source/IAccessibleHandler/__init__.py
@@ -990,6 +990,13 @@ def processMenuStartWinEvent(eventID, window, objectID, childID, validFocus):
 	if obj.IAccessibleRole != oleacc.ROLE_SYSTEM_MENUPOPUP:
 		# menuStart on anything other than a menu is silly.
 		return
+	elif not obj.shouldAllowIAccessibleMenuStartEvent:
+		if isMSAADebugLoggingEnabled():
+			log.debug(
+				f"Ignoring menuStart winEvent: {getWinEventLogInfo(window, objectID, childID)}, "
+				f"shouldAllowIAccessibleMenuStartEvent {obj.shouldAllowIAccessibleMenuStartEvent}"
+			)
+		return
 	processFocusNVDAEvent(obj, force=True)
 
 
diff --git a/source/NVDAObjects/IAccessible/__init__.py b/source/NVDAObjects/IAccessible/__init__.py
--- a/source/NVDAObjects/IAccessible/__init__.py
+++ b/source/NVDAObjects/IAccessible/__init__.py
@@ -694,6 +694,13 @@ def _get_shouldAllowIAccessibleFocusEvent(self):
 			return False
 		return True
 
+	def _get_shouldAllowIAccessibleMenuStartEvent(self) -> bool:
+		"""Determine whether an IAccessible menu start or menu popup start event should be allowed
+		for this object.
+		@return: C{True} if the event should be allowed.
+		"""
+		return True
+
 	def _get_TextInfo(self):
 		if hasattr(self,'IAccessibleTextObject'):
 			return IA2TextTextInfo
diff --git a/source/appModules/teams.py b/source/appModules/teams.py
new file mode 100644
--- /dev/null
+++ b/source/appModules/teams.py
@@ -0,0 +1,27 @@
+# A part of NonVisual Desktop Access (NVDA)
+# Copyright (C) 2020 NV Access Limited, Leonard de Ruijter
+# This file is covered by the GNU General Public License.
+# See the file COPYING for more details.
+
+""" App module for Microsoft Teams.
+"""
+
+import appModuleHandler
+from NVDAObjects.IAccessible.ia2Web import Ia2Web
+
+
+class PopOverMenu(Ia2Web):
+	shouldAllowIAccessibleMenuStartEvent = False
+
+
+class AppModule(appModuleHandler.AppModule):
+
+	def chooseNVDAObjectOverlayClasses(self, obj, clsList):
+		if (
+			Ia2Web in clsList
+			and obj.IA2Attributes.get("xml-roles") == "menu"
+			and obj.parent
+			and obj.parent.parent
+			and "message-actions-popover-container" in obj.parent.parent.IA2Attributes.get("class", "")
+		):
+			clsList.insert(0, PopOverMenu)


Test patch: