Skip to content

Commit

Permalink
Port ash's accessibility focus ring to chromecast.
Browse files Browse the repository at this point in the history
  - Copies ash's AccessibilityFocusRing and friends into
    chromecast/graphics/accessibility. See patchset #1 for the pure
    copy operation without modifications.
  - Modify the above to work without ash: explicit configuration of
    the CastWindowManagerAura's root window and window activation
    client (ash has global singletons for these).
  - Add AccessibilityManager class which delegates to the above,
    roughly analogous to the equivalent in chromeos. Configured as a
    browser process singleton in CastBrowserProcess.
  - Call AccessibilityManager from the accessibilityPrivate
    extensionsion API, so that ChromeVox can use it.

Bug: internal b/73383411
Test: manual test
Change-Id: I0019c56e7be84abc2a97b429b3820f8d8f69ffbf
Reviewed-on: https://chromium-review.googlesource.com/1071720
Reviewed-by: Scott Violet <sky@chromium.org>
Reviewed-by: Alex Sakhartchouk <alexst@chromium.org>
Reviewed-by: Albert Chaulk <achaulk@chromium.org>
Commit-Queue: Ryan Daum <rdaum@chromium.org>
Cr-Commit-Position: refs/heads/master@{#563299}
  • Loading branch information
Ryan Daum authored and Commit Bot committed May 31, 2018
1 parent 9c9cfa0 commit b653982
Show file tree
Hide file tree
Showing 32 changed files with 2,419 additions and 21 deletions.
10 changes: 10 additions & 0 deletions chromecast/browser/cast_browser_main_parts.cc
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@
// header, but is exported to allow injecting the overlay-composited
// callback.
#include "chromecast/browser/cast_display_configurator.h"
#include "chromecast/graphics/accessibility/accessibility_manager.h"
#include "chromecast/graphics/cast_screen.h"
#include "components/viz/service/display/overlay_strategy_underlay_cast.h" // nogncheck
#include "ui/display/screen.h"
Expand Down Expand Up @@ -524,9 +525,18 @@ void CastBrowserMainParts::PreMainMessageLoopRun() {
base::Unretained(video_plane_controller_.get())));
#endif

#if defined(USE_AURA)
cast_browser_process_->SetAccessibilityManager(
std::make_unique<AccessibilityManager>());
window_manager_ = CastWindowManager::Create(
CAST_IS_DEBUG_BUILD() ||
GetSwitchValueBoolean(switches::kEnableInput, false),
cast_browser_process_->accessibility_manager());
#else
window_manager_ = CastWindowManager::Create(
CAST_IS_DEBUG_BUILD() ||
GetSwitchValueBoolean(switches::kEnableInput, false));
#endif

cast_browser_process_->SetCastService(
cast_browser_process_->browser_client()->CreateCastService(
Expand Down
7 changes: 7 additions & 0 deletions chromecast/browser/cast_browser_process.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "components/prefs/pref_service.h"

#if defined(USE_AURA)
#include "chromecast/graphics/accessibility/accessibility_manager.h"
#include "chromecast/graphics/cast_screen.h"
#endif // defined(USE_AURA)

Expand Down Expand Up @@ -70,6 +71,12 @@ void CastBrowserProcess::SetCastScreen(
DCHECK(!cast_screen_);
cast_screen_ = std::move(cast_screen);
}

void CastBrowserProcess::SetAccessibilityManager(
std::unique_ptr<AccessibilityManager> accessibility_manager) {
DCHECK(!accessibility_manager_);
accessibility_manager_ = std::move(accessibility_manager);
}
#endif // defined(USE_AURA)

void CastBrowserProcess::SetMetricsServiceClient(
Expand Down
10 changes: 10 additions & 0 deletions chromecast/browser/cast_browser_process.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ class NetLog;
} // namespace net

namespace chromecast {
#if defined(USE_AURA)
class AccessibilityManager;
#endif // defined(USE_AURA)
class CastService;
class CastScreen;
class ConnectivityChecker;
Expand All @@ -43,7 +46,10 @@ class CastBrowserProcess {
void SetBrowserContext(std::unique_ptr<CastBrowserContext> browser_context);
void SetCastContentBrowserClient(CastContentBrowserClient* browser_client);
void SetCastService(std::unique_ptr<CastService> cast_service);

#if defined(USE_AURA)
void SetAccessibilityManager(
std::unique_ptr<AccessibilityManager> accessibility_manager);
void SetCastScreen(std::unique_ptr<CastScreen> cast_screen);
#endif // defined(USE_AURA)
void SetMetricsServiceClient(
Expand All @@ -63,6 +69,9 @@ class CastBrowserProcess {
CastService* cast_service() const { return cast_service_.get(); }
#if defined(USE_AURA)
CastScreen* cast_screen() const { return cast_screen_.get(); }
AccessibilityManager* accessibility_manager() const {
return accessibility_manager_.get();
}
#endif // defined(USE_AURA)
metrics::CastMetricsServiceClient* metrics_service_client() const {
return metrics_service_client_.get();
Expand All @@ -81,6 +90,7 @@ class CastBrowserProcess {
// CastBrowserMainParts.
#if defined(USE_AURA)
std::unique_ptr<CastScreen> cast_screen_;
std::unique_ptr<AccessibilityManager> accessibility_manager_;
#endif // defined(USE_AURA)
std::unique_ptr<PrefService> pref_service_;
scoped_refptr<ConnectivityChecker> connectivity_checker_;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,15 @@

#include "chromecast/browser/extensions/api/accessibility_private/accessibility_extension_api.h"

#include "chromecast/browser/cast_browser_process.h"
#include "chromecast/common/extensions_api/accessibility_private.h"
#include "chromecast/graphics/accessibility/accessibility_manager.h"
#include "content/public/browser/browser_accessibility_state.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/common/service_manager_connection.h"
#include "extensions/common/image_util.h"
#include "services/service_manager/public/cpp/connector.h"
#include "services/service_manager/public/cpp/interface_provider.h"

namespace {

Expand All @@ -31,14 +38,65 @@ AccessibilityPrivateSetNativeAccessibilityEnabledFunction::Run() {

ExtensionFunction::ResponseAction
AccessibilityPrivateSetFocusRingFunction::Run() {
LOG(ERROR) << "AccessibilityPrivateSetFocusRingFunction";
return RespondNow(Error(kErrorNotSupported));
auto* accessibility_manager =
chromecast::shell::CastBrowserProcess::GetInstance()
->accessibility_manager();

std::unique_ptr<accessibility_private::SetFocusRing::Params> params(
accessibility_private::SetFocusRing::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params);

std::vector<gfx::Rect> rects;
for (const accessibility_private::ScreenRect& rect : params->rects) {
rects.push_back(gfx::Rect(rect.left, rect.top, rect.width, rect.height));
}

if (params->color) {
SkColor color;
if (!extensions::image_util::ParseHexColorString(*(params->color), &color))
return RespondNow(Error("Could not parse hex color"));
accessibility_manager->SetFocusRingColor(color);
} else {
accessibility_manager->ResetFocusRingColor();
}

// Move the visible focus ring to cover all of these rects.
accessibility_manager->SetFocusRing(
rects, chromecast::FocusRingBehavior::PERSIST_FOCUS_RING);

// Also update the touch exploration controller so that synthesized
// touch events are anchored within the focused object.
if (!rects.empty()) {
accessibility_manager->SetTouchAccessibilityAnchorPoint(
rects[0].CenterPoint());
}

return RespondNow(NoArguments());
}

ExtensionFunction::ResponseAction
AccessibilityPrivateSetHighlightsFunction::Run() {
LOG(ERROR) << "AccessibilityPrivateSetHighlightsFunction";
return RespondNow(Error(kErrorNotSupported));
auto* accessibility_manager =
chromecast::shell::CastBrowserProcess::GetInstance()
->accessibility_manager();

std::unique_ptr<accessibility_private::SetHighlights::Params> params(
accessibility_private::SetHighlights::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params);

std::vector<gfx::Rect> rects;
for (const accessibility_private::ScreenRect& rect : params->rects) {
rects.push_back(gfx::Rect(rect.left, rect.top, rect.width, rect.height));
}

SkColor color;
if (!extensions::image_util::ParseHexColorString(params->color, &color))
return RespondNow(Error("Could not parse hex color"));

// Set the highlights to cover all of these rects.
accessibility_manager->SetHighlights(rects, color);

return RespondNow(NoArguments());
}

ExtensionFunction::ResponseAction
Expand Down
22 changes: 22 additions & 0 deletions chromecast/graphics/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,25 @@ cast_source_set("graphics") {

if (use_aura) {
sources += [
"accessibility/accessibility_cursor_ring_layer.cc",
"accessibility/accessibility_cursor_ring_layer.h",
"accessibility/accessibility_focus_ring.cc",
"accessibility/accessibility_focus_ring.h",
"accessibility/accessibility_focus_ring_controller.cc",
"accessibility/accessibility_focus_ring_controller.h",
"accessibility/accessibility_focus_ring_layer.cc",
"accessibility/accessibility_focus_ring_layer.h",
"accessibility/accessibility_highlight_layer.cc",
"accessibility/accessibility_highlight_layer.h",
"accessibility/accessibility_layer.cc",
"accessibility/accessibility_layer.h",
"accessibility/accessibility_manager.cc",
"accessibility/accessibility_manager.h",
"accessibility/accessibility_observer.h",
"accessibility/focus_ring_controller.cc",
"accessibility/focus_ring_controller.h",
"accessibility/focus_ring_layer.cc",
"accessibility/focus_ring_layer.h",
"cast_focus_client_aura.cc",
"cast_focus_client_aura.h",
"cast_system_gesture_event_handler.cc",
Expand Down Expand Up @@ -51,7 +70,9 @@ cast_source_set("graphics") {
":libcast_graphics_1.0",
"//chromecast/base",
"//chromecast/public",
"//skia",
"//ui/aura",
"//ui/compositor",
"//ui/display",
"//ui/gfx/geometry",
]
Expand Down Expand Up @@ -79,6 +100,7 @@ cast_shared_library("libcast_graphics_1.0") {
if (use_aura && !is_cast_audio_only) {
test("cast_graphics_unittests") {
sources = [
"accessibility/accessibility_focus_ring_controller_unittest.cc",
"cast_focus_client_aura_test.cc",
"cast_system_gesture_event_handler_test.cc",
"cast_views_test.cc",
Expand Down
2 changes: 2 additions & 0 deletions chromecast/graphics/DEPS
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ include_rules = [
"+ui/aura",
"+ui/base",
"+ui/base/ime",
"+ui/compositor",
"+ui/display",
"+ui/events",
"+ui/events/test",
Expand All @@ -10,6 +11,7 @@ include_rules = [
"+ui/views",
"+ui/wm/core",
"+ui/wm/public",
"+third_party/skia",
]

specific_include_rules = {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Copied with modifications from ash/accessibility, refactored for use in
// chromecast.

#include "chromecast/graphics/accessibility/accessibility_cursor_ring_layer.h"

#include "third_party/skia/include/core/SkPaint.h"
#include "third_party/skia/include/core/SkPath.h"
#include "ui/aura/window.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/paint_recorder.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "ui/gfx/canvas.h"
#include "ui/wm/core/coordinate_conversion.h"

namespace chromecast {

namespace {

// The number of pixels in the color gradient that fades to transparent.
const int kGradientWidth = 8;

// The radius of the ring in pixels.
const int kCursorRingRadius = 24;

// Extra margin to add to the layer in pixels.
const int kLayerMargin = 8;

} // namespace

AccessibilityCursorRingLayer::AccessibilityCursorRingLayer(
aura::Window* root_window,
AccessibilityLayerDelegate* delegate,
int red,
int green,
int blue)
: FocusRingLayer(root_window, delegate),
red_(red),
green_(green),
blue_(blue) {}

AccessibilityCursorRingLayer::~AccessibilityCursorRingLayer() = default;

void AccessibilityCursorRingLayer::Set(const gfx::Point& location) {
location_ = location;

gfx::Rect bounds = gfx::Rect(location.x(), location.y(), 0, 0);
int inset = kGradientWidth + kCursorRingRadius + kLayerMargin;
bounds.Inset(-inset, -inset, -inset, -inset);

DCHECK(root_window());
display::Display display =
display::Screen::GetScreen()->GetDisplayMatching(bounds);
::wm::ConvertRectFromScreen(root_window(), &bounds);
CreateOrUpdateLayer(root_window(), "AccessibilityCursorRing", bounds);
}

void AccessibilityCursorRingLayer::OnPaintLayer(
const ui::PaintContext& context) {
ui::PaintRecorder recorder(context, layer()->size());

cc::PaintFlags flags;
flags.setAntiAlias(true);
flags.setStyle(cc::PaintFlags::kStroke_Style);
flags.setStrokeWidth(2);

gfx::Rect r = layer()->bounds();
r.Offset(-r.OffsetFromOrigin());
r.Inset(kLayerMargin, kLayerMargin, kLayerMargin, kLayerMargin);
const int w = kGradientWidth;
for (int i = 0; i < w; ++i) {
flags.setColor(SkColorSetARGB(255 * i * i / (w * w), red_, green_, blue_));
SkPath path;
path.addOval(SkRect::MakeXYWH(r.x(), r.y(), r.width(), r.height()));
r.Inset(1, 1, 1, 1);
recorder.canvas()->DrawPath(path, flags);
}
}

} // namespace chromecast
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Copied with modifications from ash/accessibility, refactored for use in
// chromecast.

#ifndef CHROMECAST_GRAPHICS_ACCESSIBILITY_ACCESSIBILITY_CURSOR_RING_LAYER_H_
#define CHROMECAST_GRAPHICS_ACCESSIBILITY_ACCESSIBILITY_CURSOR_RING_LAYER_H_

#include "chromecast/graphics/accessibility/accessibility_focus_ring.h"
#include "chromecast/graphics/accessibility/focus_ring_layer.h"

namespace chromecast {

// A subclass of FocusRingLayer that highlights the mouse cursor while it's
// moving, to make it easier to find visually.
class AccessibilityCursorRingLayer : public FocusRingLayer {
public:
AccessibilityCursorRingLayer(aura::Window* root_window,
AccessibilityLayerDelegate* delegate,
int red,
int green,
int blue);
~AccessibilityCursorRingLayer() override;

// Create the layer and update its bounds and position in the hierarchy.
void Set(const gfx::Point& location);

private:
// ui::LayerDelegate overrides:
void OnPaintLayer(const ui::PaintContext& context) override;

// The current location.
gfx::Point location_;

int red_;
int green_;
int blue_;

DISALLOW_COPY_AND_ASSIGN(AccessibilityCursorRingLayer);
};

} // namespace chromecast

#endif // CHROMECAST_GRAPHICS_ACCESSIBILITY_ACCESSIBILITY_CURSOR_RING_LAYER_H_

0 comments on commit b653982

Please sign in to comment.