Commit cac4d247 authored by dmazzoni's avatar dmazzoni Committed by Commit bot

Animate the accessibility focus ring and fix some minor visual issues.

The look of the focus ring now closely matches the one drawn by the
ChromeVox content script using CSS, and it smoothly animates from one
location to the next.

BUG=314889

Review URL: https://codereview.chromium.org/602813003

Cr-Commit-Position: refs/heads/master@{#296765}
parent 85758c75
...@@ -4,20 +4,40 @@ ...@@ -4,20 +4,40 @@
#include "chrome/browser/chromeos/ui/accessibility_focus_ring.h" #include "chrome/browser/chromeos/ui/accessibility_focus_ring.h"
#include "base/logging.h"
namespace chromeos { namespace chromeos {
// static // static
AccessibilityFocusRing AccessibilityFocusRing::CreateWithRect( AccessibilityFocusRing AccessibilityFocusRing::CreateWithRect(
const gfx::Rect& bounds, int margin) { const gfx::Rect& bounds, int margin) {
// Compute the height of the top and bottom cap.
int cap_height = std::min(bounds.height() / 2, margin * 2);
gfx::Rect top(bounds.x(), bounds.y(), gfx::Rect top(bounds.x(), bounds.y(),
bounds.width(), bounds.height() / 4); bounds.width(), cap_height);
gfx::Rect bottom(bounds.x(), bounds.bottom() - cap_height,
bounds.width(), cap_height);
gfx::Rect body(bounds.x(), top.bottom(), gfx::Rect body(bounds.x(), top.bottom(),
bounds.width(), bounds.height() / 2); bounds.width(), bottom.y() - top.bottom());
gfx::Rect bottom(bounds.x(), body.bottom(),
bounds.width(), bounds.bottom() - body.bottom());
return CreateWithParagraphShape(top, body, bottom, margin); return CreateWithParagraphShape(top, body, bottom, margin);
} }
// static
AccessibilityFocusRing AccessibilityFocusRing::Interpolate(
const AccessibilityFocusRing& r1,
const AccessibilityFocusRing& r2,
double fraction) {
AccessibilityFocusRing dst;
for (int i = 0; i < 36; ++i) {
dst.points[i] = gfx::Point(
r1.points[i].x() * (1 - fraction) + r2.points[i].x() * fraction,
r1.points[i].y() * (1 - fraction) + r2.points[i].y() * fraction);
}
return dst;
}
// static // static
AccessibilityFocusRing AccessibilityFocusRing::CreateWithParagraphShape( AccessibilityFocusRing AccessibilityFocusRing::CreateWithParagraphShape(
const gfx::Rect& orig_top_line, const gfx::Rect& orig_top_line,
...@@ -28,6 +48,9 @@ AccessibilityFocusRing AccessibilityFocusRing::CreateWithParagraphShape( ...@@ -28,6 +48,9 @@ AccessibilityFocusRing AccessibilityFocusRing::CreateWithParagraphShape(
gfx::Rect middle = orig_body; gfx::Rect middle = orig_body;
gfx::Rect bottom = orig_bottom_line; gfx::Rect bottom = orig_bottom_line;
int min_height = std::min(top.height(), bottom.height());
margin = std::min(margin, min_height / 2);
if (top.x() <= middle.x() + 2 * margin) { if (top.x() <= middle.x() + 2 * margin) {
top.set_width(top.width() + top.x() - middle.x()); top.set_width(top.width() + top.x() - middle.x());
top.set_x(middle.x()); top.set_x(middle.x());
...@@ -108,7 +131,7 @@ AccessibilityFocusRing AccessibilityFocusRing::CreateWithParagraphShape( ...@@ -108,7 +131,7 @@ AccessibilityFocusRing AccessibilityFocusRing::CreateWithParagraphShape(
gfx::Rect AccessibilityFocusRing::GetBounds() const { gfx::Rect AccessibilityFocusRing::GetBounds() const {
gfx::Point top_left = points[0]; gfx::Point top_left = points[0];
gfx::Point bottom_right = points[0]; gfx::Point bottom_right = points[0];
for (size_t i = 1; i < 36; i++) { for (size_t i = 1; i < 36; ++i) {
top_left.SetToMin(points[i]); top_left.SetToMin(points[i]);
bottom_right.SetToMax(points[i]); bottom_right.SetToMax(points[i]);
} }
......
...@@ -72,6 +72,13 @@ struct AccessibilityFocusRing { ...@@ -72,6 +72,13 @@ struct AccessibilityFocusRing {
static AccessibilityFocusRing CreateWithRect( static AccessibilityFocusRing CreateWithRect(
const gfx::Rect& bounds, int margin); const gfx::Rect& bounds, int margin);
// Returns a ring where 0.0 returns r1, 1.0 returns r2, and any number
// in-between interpolates linearly between them.
static AccessibilityFocusRing Interpolate(
const AccessibilityFocusRing& r1,
const AccessibilityFocusRing& r2,
double fraction);
// Construct an AccessibilityFocusRing that outlines a paragraph-shaped // Construct an AccessibilityFocusRing that outlines a paragraph-shaped
// object. // object.
static AccessibilityFocusRing CreateWithParagraphShape( static AccessibilityFocusRing CreateWithParagraphShape(
...@@ -80,8 +87,9 @@ struct AccessibilityFocusRing { ...@@ -80,8 +87,9 @@ struct AccessibilityFocusRing {
const gfx::Rect& bottom_line, const gfx::Rect& bottom_line,
int margin); int margin);
gfx::Point points[36];
gfx::Rect GetBounds() const; gfx::Rect GetBounds() const;
gfx::Point points[36];
}; };
} // namespace chromeos } // namespace chromeos
......
...@@ -4,7 +4,11 @@ ...@@ -4,7 +4,11 @@
#include "chrome/browser/chromeos/ui/accessibility_focus_ring_controller.h" #include "chrome/browser/chromeos/ui/accessibility_focus_ring_controller.h"
#include "ash/display/display_controller.h"
#include "ash/shell.h"
#include "base/logging.h"
#include "chrome/browser/chromeos/ui/focus_ring_layer.h" #include "chrome/browser/chromeos/ui/focus_ring_layer.h"
#include "ui/gfx/screen.h"
namespace chromeos { namespace chromeos {
...@@ -13,7 +17,10 @@ namespace { ...@@ -13,7 +17,10 @@ namespace {
// The number of pixels the focus ring is outset from the object it outlines, // The number of pixels the focus ring is outset from the object it outlines,
// which also determines the border radius of the rounded corners. // which also determines the border radius of the rounded corners.
// TODO(dmazzoni): take display resolution into account. // TODO(dmazzoni): take display resolution into account.
const int kAccessibilityFocusRingMargin = 16; const int kAccessibilityFocusRingMargin = 7;
// Time to transition between one location and the next.
const int kTransitionTimeMilliseconds = 300;
// A Region is an unordered collection of Rects that maintains its // A Region is an unordered collection of Rects that maintains its
// bounding box. Used in the middle of an algorithm that groups // bounding box. Used in the middle of an algorithm that groups
...@@ -35,7 +42,8 @@ AccessibilityFocusRingController* ...@@ -35,7 +42,8 @@ AccessibilityFocusRingController*
return Singleton<AccessibilityFocusRingController>::get(); return Singleton<AccessibilityFocusRingController>::get();
} }
AccessibilityFocusRingController::AccessibilityFocusRingController() { AccessibilityFocusRingController::AccessibilityFocusRingController()
: compositor_(NULL) {
} }
AccessibilityFocusRingController::~AccessibilityFocusRingController() { AccessibilityFocusRingController::~AccessibilityFocusRingController() {
...@@ -48,22 +56,57 @@ void AccessibilityFocusRingController::SetFocusRing( ...@@ -48,22 +56,57 @@ void AccessibilityFocusRingController::SetFocusRing(
} }
void AccessibilityFocusRingController::Update() { void AccessibilityFocusRingController::Update() {
previous_rings_.swap(rings_);
rings_.clear(); rings_.clear();
RectsToRings(rects_, &rings_); RectsToRings(rects_, &rings_);
layers_.resize(rings_.size());
for (size_t i = 0; i < rings_.size(); ++i) {
if (!layers_[i])
layers_[i].reset(new AccessibilityFocusRingLayer(this));
if (i > 0) {
// Focus rings other than the first one don't animate.
layers_[i]->Set(rings_[i]);
continue;
}
if (!main_focus_ring_layer_) gfx::Rect bounds = rings_[0].GetBounds();
main_focus_ring_layer_.reset(new AccessibilityFocusRingLayer(this)); gfx::Display display =
gfx::Screen::GetNativeScreen()->GetDisplayMatching(bounds);
aura::Window* root_window = ash::Shell::GetInstance()->display_controller()
->GetRootWindowForDisplayId(display.id());
ui::Compositor* compositor = root_window->layer()->GetCompositor();
if (!compositor || root_window != layers_[0]->root_window()) {
layers_[0]->Set(rings_[0]);
if (compositor_ && compositor_->HasAnimationObserver(this)) {
compositor_->RemoveAnimationObserver(this);
compositor_ = NULL;
}
continue;
}
if (!rings_.empty()) focus_change_time_ = base::TimeTicks::Now();
main_focus_ring_layer_->Set(rings_[0]); if (!compositor->HasAnimationObserver(this)) {
compositor_ = compositor;
compositor_->AddAnimationObserver(this);
}
}
} }
void AccessibilityFocusRingController::RectsToRings( void AccessibilityFocusRingController::RectsToRings(
const std::vector<gfx::Rect>& rects, const std::vector<gfx::Rect>& src_rects,
std::vector<AccessibilityFocusRing>* rings) const { std::vector<AccessibilityFocusRing>* rings) const {
if (rects.empty()) if (src_rects.empty())
return; return;
// Give all of the rects a margin.
std::vector<gfx::Rect> rects;
rects.resize(src_rects.size());
for (size_t i = 0; i < src_rects.size(); ++i) {
rects[i] = src_rects[i];
rects[i].Inset(-GetMargin(), -GetMargin());
}
// Split the rects into contiguous regions. // Split the rects into contiguous regions.
std::vector<Region> regions; std::vector<Region> regions;
regions.push_back(Region(rects[0])); regions.push_back(Region(rects[0]));
...@@ -244,4 +287,33 @@ void AccessibilityFocusRingController::OnDeviceScaleFactorChanged() { ...@@ -244,4 +287,33 @@ void AccessibilityFocusRingController::OnDeviceScaleFactorChanged() {
Update(); Update();
} }
void AccessibilityFocusRingController::OnAnimationStep(
base::TimeTicks timestamp) {
if (rings_.empty())
return;
CHECK(compositor_);
CHECK(!rings_.empty());
CHECK(!layers_.empty());
CHECK(layers_[0]);
base::TimeDelta delta = timestamp - focus_change_time_;
base::TimeDelta transition_time =
base::TimeDelta::FromMilliseconds(kTransitionTimeMilliseconds);
if (delta >= transition_time) {
layers_[0]->Set(rings_[0]);
compositor_->RemoveAnimationObserver(this);
compositor_ = NULL;
return;
}
double fraction = delta.InSecondsF() / transition_time.InSecondsF();
// Ease-in effect.
fraction = pow(fraction, 0.3);
layers_[0]->Set(AccessibilityFocusRing::Interpolate(
previous_rings_[0], rings_[0], fraction));
}
} // namespace chromeos } // namespace chromeos
...@@ -8,14 +8,22 @@ ...@@ -8,14 +8,22 @@
#include "base/basictypes.h" #include "base/basictypes.h"
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "base/memory/singleton.h" #include "base/memory/singleton.h"
#include "base/time/time.h"
#include "chrome/browser/chromeos/ui/accessibility_focus_ring_layer.h" #include "chrome/browser/chromeos/ui/accessibility_focus_ring_layer.h"
#include "ui/compositor/compositor_animation_observer.h"
#include "ui/gfx/rect.h" #include "ui/gfx/rect.h"
namespace ui {
class Compositor;
}
namespace chromeos { namespace chromeos {
// AccessibilityFocusRingController manages a custom focus ring (or multiple // AccessibilityFocusRingController manages a custom focus ring (or multiple
// rings) for accessibility. // rings) for accessibility.
class AccessibilityFocusRingController : public FocusRingLayerDelegate { class AccessibilityFocusRingController
: public FocusRingLayerDelegate,
public ui::CompositorAnimationObserver {
public: public:
// Get the single instance of this class. // Get the single instance of this class.
static AccessibilityFocusRingController* GetInstance(); static AccessibilityFocusRingController* GetInstance();
...@@ -42,6 +50,9 @@ class AccessibilityFocusRingController : public FocusRingLayerDelegate { ...@@ -42,6 +50,9 @@ class AccessibilityFocusRingController : public FocusRingLayerDelegate {
// FocusRingLayerDelegate. // FocusRingLayerDelegate.
virtual void OnDeviceScaleFactorChanged() OVERRIDE; virtual void OnDeviceScaleFactorChanged() OVERRIDE;
// CompositorAnimationObserver.
virtual void OnAnimationStep(base::TimeTicks timestamp) OVERRIDE;
void Update(); void Update();
AccessibilityFocusRing RingFromSortedRects( AccessibilityFocusRing RingFromSortedRects(
...@@ -54,9 +65,11 @@ class AccessibilityFocusRingController : public FocusRingLayerDelegate { ...@@ -54,9 +65,11 @@ class AccessibilityFocusRingController : public FocusRingLayerDelegate {
bool Intersects(const gfx::Rect& r1, const gfx::Rect& r2) const; bool Intersects(const gfx::Rect& r1, const gfx::Rect& r2) const;
std::vector<gfx::Rect> rects_; std::vector<gfx::Rect> rects_;
std::vector<AccessibilityFocusRing> previous_rings_;
std::vector<AccessibilityFocusRing> rings_; std::vector<AccessibilityFocusRing> rings_;
scoped_ptr<AccessibilityFocusRingLayer> main_focus_ring_layer_; std::vector<scoped_ptr<AccessibilityFocusRingLayer> > layers_;
std::vector<scoped_ptr<AccessibilityFocusRingLayer> > extra_layers_; base::TimeTicks focus_change_time_;
ui::Compositor* compositor_;
friend struct DefaultSingletonTraits<AccessibilityFocusRingController>; friend struct DefaultSingletonTraits<AccessibilityFocusRingController>;
......
...@@ -11,7 +11,10 @@ namespace chromeos { ...@@ -11,7 +11,10 @@ namespace chromeos {
class TestableAccessibilityFocusRingController class TestableAccessibilityFocusRingController
: public AccessibilityFocusRingController { : public AccessibilityFocusRingController {
public: public:
TestableAccessibilityFocusRingController() {} TestableAccessibilityFocusRingController() {
// By default use an easy round number for testing.
margin_ = 10;
}
virtual ~TestableAccessibilityFocusRingController() {} virtual ~TestableAccessibilityFocusRingController() {}
void RectsToRings(const std::vector<gfx::Rect>& rects, void RectsToRings(const std::vector<gfx::Rect>& rects,
...@@ -19,10 +22,12 @@ class TestableAccessibilityFocusRingController ...@@ -19,10 +22,12 @@ class TestableAccessibilityFocusRingController
AccessibilityFocusRingController::RectsToRings(rects, rings); AccessibilityFocusRingController::RectsToRings(rects, rings);
} }
// Return an easy round number for testing.
virtual int GetMargin() const OVERRIDE { virtual int GetMargin() const OVERRIDE {
return 10; return margin_;
} }
private:
int margin_;
}; };
class AccessibilityFocusRingControllerTest : public testing::Test { class AccessibilityFocusRingControllerTest : public testing::Test {
...@@ -31,6 +36,11 @@ class AccessibilityFocusRingControllerTest : public testing::Test { ...@@ -31,6 +36,11 @@ class AccessibilityFocusRingControllerTest : public testing::Test {
virtual ~AccessibilityFocusRingControllerTest() {} virtual ~AccessibilityFocusRingControllerTest() {}
protected: protected:
gfx::Rect AddMargin(gfx::Rect r) {
r.Inset(-controller_.GetMargin(), -controller_.GetMargin());
return r;
}
TestableAccessibilityFocusRingController controller_; TestableAccessibilityFocusRingController controller_;
}; };
...@@ -42,7 +52,7 @@ TEST_F(AccessibilityFocusRingControllerTest, RectsToRingsSimpleBoundsCheck) { ...@@ -42,7 +52,7 @@ TEST_F(AccessibilityFocusRingControllerTest, RectsToRingsSimpleBoundsCheck) {
std::vector<AccessibilityFocusRing> rings; std::vector<AccessibilityFocusRing> rings;
controller_.RectsToRings(rects, &rings); controller_.RectsToRings(rects, &rings);
ASSERT_EQ(1U, rings.size()); ASSERT_EQ(1U, rings.size());
ASSERT_EQ(rects[0], rings[0].GetBounds()); ASSERT_EQ(AddMargin(rects[0]), rings[0].GetBounds());
} }
TEST_F(AccessibilityFocusRingControllerTest, RectsToRingsVerticalStack) { TEST_F(AccessibilityFocusRingControllerTest, RectsToRingsVerticalStack) {
...@@ -54,7 +64,7 @@ TEST_F(AccessibilityFocusRingControllerTest, RectsToRingsVerticalStack) { ...@@ -54,7 +64,7 @@ TEST_F(AccessibilityFocusRingControllerTest, RectsToRingsVerticalStack) {
std::vector<AccessibilityFocusRing> rings; std::vector<AccessibilityFocusRing> rings;
controller_.RectsToRings(rects, &rings); controller_.RectsToRings(rects, &rings);
ASSERT_EQ(1U, rings.size()); ASSERT_EQ(1U, rings.size());
ASSERT_EQ(gfx::Rect(10, 10, 60, 60), rings[0].GetBounds()); ASSERT_EQ(AddMargin(gfx::Rect(10, 10, 60, 60)), rings[0].GetBounds());
} }
TEST_F(AccessibilityFocusRingControllerTest, RectsToRingsHorizontalStack) { TEST_F(AccessibilityFocusRingControllerTest, RectsToRingsHorizontalStack) {
...@@ -66,58 +76,58 @@ TEST_F(AccessibilityFocusRingControllerTest, RectsToRingsHorizontalStack) { ...@@ -66,58 +76,58 @@ TEST_F(AccessibilityFocusRingControllerTest, RectsToRingsHorizontalStack) {
std::vector<AccessibilityFocusRing> rings; std::vector<AccessibilityFocusRing> rings;
controller_.RectsToRings(rects, &rings); controller_.RectsToRings(rects, &rings);
ASSERT_EQ(1U, rings.size()); ASSERT_EQ(1U, rings.size());
ASSERT_EQ(gfx::Rect(10, 10, 120, 30), rings[0].GetBounds()); ASSERT_EQ(AddMargin(gfx::Rect(10, 10, 120, 30)), rings[0].GetBounds());
} }
TEST_F(AccessibilityFocusRingControllerTest, RectsToRingsParagraphShape) { TEST_F(AccessibilityFocusRingControllerTest, RectsToRingsParagraphShape) {
// Given a simple paragraph shape, make sure we get something that // Given a simple paragraph shape, make sure we get something that
// outlines it correctly. // outlines it correctly.
std::vector<gfx::Rect> rects; std::vector<gfx::Rect> rects;
rects.push_back(gfx::Rect(0, 0, 200, 100)); rects.push_back(gfx::Rect(10, 10, 180, 80));
rects.push_back(gfx::Rect(0, 100, 600, 300)); rects.push_back(gfx::Rect(10, 110, 580, 280));
rects.push_back(gfx::Rect(400, 400, 200, 100)); rects.push_back(gfx::Rect(410, 410, 180, 80));
std::vector<AccessibilityFocusRing> rings; std::vector<AccessibilityFocusRing> rings;
controller_.RectsToRings(rects, &rings); controller_.RectsToRings(rects, &rings);
ASSERT_EQ(1U, rings.size()); ASSERT_EQ(1U, rings.size());
ASSERT_EQ(gfx::Rect(0, 0, 600, 500), rings[0].GetBounds()); EXPECT_EQ(gfx::Rect(0, 0, 600, 500), rings[0].GetBounds());
const gfx::Point* points = rings[0].points; const gfx::Point* points = rings[0].points;
ASSERT_EQ(gfx::Point(0, 90), points[0]); EXPECT_EQ(gfx::Point(0, 90), points[0]);
ASSERT_EQ(gfx::Point(0, 10), points[1]); EXPECT_EQ(gfx::Point(0, 10), points[1]);
ASSERT_EQ(gfx::Point(0, 0), points[2]); EXPECT_EQ(gfx::Point(0, 0), points[2]);
ASSERT_EQ(gfx::Point(10, 0), points[3]); EXPECT_EQ(gfx::Point(10, 0), points[3]);
ASSERT_EQ(gfx::Point(190, 0), points[4]); EXPECT_EQ(gfx::Point(190, 0), points[4]);
ASSERT_EQ(gfx::Point(200, 0), points[5]); EXPECT_EQ(gfx::Point(200, 0), points[5]);
ASSERT_EQ(gfx::Point(200, 10), points[6]); EXPECT_EQ(gfx::Point(200, 10), points[6]);
ASSERT_EQ(gfx::Point(200, 90), points[7]); EXPECT_EQ(gfx::Point(200, 90), points[7]);
ASSERT_EQ(gfx::Point(200, 100), points[8]); EXPECT_EQ(gfx::Point(200, 100), points[8]);
ASSERT_EQ(gfx::Point(210, 100), points[9]); EXPECT_EQ(gfx::Point(210, 100), points[9]);
ASSERT_EQ(gfx::Point(590, 100), points[10]); EXPECT_EQ(gfx::Point(590, 100), points[10]);
ASSERT_EQ(gfx::Point(600, 100), points[11]); EXPECT_EQ(gfx::Point(600, 100), points[11]);
ASSERT_EQ(gfx::Point(600, 110), points[12]); EXPECT_EQ(gfx::Point(600, 110), points[12]);
ASSERT_EQ(gfx::Point(600, 390), points[13]); EXPECT_EQ(gfx::Point(600, 390), points[13]);
ASSERT_EQ(gfx::Point(600, 400), points[14]); EXPECT_EQ(gfx::Point(600, 400), points[14]);
ASSERT_EQ(gfx::Point(600, 400), points[15]); EXPECT_EQ(gfx::Point(600, 400), points[15]);
ASSERT_EQ(gfx::Point(600, 400), points[16]); EXPECT_EQ(gfx::Point(600, 400), points[16]);
ASSERT_EQ(gfx::Point(600, 400), points[17]); EXPECT_EQ(gfx::Point(600, 400), points[17]);
ASSERT_EQ(gfx::Point(600, 410), points[18]); EXPECT_EQ(gfx::Point(600, 410), points[18]);
ASSERT_EQ(gfx::Point(600, 490), points[19]); EXPECT_EQ(gfx::Point(600, 490), points[19]);
ASSERT_EQ(gfx::Point(600, 500), points[20]); EXPECT_EQ(gfx::Point(600, 500), points[20]);
ASSERT_EQ(gfx::Point(590, 500), points[21]); EXPECT_EQ(gfx::Point(590, 500), points[21]);
ASSERT_EQ(gfx::Point(410, 500), points[22]); EXPECT_EQ(gfx::Point(410, 500), points[22]);
ASSERT_EQ(gfx::Point(400, 500), points[23]); EXPECT_EQ(gfx::Point(400, 500), points[23]);
ASSERT_EQ(gfx::Point(400, 490), points[24]); EXPECT_EQ(gfx::Point(400, 490), points[24]);
ASSERT_EQ(gfx::Point(400, 410), points[25]); EXPECT_EQ(gfx::Point(400, 410), points[25]);
ASSERT_EQ(gfx::Point(400, 400), points[26]); EXPECT_EQ(gfx::Point(400, 400), points[26]);
ASSERT_EQ(gfx::Point(390, 400), points[27]); EXPECT_EQ(gfx::Point(390, 400), points[27]);
ASSERT_EQ(gfx::Point(10, 400), points[28]); EXPECT_EQ(gfx::Point(10, 400), points[28]);
ASSERT_EQ(gfx::Point(0, 400), points[29]); EXPECT_EQ(gfx::Point(0, 400), points[29]);
ASSERT_EQ(gfx::Point(0, 390), points[30]); EXPECT_EQ(gfx::Point(0, 390), points[30]);
ASSERT_EQ(gfx::Point(0, 110), points[31]); EXPECT_EQ(gfx::Point(0, 110), points[31]);
ASSERT_EQ(gfx::Point(0, 100), points[32]); EXPECT_EQ(gfx::Point(0, 100), points[32]);
ASSERT_EQ(gfx::Point(0, 100), points[33]); EXPECT_EQ(gfx::Point(0, 100), points[33]);
ASSERT_EQ(gfx::Point(0, 100), points[34]); EXPECT_EQ(gfx::Point(0, 100), points[34]);
ASSERT_EQ(gfx::Point(0, 100), points[35]); EXPECT_EQ(gfx::Point(0, 100), points[35]);
} }
} // namespace chromeos } // namespace chromeos
...@@ -16,7 +16,7 @@ namespace chromeos { ...@@ -16,7 +16,7 @@ namespace chromeos {
namespace { namespace {
// The number of pixels in the color gradient that fades to transparent. // The number of pixels in the color gradient that fades to transparent.
const int kGradientWidth = 10; const int kGradientWidth = 6;
// The color of the focus ring. In the future this might be a parameter. // The color of the focus ring. In the future this might be a parameter.
const int kFocusRingColorRed = 247; const int kFocusRingColorRed = 247;
...@@ -118,10 +118,11 @@ void AccessibilityFocusRingLayer::OnPaintLayer(gfx::Canvas* canvas) { ...@@ -118,10 +118,11 @@ void AccessibilityFocusRingLayer::OnPaintLayer(gfx::Canvas* canvas) {
paint.setStrokeWidth(2); paint.setStrokeWidth(2);
SkPath path; SkPath path;
for (int i = 0; i < kGradientWidth; i++) { const int w = kGradientWidth;
for (int i = 0; i < w; ++i) {
paint.setColor( paint.setColor(
SkColorSetARGBMacro( SkColorSetARGBMacro(
255 - (255 * i / kGradientWidth), 255 * (w - i) * (w - i) / (w * w),
kFocusRingColorRed, kFocusRingColorGreen, kFocusRingColorBlue)); kFocusRingColorRed, kFocusRingColorGreen, kFocusRingColorBlue));
path = MakePath(ring_, i, offset); path = MakePath(ring_, i, offset);
canvas->DrawPath(path, paint); canvas->DrawPath(path, paint);
......
...@@ -40,6 +40,7 @@ class FocusRingLayer : public ui::LayerDelegate { ...@@ -40,6 +40,7 @@ class FocusRingLayer : public ui::LayerDelegate {
void Set(aura::Window* root_window, const gfx::Rect& bounds); void Set(aura::Window* root_window, const gfx::Rect& bounds);
ui::Layer* layer() { return layer_.get(); } ui::Layer* layer() { return layer_.get(); }
aura::Window* root_window() { return root_window_; }
protected: protected:
// Updates |root_window_| and creates |layer_| if it doesn't exist, // Updates |root_window_| and creates |layer_| if it doesn't exist,
......
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