OLD | NEW |
---|---|
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++) { | |
xiyuan
2014/09/24 19:40:35
nit: ++i
dmazzoni
2014/09/24 21:40:56
Done.
| |
106 rects[i] = src_rects[i]; | |
107 rects[i].Inset(-kAccessibilityFocusRingMargin, | |
108 -kAccessibilityFocusRingMargin); | |
109 } | |
110 | |
67 // Split the rects into contiguous regions. | 111 // Split the rects into contiguous regions. |
68 std::vector<Region> regions; | 112 std::vector<Region> regions; |
69 regions.push_back(Region(rects[0])); | 113 regions.push_back(Region(rects[0])); |
70 for (size_t i = 1; i < rects.size(); ++i) { | 114 for (size_t i = 1; i < rects.size(); ++i) { |
71 bool found = false; | 115 bool found = false; |
72 for (size_t j = 0; j < regions.size(); ++j) { | 116 for (size_t j = 0; j < regions.size(); ++j) { |
73 if (Intersects(rects[i], regions[j].bounds)) { | 117 if (Intersects(rects[i], regions[j].bounds)) { |
74 regions[j].rects.push_back(rects[i]); | 118 regions[j].rects.push_back(rects[i]); |
75 regions[j].bounds.Union(rects[i]); | 119 regions[j].bounds.Union(rects[i]); |
76 found = true; | 120 found = true; |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
237 return (r2.x() <= r1.right() + slop && | 281 return (r2.x() <= r1.right() + slop && |
238 r2.right() >= r1.x() - slop && | 282 r2.right() >= r1.x() - slop && |
239 r2.y() <= r1.bottom() + slop && | 283 r2.y() <= r1.bottom() + slop && |
240 r2.bottom() >= r1.y() - slop); | 284 r2.bottom() >= r1.y() - slop); |
241 } | 285 } |
242 | 286 |
243 void AccessibilityFocusRingController::OnDeviceScaleFactorChanged() { | 287 void AccessibilityFocusRingController::OnDeviceScaleFactorChanged() { |
244 Update(); | 288 Update(); |
245 } | 289 } |
246 | 290 |
291 void AccessibilityFocusRingController::OnAnimationStep( | |
292 base::TimeTicks timestamp) { | |
293 CHECK(compositor_); | |
294 CHECK(!rings_.empty()); | |
295 CHECK(!layers_.empty()); | |
296 CHECK(layers_[0]); | |
297 | |
298 base::TimeDelta delta = timestamp - focus_change_time_; | |
299 base::TimeDelta transition_time = | |
300 base::TimeDelta::FromMilliseconds(kTransitionTimeMilliseconds); | |
301 if (delta >= transition_time) { | |
302 layers_[0]->Set(rings_[0]); | |
303 compositor_->RemoveAnimationObserver(this); | |
304 compositor_ = NULL; | |
305 return; | |
306 } | |
307 | |
308 double fraction = delta.InSecondsF() / transition_time.InSecondsF(); | |
309 | |
310 // Ease-in effect. | |
311 fraction = pow(fraction, 0.3); | |
312 | |
313 layers_[0]->Set(AccessibilityFocusRing::Interpolate( | |
314 previous_rings_[0], rings_[0], fraction)); | |
315 } | |
316 | |
247 } // namespace chromeos | 317 } // namespace chromeos |
OLD | NEW |