From 128f6836a7668f52f34c32c0c12ab43c1982c90a Mon Sep 17 00:00:00 2001 From: Danstiv <50794055+Danstiv@users.noreply.github.com> Date: Fri, 1 Sep 2023 10:01:56 +0700 Subject: [PATCH] Implement tab navigation (#15332) Link to issue number: #15046 Summary of the issue: The lack of the ability to quickly switch to tabs complicates navigation Description of user facing changes Users will be able to switch between tabs in web documents, by assigning the appropriate gesture. Description of development approach Added another elif into _searchableAttribsForNodeType method in iaccessible, UIA and mshtml classes. Added quick nav for tab navigation. --- source/UIAHandler/browseMode.py | 5 +++++ source/browseMode.py | 11 +++++++++++ source/virtualBuffers/MSHTML.py | 6 ++++++ source/virtualBuffers/gecko_ia2.py | 4 ++++ user_docs/en/changes.t2t | 1 + user_docs/en/userGuide.t2t | 20 ++++++++++++++++++++ 6 files changed, 47 insertions(+) diff --git a/source/UIAHandler/browseMode.py b/source/UIAHandler/browseMode.py index 46234cbd04d..63fcfaacc59 100644 --- a/source/UIAHandler/browseMode.py +++ b/source/UIAHandler/browseMode.py @@ -486,6 +486,11 @@ def _iterNodesByType(self,nodeType,direction="next",pos=None): ) ]) return UIAControlQuicknavIterator(nodeType, self, pos, condition, direction) + elif nodeType == "tab": + condition = UIAHandler.handler.clientObject.createPropertyCondition( + UIAHandler.UIA_ControlTypePropertyId, UIAHandler.UIA_TabItemControlTypeId + ) + return UIAControlQuicknavIterator(nodeType, self, pos, condition, direction) elif nodeType=="nonTextContainer": condition=createUIAMultiPropertyCondition({UIAHandler.UIA_ControlTypePropertyId:UIAHandler.UIA_ListControlTypeId,UIAHandler.UIA_IsKeyboardFocusablePropertyId:True},{UIAHandler.UIA_ControlTypePropertyId:UIAHandler.UIA_ComboBoxControlTypeId}) return UIAControlQuicknavIterator(nodeType,self,pos,condition,direction) diff --git a/source/browseMode.py b/source/browseMode.py index 99632e79b51..d613c820854 100644 --- a/source/browseMode.py +++ b/source/browseMode.py @@ -920,6 +920,17 @@ def _get_disableAutoPassThrough(self): # Translators: Message presented when the browse mode element is not found. prevError=_("no previous grouping") ) +qn( + "tab", key=None, + # Translators: Input help message for a quick navigation command in browse mode. + nextDoc=_("moves to the next tab"), + # Translators: Message presented when the browse mode element is not found. + nextError=_("no next tab"), + # Translators: Input help message for a quick navigation command in browse mode. + prevDoc=_("moves to the previous tab"), + # Translators: Message presented when the browse mode element is not found. + prevError=_("no previous tab") +) del qn diff --git a/source/virtualBuffers/MSHTML.py b/source/virtualBuffers/MSHTML.py index 137687a5384..062c6ac70f5 100644 --- a/source/virtualBuffers/MSHTML.py +++ b/source/virtualBuffers/MSHTML.py @@ -401,6 +401,12 @@ def _searchableAttribsForNodeType(self,nodeType): "name": [VBufStorage_findMatch_notEmpty] }, ] + elif nodeType == "tab": + attrs = [ + { + "IAccessible::role": [oleacc.ROLE_SYSTEM_PAGETAB], + }, + ] elif nodeType == "embeddedObject": attrs = [ {"IHTMLDOMNode::nodeName": ["OBJECT", "EMBED", "APPLET", "AUDIO", "VIDEO", "FIGURE"]}, diff --git a/source/virtualBuffers/gecko_ia2.py b/source/virtualBuffers/gecko_ia2.py index a4893ee2536..1fc361cffcf 100755 --- a/source/virtualBuffers/gecko_ia2.py +++ b/source/virtualBuffers/gecko_ia2.py @@ -543,6 +543,10 @@ def _searchableAttribsForNodeType(self,nodeType): }, {"IAccessible::role":[oleacc.ROLE_SYSTEM_APPLICATION,oleacc.ROLE_SYSTEM_DIALOG]}, ] + elif nodeType == "tab": + attrs = [ + {"IAccessible::role": [oleacc.ROLE_SYSTEM_PAGETAB]} + ] else: return None return attrs diff --git a/user_docs/en/changes.t2t b/user_docs/en/changes.t2t index 2676f753866..026ffe136e9 100644 --- a/user_docs/en/changes.t2t +++ b/user_docs/en/changes.t2t @@ -21,6 +21,7 @@ What's New in NVDA - - When using automatic detection of braille displays, it is now possible to opt-out drivers from detection from the braille display selection dialog. (#15196) - A new option in Document Formatting settings, "Ignore blank lines for line indentation reporting". (#13394) +- Added an unassigned gesture to navigate by tab groupings in browse mode. (#15046) - == Changes == diff --git a/user_docs/en/userGuide.t2t b/user_docs/en/userGuide.t2t index 3ff435a5885..25495d3c52a 100644 --- a/user_docs/en/userGuide.t2t +++ b/user_docs/en/userGuide.t2t @@ -814,6 +814,26 @@ If you want to use these while still being able to use your cursor keys to read To toggle single letter navigation on and off for the current document, press NVDA+shift+space. %kc:endInclude ++++ Other navigation commands +++[OtherNavigationCommands] + +In addition to the quick navigation commands listed above, NVDA has commands that have no default keys assigned. +To use these commands, you first need to assign gestures to them using the [Input Gestures dialog #InputGestures]. +Here is a list of available commands +- Article +- Grouping +- Tab +- +Keep in mind that there are two commands for each type of element, for moving forward in the document and backward in the document, and you must assign gestures to both commands in order to be able to quickly navigate in both directions. + +For example, if you want to use the ``y`` / ``shift+y`` keys to quickly navigate through tabs, you would do the following + ++ Open input gestures dialog from browse mode. ++ Find "moves to the next tab" item in the Browse mode section. ++ Assign ``y`` key for found gesture. ++ Find "moves to the previous tab" item. ++ Assign ``shift+y`` for found gesture. ++ + ++ The Elements List ++[ElementsList] The elements list provides access to a list of various types of elements in the document as appropriate for the application. For example, in web browsers, the elements list can list links, headings, form fields, buttons or landmarks.