Enable Interaction with Device Toolbar while Settings dialog is open
This PR enables interactivity with externally visible tools like the
Device Toolbar while DevTools are docked and the Settings dialog
is open. This is accomplished by three behavioral changes:
(1) Settings dialog is no longer dismissed by clicks outside.
Previously, with DevTools docked, it takes two clicks to reach
the Device Toolbar - one to dismiss Settings, and then another
click to interact.
This change fixes an accessibility issue with the Settings dialog
and the NVDA screen reader, causing button interactions to close.
the dialog by injecting click events outside the dialog.
See: https://chromium-review.googlesource.com/c/chromium/src/+/1848114
(2) The Settings dialog now permits clicks to penetrate the GlassPane
that wraps the Settings dialog. This allows interaction with input
fields on the Device Toolbar "on first click".
This change improves UX with (1) and motivated by the idea that
users should not have to dismiss one to interact with the other,
which is the case when DevTools is undocked.
(3) The Settings dialog no longer disables tab indexing for tools
outside the Settings dialog. Previously, it was impossible to
access the Device Toolbar using keyboard navigation while the
Settings dialog was open. This change goes hand in hand with (2).
Technical Notes
The changes for (1) and (2) are natively supported by the Dialog and
Glass Pane as runtime configuration options.
Currently, the UI.Dialog will blindly reassign the tabindex of every
HTML node in the document to -1, preventing them from being accessed
from the keyboard.
A top level SplitWidget divides the DevTools (the "sidebar widget")
from the webpage and Device Toolbar (the "main widget") when DevTools
is docked.
To implement change (3), the UI.Dialog must be aware of the top-level
SplitWidget so it can exclude elements inside the "main widget" from
having tab navigation disabled.
This is accomplished by exposing the SplitWidget containing the
UI.inspectorView, a globally available reference to the "sidebar widget"
containing DevTools. The SplitWidget then provides a reference to its
"main widget".
A new configuration option is added to UI.Dialog to exclude "main widget"
elements. By default, this option is not chosen to preserve functionality
with existing clients of UI.Dialog. To enable (3), the Settings dialog
will choose this option.
To preserve Esc to close Settings, the keydown handler for UI.Dialog
has been moved to the document level. This allows users to quickly return
to DevTools when the Device Toolbar is in focus. It does not conflict
with existing Esc key handlers for tooltips and selection boxes.
Remark: The two tools that use the top level split view are the Device
Toolbar and the Screencast view for remote debugging. The Screencast
view has been modified to support these changes.
Remark: When the Console is docked, tab navigation can get lost "behind"
the Settings dialog. This is a separate bug (present before this change)
where the docked Console elements lack tabindex values.
Bug: 963183
Change-Id: I693375f730a988835948e867ff3a93d2743fe75a
Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/1947173
Reviewed-by: Anubha Mathur <[email protected]>
Reviewed-by: Robert Paveza <[email protected]>
Reviewed-by: Vidal Diazleal <[email protected]>
Commit-Queue: Brian Cui <[email protected]>
diff --git a/front_end/settings/SettingsScreen.js b/front_end/settings/SettingsScreen.js
index d0406cf..1c3230e 100644
--- a/front_end/settings/SettingsScreen.js
+++ b/front_end/settings/SettingsScreen.js
@@ -74,6 +74,9 @@
const dialog = new UI.Dialog();
dialog.contentElement.tabIndex = -1;
dialog.addCloseButton();
+ dialog.setOutsideClickCallback(() => {});
+ dialog.setPointerEventsBehavior(UI.GlassPane.PointerEventsBehavior.PierceGlassPane);
+ dialog.setOutsideTabIndexBehavior(UI.Dialog.OutsideTabIndexBehavior.PreserveMainViewTabIndex);
settingsScreen.show(dialog.contentElement);
dialog.show();
settingsScreen._selectTab(name || 'preferences');