1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "ash/accessibility/accessibility_cursor_ring_layer.h"
6 
7 #include "ash/shell.h"
8 #include "third_party/skia/include/core/SkPaint.h"
9 #include "third_party/skia/include/core/SkPath.h"
10 #include "ui/aura/window.h"
11 #include "ui/compositor/layer.h"
12 #include "ui/compositor/paint_recorder.h"
13 #include "ui/display/display.h"
14 #include "ui/display/screen.h"
15 #include "ui/gfx/canvas.h"
16 #include "ui/wm/core/coordinate_conversion.h"
17 
18 namespace ash {
19 
20 namespace {
21 
22 // The number of pixels in the color gradient that fades to transparent.
23 const int kGradientWidth = 8;
24 
25 // The radius of the ring in pixels.
26 const int kCursorRingRadius = 24;
27 
28 // Extra margin to add to the layer in pixels.
29 const int kLayerMargin = 8;
30 
31 }  // namespace
32 
AccessibilityCursorRingLayer(AccessibilityLayerDelegate * delegate,int red,int green,int blue)33 AccessibilityCursorRingLayer::AccessibilityCursorRingLayer(
34     AccessibilityLayerDelegate* delegate,
35     int red,
36     int green,
37     int blue)
38     : FocusRingLayer(delegate), red_(red), green_(green), blue_(blue) {}
39 
40 AccessibilityCursorRingLayer::~AccessibilityCursorRingLayer() = default;
41 
Set(const gfx::Point & location)42 void AccessibilityCursorRingLayer::Set(const gfx::Point& location) {
43   location_ = location;
44 
45   gfx::Rect bounds = gfx::Rect(location.x(), location.y(), 0, 0);
46   int inset = kGradientWidth + kCursorRingRadius + kLayerMargin;
47   bounds.Inset(-inset, -inset, -inset, -inset);
48 
49   display::Display display =
50       display::Screen::GetScreen()->GetDisplayMatching(bounds);
51   aura::Window* root_window = Shell::GetRootWindowForDisplayId(display.id());
52   ::wm::ConvertRectFromScreen(root_window, &bounds);
53   CreateOrUpdateLayer(root_window, "AccessibilityCursorRing", bounds);
54 }
55 
OnPaintLayer(const ui::PaintContext & context)56 void AccessibilityCursorRingLayer::OnPaintLayer(
57     const ui::PaintContext& context) {
58   ui::PaintRecorder recorder(context, layer()->size());
59 
60   cc::PaintFlags flags;
61   flags.setAntiAlias(true);
62   flags.setStyle(cc::PaintFlags::kStroke_Style);
63   flags.setStrokeWidth(2);
64 
65   gfx::Rect r = layer()->bounds();
66   r.Offset(-r.OffsetFromOrigin());
67   r.Inset(kLayerMargin, kLayerMargin, kLayerMargin, kLayerMargin);
68   const int w = kGradientWidth;
69   for (int i = 0; i < w; ++i) {
70     flags.setColor(SkColorSetARGB(255 * i * i / (w * w), red_, green_, blue_));
71     SkPath path;
72     path.addOval(SkRect::MakeXYWH(r.x(), r.y(), r.width(), r.height()));
73     r.Inset(1, 1, 1, 1);
74     recorder.canvas()->DrawPath(path, flags);
75   }
76 }
77 
78 }  // namespace ash
79