Commit 7ffd10d3 authored by Joel Riley's avatar Joel Riley Committed by Chromium LUCI CQ

Re-land: Move focus rings and highlight layers under accessibility bubbles.

Original patch: http://crrev.com/c/2568547
Revert: http://crrev.com/c/2583106

Fix for issue where focus ring appears below switch access panel. Now clients can specify if they want their focus ring to appear above or below accessibility bubble panels. STS will specify they appear below, though other clients will (by default) specify they appear above all panels. This fixes an issue with the switch access focus ring didn't appear above the switch access panel.

Original description:

Move focus rings and highlight layers under accessibility bubbles.

Will allow Select-to-speak panel UI to appear above focus ring and highlight layers. This also avoids the need to create more window containers.

Bug: 1157261, 1143814
Change-Id: Ibd8dd577ecd4fb5767b628c2eff679a2f6931b9c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2582997Reviewed-by: default avatarDominic Mazzoni <dmazzoni@chromium.org>
Reviewed-by: default avatarXiyuan Xia <xiyuan@chromium.org>
Commit-Queue: Joel Riley <joelriley@google.com>
Cr-Commit-Position: refs/heads/master@{#836222}
parent e91124f4
......@@ -50,7 +50,8 @@ void AccessibilityCursorRingLayer::Set(const gfx::Point& location) {
display::Screen::GetScreen()->GetDisplayMatching(bounds);
aura::Window* root_window = Shell::GetRootWindowForDisplayId(display.id());
::wm::ConvertRectFromScreen(root_window, &bounds);
CreateOrUpdateLayer(root_window, "AccessibilityCursorRing", bounds);
CreateOrUpdateLayer(root_window, "AccessibilityCursorRing", bounds,
/*stack_at_top=*/true);
}
void AccessibilityCursorRingLayer::OnPaintLayer(
......
......@@ -6,6 +6,7 @@
#include "ash/accessibility/accessibility_cursor_ring_layer.h"
#include "ash/public/cpp/accessibility_focus_ring_info.h"
#include "ash/public/cpp/shell_window_ids.h"
#include "ash/shell.h"
#include "ash/test/ash_test_base.h"
#include "testing/gtest/include/gtest/gtest.h"
......@@ -110,7 +111,9 @@ TEST_F(AccessibilityFocusRingControllerTest, FocusRingWorksOnMultipleDisplays) {
controller->GetFocusRingGroupForTesting("catsRCute")
->focus_layers_for_testing();
EXPECT_EQ(1u, layers.size());
EXPECT_EQ(root_windows[0], layers[0]->root_window());
aura::Window* window0_container = Shell::GetContainer(
root_windows[0], kShellWindowId_AccessibilityBubbleContainer);
EXPECT_EQ(window0_container, layers[0]->root_window());
// The focus ring has some padding, so just check the center point is where
// we would expect it.
EXPECT_EQ(layers[0]->layer()->GetTargetBounds().CenterPoint(),
......@@ -127,7 +130,9 @@ TEST_F(AccessibilityFocusRingControllerTest, FocusRingWorksOnMultipleDisplays) {
moved_layers = controller->GetFocusRingGroupForTesting("catsRCute")
->focus_layers_for_testing();
EXPECT_EQ(1u, moved_layers.size());
EXPECT_EQ(root_windows[1], moved_layers[0]->root_window());
aura::Window* window1_container = Shell::GetContainer(
root_windows[1], kShellWindowId_AccessibilityBubbleContainer);
EXPECT_EQ(window1_container, moved_layers[0]->root_window());
EXPECT_EQ(moved_layers[0]->layer()->GetTargetBounds().CenterPoint(),
gfx::Rect(100, 50, 10, 10).CenterPoint());
}
......
......@@ -84,8 +84,9 @@ void AccessibilityFocusRingGroup::UpdateFocusRingsFromInfo(
for (size_t i = 0; i < focus_rings_.size(); ++i) {
focus_layers_[i]->SetAppearance(
focus_ring_info_->type, focus_ring_info_->color,
focus_ring_info_->secondary_color, focus_ring_info_->background_color);
focus_ring_info_->type, focus_ring_info_->stacking_order,
focus_ring_info_->color, focus_ring_info_->secondary_color,
focus_ring_info_->background_color);
}
}
......
......@@ -4,6 +4,7 @@
#include "ash/accessibility/accessibility_focus_ring_layer.h"
#include "ash/public/cpp/shell_window_ids.h"
#include "ash/shell.h"
#include "base/bind.h"
#include "third_party/skia/include/core/SkPaint.h"
......@@ -100,6 +101,8 @@ void AccessibilityFocusRingLayer::Set(const AccessibilityFocusRing& ring) {
display::Display display =
display::Screen::GetScreen()->GetDisplayMatching(bounds);
aura::Window* root_window = Shell::GetRootWindowForDisplayId(display.id());
aura::Window* container = Shell::GetContainer(
root_window, kShellWindowId_AccessibilityBubbleContainer);
if (SkColorGetA(background_color_) > 0) {
bounds = display.bounds();
......@@ -107,16 +110,22 @@ void AccessibilityFocusRingLayer::Set(const AccessibilityFocusRing& ring) {
int inset = kGradientWidth;
bounds.Inset(-inset, -inset, -inset, -inset);
}
::wm::ConvertRectFromScreen(root_window, &bounds);
CreateOrUpdateLayer(root_window, "AccessibilityFocusRing", bounds);
::wm::ConvertRectFromScreen(container, &bounds);
bool stack_at_top =
(stacking_order_ == FocusRingStackingOrder::ABOVE_ACCESSIBILITY_BUBBLES);
CreateOrUpdateLayer(container, "AccessibilityFocusRing", bounds,
stack_at_top);
}
void AccessibilityFocusRingLayer::SetAppearance(FocusRingType type,
SkColor color,
SkColor secondary_color,
SkColor background_color) {
void AccessibilityFocusRingLayer::SetAppearance(
FocusRingType type,
FocusRingStackingOrder stacking_order,
SkColor color,
SkColor secondary_color,
SkColor background_color) {
SetColor(color);
type_ = type;
stacking_order_ = stacking_order;
secondary_color_ = secondary_color;
background_color_ = background_color;
}
......
......@@ -26,6 +26,7 @@ class ASH_EXPORT AccessibilityFocusRingLayer : public FocusRingLayer {
void Set(const AccessibilityFocusRing& ring);
void SetAppearance(FocusRingType type,
FocusRingStackingOrder stacking_order,
SkColor color,
SkColor secondary_color,
SkColor background_alpha);
......@@ -45,6 +46,8 @@ class ASH_EXPORT AccessibilityFocusRingLayer : public FocusRingLayer {
AccessibilityFocusRing ring_;
// The type of focus ring.
FocusRingType type_;
// How the focus ring should be stacked relative to other layers.
FocusRingStackingOrder stacking_order_;
// The secondary color.
SkColor secondary_color_;
// The color of the background. When fully transparent, no background will be
......
......@@ -4,6 +4,7 @@
#include "ash/accessibility/accessibility_highlight_layer.h"
#include "ash/public/cpp/shell_window_ids.h"
#include "ash/shell.h"
#include "third_party/skia/include/core/SkPaint.h"
#include "third_party/skia/include/core/SkPath.h"
......@@ -49,8 +50,11 @@ void AccessibilityHighlightLayer::Set(const std::vector<gfx::Rect>& rects,
display::Display display =
display::Screen::GetScreen()->GetDisplayMatching(bounds);
aura::Window* root_window = Shell::GetRootWindowForDisplayId(display.id());
::wm::ConvertRectFromScreen(root_window, &bounds);
CreateOrUpdateLayer(root_window, "AccessibilityHighlight", bounds);
aura::Window* container = Shell::GetContainer(
root_window, kShellWindowId_AccessibilityPanelContainer);
::wm::ConvertRectFromScreen(container, &bounds);
CreateOrUpdateLayer(container, "AccessibilityHighlight", bounds,
/*stack_at_top=*/false);
}
bool AccessibilityHighlightLayer::CanAnimate() const {
......
......@@ -29,13 +29,15 @@ AccessibilityLayer::~AccessibilityLayer() {
}
void AccessibilityLayer::Set(aura::Window* root_window,
const gfx::Rect& bounds) {
const gfx::Rect& bounds,
bool stack_at_top) {
DCHECK(root_window);
layer_rect_ = bounds;
gfx::Rect layer_bounds = bounds;
int inset = -(GetInset());
layer_bounds.Inset(inset, inset, inset, inset);
CreateOrUpdateLayer(root_window, "AccessibilityLayer", layer_bounds);
CreateOrUpdateLayer(root_window, "AccessibilityLayer", layer_bounds,
stack_at_top);
}
void AccessibilityLayer::SetOpacity(float opacity) {
......@@ -51,7 +53,8 @@ void AccessibilityLayer::SetSubpixelPositionOffset(
void AccessibilityLayer::CreateOrUpdateLayer(aura::Window* root_window,
const char* layer_name,
const gfx::Rect& bounds) {
const gfx::Rect& bounds,
bool stack_at_top) {
if (!layer_ || root_window != root_window_) {
root_window_ = root_window;
ui::Layer* root_layer = root_window->layer();
......@@ -67,7 +70,11 @@ void AccessibilityLayer::CreateOrUpdateLayer(aura::Window* root_window,
// Keep moving it to the top in case new layers have been added
// since we created this layer.
layer_->parent()->StackAtTop(layer_.get());
if (stack_at_top) {
layer_->parent()->StackAtTop(layer_.get());
} else {
layer_->parent()->StackAtBottom(layer_.get());
}
layer_->SetBounds(bounds);
gfx::Rect layer_bounds(0, 0, bounds.width(), bounds.height());
......
......@@ -45,7 +45,9 @@ class AccessibilityLayer : public ui::LayerDelegate,
// Move the accessibility layer to the given bounds in the coordinates of
// the given root window.
void Set(aura::Window* root_window, const gfx::Rect& bounds);
void Set(aura::Window* root_window,
const gfx::Rect& bounds,
bool stack_at_top);
// Set the layer's opacity.
void SetOpacity(float opacity);
......@@ -70,10 +72,11 @@ class AccessibilityLayer : public ui::LayerDelegate,
protected:
// Updates |root_window_| and creates |layer_| if it doesn't exist,
// or if the root window has changed. Moves the layer to the top if
// it wasn't there already.
// |stack_at_top| is true, otherwise moves layer to the bottom.
void CreateOrUpdateLayer(aura::Window* root_window,
const char* layer_name,
const gfx::Rect& bounds);
const gfx::Rect& bounds,
bool stack_at_top);
// The current root window containing the focused object.
aura::Window* root_window_ = nullptr;
......
......@@ -5,6 +5,8 @@
#include "ash/accessibility/focus_ring_controller.h"
#include "ash/accessibility/focus_ring_layer.h"
#include "ash/public/cpp/shell_window_ids.h"
#include "ash/shell.h"
#include "ash/system/tray/actionable_view.h"
#include "ash/system/tray/tray_background_view.h"
#include "ash/wm/window_util.h"
......@@ -83,7 +85,9 @@ void FocusRingController::UpdateFocusRing() {
// Update the focus ring layer.
if (!focus_ring_layer_)
focus_ring_layer_.reset(new FocusRingLayer(this));
focus_ring_layer_->Set(root_window, view_bounds);
aura::Window* container = Shell::GetContainer(
root_window, kShellWindowId_AccessibilityBubbleContainer);
focus_ring_layer_->Set(container, view_bounds, /*stack_at_top=*/true);
}
void FocusRingController::OnDeviceScaleFactorChanged() {
......
......@@ -33,7 +33,8 @@ PointScanLayer::PointScanLayer(AccessibilityLayerDelegate* delegate)
: AccessibilityLayer(delegate) {
aura::Window* root_window =
Shell::GetRootWindowForDisplayId(GetPrimaryDisplay().id());
CreateOrUpdateLayer(root_window, "PointScanning", gfx::Rect());
CreateOrUpdateLayer(root_window, "PointScanning", gfx::Rect(),
/*stack_at_top=*/true);
SetOpacity(1.0);
bounds_ = GetPrimaryDisplay().bounds();
layer()->SetBounds(bounds_);
......
......@@ -13,7 +13,8 @@ bool AccessibilityFocusRingInfo::operator==(
const AccessibilityFocusRingInfo& other) const {
return rects_in_screen == other.rects_in_screen &&
behavior == other.behavior && type == other.type &&
color == other.color && secondary_color == other.secondary_color &&
stacking_order == other.stacking_order && color == other.color &&
secondary_color == other.secondary_color &&
background_color == other.background_color;
}
......
......@@ -20,6 +20,14 @@ enum class ASH_PUBLIC_EXPORT FocusRingBehavior { FADE_OUT, PERSIST };
// The visual style of the focus ring.
enum class ASH_PUBLIC_EXPORT FocusRingType { GLOW, SOLID, DASHED };
// How focus rings are layered.
enum class ASH_PUBLIC_EXPORT FocusRingStackingOrder {
// Above most UI, including accessibility bubble panels.
ABOVE_ACCESSIBILITY_BUBBLES,
// Above most UI, except below accessibility bubble panels.
BELOW_ACCESSIBILITY_BUBBLES
};
// Defines a specific focus ring by specifying:
// - |rects_in_screen| the regions around which to draw the focus ring (in
// screen coordinates).
......@@ -40,6 +48,8 @@ struct ASH_PUBLIC_EXPORT AccessibilityFocusRingInfo {
std::vector<gfx::Rect> rects_in_screen;
FocusRingBehavior behavior = FocusRingBehavior::FADE_OUT;
FocusRingType type = FocusRingType::GLOW;
FocusRingStackingOrder stacking_order =
FocusRingStackingOrder::ABOVE_ACCESSIBILITY_BUBBLES;
SkColor color = SK_ColorTRANSPARENT;
SkColor secondary_color = SK_ColorTRANSPARENT;
SkColor background_color = SK_ColorTRANSPARENT;
......
......@@ -149,6 +149,23 @@ AccessibilityPrivateSetFocusRingsFunction::Run() {
NOTREACHED();
}
if (focus_ring_info.stacking_order) {
switch (focus_ring_info.stacking_order) {
case accessibility_private::
FOCUS_RING_STACKING_ORDER_ABOVEACCESSIBILITYBUBBLES:
focus_ring->stacking_order =
ash::FocusRingStackingOrder::ABOVE_ACCESSIBILITY_BUBBLES;
break;
case accessibility_private::
FOCUS_RING_STACKING_ORDER_BELOWACCESSIBILITYBUBBLES:
focus_ring->stacking_order =
ash::FocusRingStackingOrder::BELOW_ACCESSIBILITY_BUBBLES;
break;
default:
NOTREACHED();
}
}
if (focus_ring_info.background_color &&
!extensions::image_util::ParseHexColorString(
*(focus_ring_info.background_color),
......
......@@ -8,6 +8,8 @@ var RoleType = chrome.automation.RoleType;
const AccessibilityFeature = chrome.accessibilityPrivate.AccessibilityFeature;
const SelectToSpeakPanelAction =
chrome.accessibilityPrivate.SelectToSpeakPanelAction;
const FocusRingStackingOrder =
chrome.accessibilityPrivate.FocusRingStackingOrder;
// This must be the same as in ash/system/accessibility/select_to_speak_tray.cc:
// ash::kSelectToSpeakTrayClassName.
......@@ -763,9 +765,15 @@ class SelectToSpeak {
if (drawBackground && this.prefsManager_.backgroundShadingEnabled()) {
color = DEFAULT_BACKGROUND_SHADING_COLOR;
}
// If we're also showing a navigation panel, ensure the focus ring appears
// below the panel UI.
const stackingOrder = this.shouldShowNavigationControls_() ?
FocusRingStackingOrder.BELOW_ACCESSIBILITY_BUBBLES :
FocusRingStackingOrder.ABOVE_ACCESSIBILITY_BUBBLES;
chrome.accessibilityPrivate.setFocusRings([{
rects,
type: chrome.accessibilityPrivate.FocusType.GLOW,
stackingOrder,
color: this.prefsManager_.focusRingColor(),
backgroundColor: color,
}]);
......
......@@ -158,6 +158,12 @@
"description": "The type of visual appearance for the focus ring.",
"enum": ["glow", "solid", "dashed"]
},
{
"id": "FocusRingStackingOrder",
"type": "string",
"description": "Whether to stack focus rings above or below accessibility bubble panels. Note: focus rings will be stacked above most other UI in either case",
"enum": ["aboveAccessibilityBubbles", "belowAccessibilityBubbles"]
},
{
"id": "FocusRingInfo",
"type": "object",
......@@ -185,6 +191,11 @@
"description": "A RGB hex-value color string (e.g. #803F82E4) that describes the color drawn outside of the focus ring and over the rest of the display.",
"optional": true
},
"stackingOrder": {
"$ref": "FocusRingStackingOrder",
"description": "The FocusType for the ring.",
"optional": true
},
"id": {
"type": "string",
"description": "An identifier for this focus ring, unique within the extension.",
......
......@@ -197,6 +197,14 @@ chrome.accessibilityPrivate.FocusType = {
DASHED: 'dashed',
};
/**
* @enum {string}
*/
chrome.accessibilityPrivate.FocusRingStackingOrder = {
ABOVE_ACCESSIBILITY_BUBBLES: 'aboveAccessibilityBubbles',
BELOW_ACCESSIBILITY_BUBBLES: 'belowAccessibilityBubbles',
};
/**
* @typedef {{
* rects: !Array<!chrome.accessibilityPrivate.ScreenRect>,
......@@ -204,6 +212,8 @@ chrome.accessibilityPrivate.FocusType = {
* color: string,
* secondaryColor: (string|undefined),
* backgroundColor: (string|undefined),
* stackingOrder:
* (!chrome.accessibilityPrivate.FocusRingStackingOrder|undefined),
* id: (string|undefined)
* }}
*/
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment