Repository: nvaccess/nvda

Issue:
Windows 10 build 15002: cannot activate browse/focus mode in Edge, cannot navigate to the document by tabbing around
Hi,

Related to #6712: In Windows 10 build 15002, when using Edge, one cannot move to the document when tabbing around nor toggle focus/browse mode.

STR:

1. Install build 15002.
2. Open Edge, then try tabbing around to see if you can locate the document.

Expected: one can tab to the document and toggle focus/browse mode.
Actual: Where there should have been a document, NVDA says, "unknown".
Observation: in build 15002, there is a new "frame" that is sort of a parent of the actual document, whereas this isn't there in prior builds.
Impact: Major, as this prevents people from testing various enhancements to Edge support that are now part of master branch snapshots.

Setup:

* NVDA version: next.13795
* OS: Windows 10 build 15002

Thanks.


Discussion:
I think this should be priority 1 to look into. We need to get some feel for the cause of this and cost to fix it.
Edge documents are no longer contained within the expected Edge root container UIAElement. Thus NVDA does not give them browseMode.
The document either seems to be contained with in a grouping with a name of "WebRuntime Component View" or sometimes this parent is skipped altogether. 
The reason NVDA no longer tracks focus is eventHandler.shouldAcceptEvent is now returning false. I'm guessing some kind of foreground window check is failing?
I'm going to have a bit of a chat to the Edge teem in the next two days to see if we can shed any light on this brokenness.
NVDA is itself changing the role of the document to frame, as  we have code that does this if it finds a pain in edge with the textPattern yet is not a direct child of  the EdgeRoot container.
Filed MS Bug 10566743: NVDA can no longer access the content of documents in Microsoft Edge

Resolving patch:
diff --git a/source/NVDAObjects/UIA/__init__.py b/source/NVDAObjects/UIA/__init__.py
--- a/source/NVDAObjects/UIA/__init__.py
+++ b/source/NVDAObjects/UIA/__init__.py
@@ -567,7 +567,7 @@ def findOverlayClasses(self,clsList):
 			import edge
 			if UIAClassName in ("Internet Explorer_Server","WebView") and self.role==controlTypes.ROLE_PANE:
 				clsList.append(edge.EdgeHTMLRootContainer)
-			elif self.UIATextPattern and isinstance(self.parent,edge.EdgeHTMLRootContainer):
+			elif self.UIATextPattern and self.role==controlTypes.ROLE_PANE and self.parent and (isinstance(self.parent,edge.EdgeHTMLRootContainer) or not isinstance(self.parent,edge.EdgeNode)): 
 				clsList.append(edge.EdgeHTMLRoot)
 			elif self.role==controlTypes.ROLE_LIST:
 				clsList.append(edge.EdgeList)
diff --git a/source/NVDAObjects/UIA/edge.py b/source/NVDAObjects/UIA/edge.py
--- a/source/NVDAObjects/UIA/edge.py
+++ b/source/NVDAObjects/UIA/edge.py
@@ -208,6 +208,10 @@ def _getTextWithFieldsForUIARange(self,rootElement,textRange,formatConfig,includ
 		startRange.MoveEndpointByRange(UIAHandler.TextPatternRangeEndpoint_End,enclosingRange,UIAHandler.TextPatternRangeEndpoint_End)
 		if startRange.CompareEndpoints(UIAHandler.TextPatternRangeEndpoint_End,textRange,UIAHandler.TextPatternRangeEndpoint_End)>0:
 			startRange.MoveEndpointByRange(UIAHandler.TextPatternRangeEndpoint_End,textRange,UIAHandler.TextPatternRangeEndpoint_End)
+		# Ensure we don't now have a collapsed range
+		if startRange.CompareEndpoints(UIAHandler.TextPatternRangeEndpoint_End,startRange,UIAHandler.TextPatternRangeEndpoint_Start)<=0:
+			log.debug("Collapsed range. Returning")
+			return
 		# check for an embedded child
 		childElements=startRange.getChildren()
 		if childElements.length==1 and UIAHandler.handler.clientObject.compareElements(rootElement,childElements.getElement(0)):
diff --git a/source/eventHandler.py b/source/eventHandler.py
--- a/source/eventHandler.py
+++ b/source/eventHandler.py
@@ -256,6 +256,13 @@ def shouldAcceptEvent(eventName, windowHandle=None):
 		# #5595: Events for the cursor get mapped to the desktop window.
 		return True
 
+	# #6713: Edge (and soon all UWP apps) will no longer have windows as descendants of the foreground window.
+	# However, it does look like they are always  equal to or descendants of the "active" window of the input thread. 
+	if wClass.startswith('Windows.UI.Core'):
+		gi=winUser.getGUIThreadInfo(0)
+		if winUser.isDescendantWindow(gi.hwndActive,windowHandle):
+			return True
+
 	fg = winUser.getForegroundWindow()
 	if wClass == "NetUIHWND" and winUser.getClassName(fg) == "Net UI Tool Window Layered":
 		# #5504: In Office >= 2013 with the ribbon showing only tabs,


Test patch: