Chromium Code Reviews| Index: chrome/browser/chromeos/ui/accessibility_focus_ring_layer.cc |
| diff --git a/chrome/browser/chromeos/ui/accessibility_focus_ring_layer.cc b/chrome/browser/chromeos/ui/accessibility_focus_ring_layer.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..b0fafba3c8bff7d5e13dce6eab7fa91ca6bcc4e6 |
| --- /dev/null |
| +++ b/chrome/browser/chromeos/ui/accessibility_focus_ring_layer.cc |
| @@ -0,0 +1,138 @@ |
| +// Copyright 2014 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. |
| + |
| +#include "chrome/browser/chromeos/ui/accessibility_focus_ring_layer.h" |
| + |
| +#include "ash/shell.h" |
| +#include "base/bind.h" |
| +#include "ui/aura/window.h" |
| +#include "ui/compositor/layer.h" |
| +#include "ui/gfx/canvas.h" |
| + |
| +namespace chromeos { |
| + |
| +namespace { |
| + |
| +// The number of pixels in the color gradient that fades to transparent. |
| +const int kGradientWidth = 10; |
| + |
| +// The color of the focus ring. In the future this might be a parameter. |
| +const int kFocusRingColorRed = 247; |
| +const int kFocusRingColorGreen = 152; |
| +const int kFocusRingColorBlue = 58; |
| + |
| +int sign(int x) { |
| + return ((x > 0) ? 1 : (x == 0) ? 0 : -1); |
| +} |
| + |
| +SkPath MakePath(const AccessibilityFocusRing& input_ring, |
| + int outset, |
| + const gfx::Vector2d& offset) { |
| + AccessibilityFocusRing ring = input_ring; |
| + |
| + for (int i = 0; i < 36; i++) { |
| + gfx::Point p = input_ring.points[i]; |
| + gfx::Point prev; |
| + gfx::Point next; |
| + |
| + int prev_index = i; |
| + do { |
| + prev_index = (prev_index + 35) % 36; |
| + prev = input_ring.points[prev_index]; |
| + } while (prev.x() == p.x() && prev.y() == p.y()); |
| + |
| + int next_index = i; |
| + do { |
| + next_index = (next_index + 1) % 36; |
| + next = input_ring.points[next_index]; |
| + } while (next.x() == p.x() && next.y() == p.y()); |
| + |
| + gfx::Point delta0 = gfx::Point(sign(p.x() - prev.x()), |
| + sign(p.y() - prev.y())); |
| + gfx::Point delta1 = gfx::Point(sign(next.x() - p.x()), |
| + sign(next.y() - p.y())); |
| + |
| + if (delta0.x() == delta1.x() && delta0.y() == delta1.y()) { |
| + ring.points[i] = gfx::Point( |
| + input_ring.points[i].x() + outset * delta0.y(), |
| + input_ring.points[i].y() - outset * delta0.x()); |
| + } else { |
| + ring.points[i] = gfx::Point( |
| + input_ring.points[i].x() + ((i + 13) % 36 >= 18 ? outset : -outset), |
| + input_ring.points[i].y() + ((i + 4) % 36 >= 18 ? outset : -outset)); |
| + } |
| + } |
| + |
| + SkPath path; |
| + gfx::Point p0 = ring.points[0] - offset; |
| + path.moveTo(SkIntToScalar(p0.x()), SkIntToScalar(p0.y())); |
| + for (int i = 0; i < 12; i++) { |
| + int index0 = ((3 * i) + 1) % 36; |
| + int index1 = ((3 * i) + 2) % 36; |
| + int index2 = ((3 * i) + 3) % 36; |
| + gfx::Point p0 = ring.points[index0] - offset; |
| + gfx::Point p1 = ring.points[index1] - offset; |
| + gfx::Point p2 = ring.points[index2] - offset; |
| + path.lineTo(SkIntToScalar(p0.x()), SkIntToScalar(p0.y())); |
| + path.quadTo(SkIntToScalar(p1.x()), SkIntToScalar(p1.y()), |
| + SkIntToScalar(p2.x()), SkIntToScalar(p2.y())); |
| + } |
| + |
| + return path; |
| +} |
| + |
| +} // namespace |
| + |
| +AccessibilityFocusRingLayer::AccessibilityFocusRingLayer( |
| + FocusRingLayerDelegate* delegate) |
| + : FocusRingLayer(delegate) { |
| +} |
| + |
| +AccessibilityFocusRingLayer::~AccessibilityFocusRingLayer() {} |
| + |
| +void AccessibilityFocusRingLayer::Set(const AccessibilityFocusRing& ring) { |
| + ring_ = ring; |
| + |
| + gfx::Rect bounds = ring.GetBounds(); |
| + int inset = kGradientWidth; |
| + bounds.Inset(-inset, -inset, -inset, -inset); |
| + |
| + if (!layer_) { |
| + aura::Window* root_window = ash::Shell::GetPrimaryRootWindow(); |
|
xiyuan
2014/09/11 03:57:45
Primary root window might not always be right. We
dmazzoni
2014/09/11 21:44:39
Great! I knew this needed to be done but wasn't su
|
| + ui::Layer* root_layer = root_window->layer(); |
| + layer_.reset(new ui::Layer(ui::LAYER_TEXTURED)); |
| + layer_->set_name("AccessibilityFocusRing"); |
| + layer_->set_delegate(this); |
| + layer_->SetFillsBoundsOpaquely(false); |
| + root_layer->Add(layer_.get()); |
| + } |
| + |
| + // Keep moving it to the top in case new layers have been added |
| + // since we created this layer. |
| + layer_->parent()->StackAtTop(layer_.get()); |
| + |
| + // Update the layer bounds. |
| + layer_->SetBounds(bounds); |
| +} |
| + |
| +void AccessibilityFocusRingLayer::OnPaintLayer(gfx::Canvas* canvas) { |
| + gfx::Vector2d offset = layer_->bounds().OffsetFromOrigin(); |
| + |
| + SkPaint paint; |
| + paint.setFlags(SkPaint::kAntiAlias_Flag); |
| + paint.setStyle(SkPaint::kStroke_Style); |
| + paint.setStrokeWidth(2); |
| + |
| + SkPath path; |
| + for (int i = 0; i < kGradientWidth; i++) { |
| + paint.setColor( |
| + SkColorSetARGBMacro( |
| + 255 - (255 * i / kGradientWidth), |
| + kFocusRingColorRed, kFocusRingColorGreen, kFocusRingColorBlue)); |
| + path = MakePath(ring_, i, offset); |
| + canvas->DrawPath(path, paint); |
| + } |
| +} |
| + |
| +} // namespace chromeos |