Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(770)

Side by Side Diff: chrome/browser/chromeos/ui/accessibility_focus_ring_controller.cc

Issue 602813003: Animate the accessibility focus ring and fix some minor visual issues. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@focus_ring_in_chromevox
Patch Set: Fix unit tests Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/chromeos/ui/accessibility_focus_ring_controller.h" 5 #include "chrome/browser/chromeos/ui/accessibility_focus_ring_controller.h"
6 6
7 #include "ash/display/display_controller.h"
8 #include "ash/shell.h"
9 #include "base/logging.h"
7 #include "chrome/browser/chromeos/ui/focus_ring_layer.h" 10 #include "chrome/browser/chromeos/ui/focus_ring_layer.h"
11 #include "ui/gfx/screen.h"
8 12
9 namespace chromeos { 13 namespace chromeos {
10 14
11 namespace { 15 namespace {
12 16
13 // The number of pixels the focus ring is outset from the object it outlines, 17 // The number of pixels the focus ring is outset from the object it outlines,
14 // which also determines the border radius of the rounded corners. 18 // which also determines the border radius of the rounded corners.
15 // TODO(dmazzoni): take display resolution into account. 19 // TODO(dmazzoni): take display resolution into account.
16 const int kAccessibilityFocusRingMargin = 16; 20 const int kAccessibilityFocusRingMargin = 7;
21
22 // Time to transition between one location and the next.
23 const int kTransitionTimeMilliseconds = 300;
17 24
18 // A Region is an unordered collection of Rects that maintains its 25 // A Region is an unordered collection of Rects that maintains its
19 // bounding box. Used in the middle of an algorithm that groups 26 // bounding box. Used in the middle of an algorithm that groups
20 // adjacent and overlapping rects. 27 // adjacent and overlapping rects.
21 struct Region { 28 struct Region {
22 explicit Region(gfx::Rect initial_rect) { 29 explicit Region(gfx::Rect initial_rect) {
23 bounds = initial_rect; 30 bounds = initial_rect;
24 rects.push_back(initial_rect); 31 rects.push_back(initial_rect);
25 } 32 }
26 gfx::Rect bounds; 33 gfx::Rect bounds;
27 std::vector<gfx::Rect> rects; 34 std::vector<gfx::Rect> rects;
28 }; 35 };
29 36
30 } // namespace 37 } // namespace
31 38
32 // static 39 // static
33 AccessibilityFocusRingController* 40 AccessibilityFocusRingController*
34 AccessibilityFocusRingController::GetInstance() { 41 AccessibilityFocusRingController::GetInstance() {
35 return Singleton<AccessibilityFocusRingController>::get(); 42 return Singleton<AccessibilityFocusRingController>::get();
36 } 43 }
37 44
38 AccessibilityFocusRingController::AccessibilityFocusRingController() { 45 AccessibilityFocusRingController::AccessibilityFocusRingController()
46 : compositor_(NULL) {
39 } 47 }
40 48
41 AccessibilityFocusRingController::~AccessibilityFocusRingController() { 49 AccessibilityFocusRingController::~AccessibilityFocusRingController() {
42 } 50 }
43 51
44 void AccessibilityFocusRingController::SetFocusRing( 52 void AccessibilityFocusRingController::SetFocusRing(
45 const std::vector<gfx::Rect>& rects) { 53 const std::vector<gfx::Rect>& rects) {
46 rects_ = rects; 54 rects_ = rects;
47 Update(); 55 Update();
48 } 56 }
49 57
50 void AccessibilityFocusRingController::Update() { 58 void AccessibilityFocusRingController::Update() {
59 previous_rings_.swap(rings_);
51 rings_.clear(); 60 rings_.clear();
52 RectsToRings(rects_, &rings_); 61 RectsToRings(rects_, &rings_);
62 layers_.resize(rings_.size());
63 for (size_t i = 0; i < rings_.size(); ++i) {
64 if (!layers_[i])
65 layers_[i].reset(new AccessibilityFocusRingLayer(this));
53 66
54 if (!main_focus_ring_layer_) 67 if (i > 0) {
55 main_focus_ring_layer_.reset(new AccessibilityFocusRingLayer(this)); 68 // Focus rings other than the first one don't animate.
69 layers_[i]->Set(rings_[i]);
70 continue;
71 }
56 72
57 if (!rings_.empty()) 73 gfx::Rect bounds = rings_[0].GetBounds();
58 main_focus_ring_layer_->Set(rings_[0]); 74 gfx::Display display =
75 gfx::Screen::GetNativeScreen()->GetDisplayMatching(bounds);
76 aura::Window* root_window = ash::Shell::GetInstance()->display_controller()
77 ->GetRootWindowForDisplayId(display.id());
78 ui::Compositor* compositor = root_window->layer()->GetCompositor();
79 if (!compositor || root_window != layers_[0]->root_window()) {
80 layers_[0]->Set(rings_[0]);
81 if (compositor_ && compositor_->HasAnimationObserver(this)) {
82 compositor_->RemoveAnimationObserver(this);
83 compositor_ = NULL;
84 }
85 continue;
86 }
87
88 focus_change_time_ = base::TimeTicks::Now();
89 if (!compositor->HasAnimationObserver(this)) {
90 compositor_ = compositor;
91 compositor_->AddAnimationObserver(this);
92 }
93 }
59 } 94 }
60 95
61 void AccessibilityFocusRingController::RectsToRings( 96 void AccessibilityFocusRingController::RectsToRings(
62 const std::vector<gfx::Rect>& rects, 97 const std::vector<gfx::Rect>& src_rects,
63 std::vector<AccessibilityFocusRing>* rings) const { 98 std::vector<AccessibilityFocusRing>* rings) const {
64 if (rects.empty()) 99 if (src_rects.empty())
65 return; 100 return;
66 101
102 // Give all of the rects a margin.
103 std::vector<gfx::Rect> rects;
104 rects.resize(src_rects.size());
105 for (size_t i = 0; i < src_rects.size(); ++i) {
106 rects[i] = src_rects[i];
107 rects[i].Inset(-GetMargin(), -GetMargin());
108 }
109
67 // Split the rects into contiguous regions. 110 // Split the rects into contiguous regions.
68 std::vector<Region> regions; 111 std::vector<Region> regions;
69 regions.push_back(Region(rects[0])); 112 regions.push_back(Region(rects[0]));
70 for (size_t i = 1; i < rects.size(); ++i) { 113 for (size_t i = 1; i < rects.size(); ++i) {
71 bool found = false; 114 bool found = false;
72 for (size_t j = 0; j < regions.size(); ++j) { 115 for (size_t j = 0; j < regions.size(); ++j) {
73 if (Intersects(rects[i], regions[j].bounds)) { 116 if (Intersects(rects[i], regions[j].bounds)) {
74 regions[j].rects.push_back(rects[i]); 117 regions[j].rects.push_back(rects[i]);
75 regions[j].bounds.Union(rects[i]); 118 regions[j].bounds.Union(rects[i]);
76 found = true; 119 found = true;
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
237 return (r2.x() <= r1.right() + slop && 280 return (r2.x() <= r1.right() + slop &&
238 r2.right() >= r1.x() - slop && 281 r2.right() >= r1.x() - slop &&
239 r2.y() <= r1.bottom() + slop && 282 r2.y() <= r1.bottom() + slop &&
240 r2.bottom() >= r1.y() - slop); 283 r2.bottom() >= r1.y() - slop);
241 } 284 }
242 285
243 void AccessibilityFocusRingController::OnDeviceScaleFactorChanged() { 286 void AccessibilityFocusRingController::OnDeviceScaleFactorChanged() {
244 Update(); 287 Update();
245 } 288 }
246 289
290 void AccessibilityFocusRingController::OnAnimationStep(
291 base::TimeTicks timestamp) {
292 if (rings_.empty())
293 return;
294
295 CHECK(compositor_);
296 CHECK(!rings_.empty());
297 CHECK(!layers_.empty());
298 CHECK(layers_[0]);
299
300 base::TimeDelta delta = timestamp - focus_change_time_;
301 base::TimeDelta transition_time =
302 base::TimeDelta::FromMilliseconds(kTransitionTimeMilliseconds);
303 if (delta >= transition_time) {
304 layers_[0]->Set(rings_[0]);
305 compositor_->RemoveAnimationObserver(this);
306 compositor_ = NULL;
307 return;
308 }
309
310 double fraction = delta.InSecondsF() / transition_time.InSecondsF();
311
312 // Ease-in effect.
313 fraction = pow(fraction, 0.3);
314
315 layers_[0]->Set(AccessibilityFocusRing::Interpolate(
316 previous_rings_[0], rings_[0], fraction));
317 }
318
247 } // namespace chromeos 319 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698