Repository: nvaccess/nvda

Issue:
Alt must be pressed more than once for MS Office ribbons to gain focus with NVDA
**Reported by mdcurran on 2014-06-19 01:02**
The UI Automation implementation for MS Office ribbons does not fire a focus event the first time the ribbon is activate after starting NVDA. Due to this, and some other small deficiencies with roles and naming in that implementation, it is probably best to disable UI Automation for the MS Office ribbons entirely. This will mean ignoring UIA for any NetUIHWND window that is a descendant of an MsoCommandBar window.
**Blocking #970**



Discussion:
Comment 1 by Michael Curran &lt;mick@... on 2014-06-19 01:27
In [2e7b7911e81b8222f32e4c22047a8ddbfd1f926f]:
```CommitTicketReference repository="" revision="2e7b7911e81b8222f32e4c22047a8ddbfd1f926f"
Merge branch 't4207' into next. Incubates #4207

```
Changes:
Added labels: incubating
```

Comment 2 by Michael Curran &lt;mick@... on 2014-07-07 09:05
In [021d832f99616c24f90d5b1705261b8f11e0edb3]:
```CommitTicketReference repository="" revision="021d832f99616c24f90d5b1705261b8f11e0edb3"
Merge branch 't4207'. Fixes #4207

```
Changes:
Removed labels: incubating
State: closed
```

Comment 3 by mdcurran on 2014-07-07 09:06
Changes:
Milestone changed from None to 2014.3

Comment 5 by mdcurran on 2014-07-15 06:21
This fix broke detection and reporting of the Status bar in MS Office applications (#4257). Will need a different approach. 
Changes:
State: reopened

Comment 6 by mdcurran on 2014-07-15 06:37
Fix was reverted in 6fb9c10

Comment 7 by jteh on 2014-07-15 23:47
Changes:
Milestone changed from 2014.3 to None

@michaelDCurran Do you have any updates to share with regards to implementation notes for this issue? In my brief (and probably perfunctory testing) with Word 2010, there were two issues I noticed with variable degrees of consistency:
* When I opened a new blank Word document, pressing Alt only took me to the System submenu. Alt+H to specifically go to the Home tab in the ribbon didn't work either. I Alt+Tabbed to another already open Word document and replicated this same behaviour there. Maximizing the window resolved these oddities.
* Next, I opened a new blank Word document to retest these oddities, and pressing Alt did nothing. As reported by Mick in this ticket, the second Alt press was needed for NVDA to go to the ribbon. However, I was able to reproduce this successfully only once.
I was under the assumption that the needing to press alt twice had been fixed along time ago. I can't reproduce it with Word 2016.  As for my comment about not using UIA, it is worth mentioning that going forward, NVDA will exclusively use UIA for MS Word. See #7409. But, this will only be for Office 365. Can this specific issue of having to press alt twice be reproduced in Word 2013 / Word 2010? Getting the System menu when pressing alt seems like an entirely different issue to me. If pressing alt twice issue can't be reproduced in Word 2013 / Word 2010 this issue can be closed.
Yes, I am able to reproduce this issue in Word 2010 via the following STR:
* Open a new blank Word document.
* Press Alt.
Expected Result: NVDA should move to the Home tab on the ribbon.
Actual Result: NVDA stays quiet and nothing seems to happen.
* Press Alt again.
Expected Result: NVDA should move to the Home tab on the ribbon.
Actual Result: NVDA does move to the Home tab on the ribbon.
However, this behaviour can be experienced only once per Word document. Pressing Esc and Alt once for the same document as tested above will work as expected, but when a new blank Word document is opened, Alt needs to be pressed twice for accessing the ribbon for the first time. It may be worth noting that the Word window seemed maximized during my above tests.
Wait, upon retesting, the above STR wasn't exactly consistently reliable. I did manage to reproduce this two more times again, but it was hit and miss to some extent. What I noticed in the Log Viewer was that the Alt key press wasn't getting registered in the first place (as in the log showed inputs of Alt+Tab followed by NVDA+F1, although at one of these two times, I am sure Alt interrupted NVDA's speech for the window title. Regardless, it seems like Alt isn't getting sent to Word or the computer either due to a Word deficiency, or something wrong with my keyboard, or something of the sort. This is very trivial though, and I doubt it has got anything to do with NVDA anyways. I am happy for this to be closed because we can always reopen if someone can provide a more concrete method of replication.
I can definitely reproduce this with MS Excel 2010 on Windows 7 x64 100% of the time by simply launching Excel from the run box and pressing alt. When pressed for the first time nothing happens, the second press returns to the sheet and finally third press activates the ribbon. It is NVDA specific, because with the same STR when JAWS 2018 is running ribbon got reported with each alt press. Can this be reopened? It isn't life threatening, but very confusing, especially for new users.
cc @ehollig Could you reopen please?
I can reproduce this in MS Excel 2010 but only when pressing alt for the first time after opening the application. After pressing escape and then alt again, NVDA reports the ribbon accordingly
@lukaszgo1 thee were some changes for Excel 2007 in a recent alpha regarding formulas and regarding performance. Could you please test with last alpha if this is still an issue? I cannot reproduce it anymore in Office 2010 or higher. That PR might have had an effect on this.
Still reproducible. The PR mentioned by you had nothing to do with it.

Resolving patch:
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
@@ -2026,6 +2026,8 @@ def _get_value(self):
 	("AkelEditW",oleacc.ROLE_SYSTEM_CLIENT):"akelEdit.AkelEdit",
 	("AkelEditA",oleacc.ROLE_SYSTEM_CLIENT):"akelEdit.AkelEdit",
 	("MSOUNISTAT",oleacc.ROLE_SYSTEM_CLIENT):"msOffice.MSOUNISTAT",
+	("NetUIHWND", oleacc.ROLE_SYSTEM_PROPERTYPAGE): "msOffice.StatusBar",
+	("NetUIHWND", oleacc.ROLE_SYSTEM_TOOLBAR): "msOffice.RibbonSection",
 	("QWidget",oleacc.ROLE_SYSTEM_CLIENT):"qt.Client",
 	("QWidget",oleacc.ROLE_SYSTEM_LIST):"qt.Container",
 	("Qt5QWindowIcon",oleacc.ROLE_SYSTEM_LIST):"qt.Container",
diff --git a/source/NVDAObjects/IAccessible/msOffice.py b/source/NVDAObjects/IAccessible/msOffice.py
--- a/source/NVDAObjects/IAccessible/msOffice.py
+++ b/source/NVDAObjects/IAccessible/msOffice.py
@@ -1,8 +1,8 @@
-#NVDAObjects/IAccessible/msOffice.py
-#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) 2006-2010 Michael Curran <mick@kulgan.net>, James Teh <jamie@jantrid.net>
+# -*- coding: UTF-8 -*-
+# A part of NonVisual Desktop Access (NVDA)
+# Copyright (C) 2006-2020 NV Access Limited, Manish Agrawal, Łukasz Golonka
+# This file may be used under the terms of the GNU General Public License, version 2 or later.
+# For more details see: https://www.gnu.org/licenses/gpl-2.0.html
 
 import oleacc
 import IAccessibleHandler
@@ -180,3 +180,36 @@ def script_selectGraphic(self, gesture):
 		"kb:leftArrow": "selectGraphic",
 		"kb:rightArrow": "selectGraphic",
 	}
+
+
+class StatusBar (IAccessible):
+
+	def _get_role(self):
+		""" #4257: Status bar in Office applications does not  expose proper role via IAccessible.
+We cannot acces it via UIA because it does not fire focus events when focused for the first time.
+Fortunately accValue contains "status bar" and is not localized.
+"""
+		accValue = self.IAccessibleObject.accValue(self.IAccessibleChildID)
+		if accValue == 'Ribbon Tab':
+			return controlTypes.ROLE_TAB
+		if accValue == 'Status Bar':
+			return controlTypes.ROLE_STATUSBAR
+		return super()._get_role()
+
+	def _get_description(self):
+		return ""
+
+	def _get_isPresentableFocusAncestor(self):
+		accValue = self.IAccessibleObject.accValue(self.IAccessibleChildID)
+		if accValue == "Ribbon":
+			return False
+		return super().isPresentableFocusAncestor
+
+
+class RibbonSection (IAccessible):
+
+	def _get_role(self):
+		accValue = self.IAccessibleObject.accValue(self.IAccessibleChildID)
+		if accValue == "Group":
+			return controlTypes.ROLE_GROUPING
+		return super()._get_role()
diff --git a/source/_UIAHandler.py b/source/_UIAHandler.py
--- a/source/_UIAHandler.py
+++ b/source/_UIAHandler.py
@@ -538,6 +538,24 @@ def _isUIAWindowHelper(self,hwnd):
 		# allow the appModule for the window to also choose if this window is bad
 		if appModule and appModule.isBadUIAWindow(hwnd):
 			return False
+		if windowClass == "NetUIHWND" and appModule:
+			# NetUIHWND is used for various controls in MS Office.
+			# IAccessible should be used for NetUIHWND in versions older than 2016
+			# Fixes: lack of focus reporting (#4207),
+			# Fixes: strange reporting of context menu items(#9252),
+			# fixes: not being able to report ribbon sections when they starts with an edit  field (#7067)
+			# Note that #7067 is not fixed for Office 2016 and never.
+			# Using IAccessible for NetUIHWND controls causes focus changes not to be reported
+			# when the ribbon is collapsed.
+			# Testing shows that these controls emits proper events but they are ignored by NVDA.
+			isOfficeApp = appModule.productName.startswith(("Microsoft Office", "Microsoft Outlook"))
+			isOffice2013OrOlder = int(appModule.productVersion.split(".")[0]) < 16
+			if isOfficeApp and isOffice2013OrOlder:
+				parentHwnd = winUser.getAncestor(hwnd, winUser.GA_PARENT)
+				while parentHwnd:
+					if winUser.getClassName(parentHwnd) in ("Net UI Tool Window", "MsoCommandBar",):
+						return False
+					parentHwnd = winUser.getAncestor(parentHwnd, winUser.GA_PARENT)
 		# Ask the window if it supports UIA natively
 		res=windll.UIAutomationCore.UiaHasServerSideProvider(hwnd)
 		if res:


Test patch: