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 <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 | 10 |
11 #include "ash/display/window_tree_host_manager.h" | |
12 #include "ash/shell.h" | 11 #include "ash/shell.h" |
13 #include "base/logging.h" | 12 #include "base/logging.h" |
14 #include "chrome/browser/chromeos/ui/focus_ring_layer.h" | 13 #include "chrome/browser/chromeos/ui/focus_ring_layer.h" |
15 #include "ui/display/screen.h" | |
16 | 14 |
17 namespace chromeos { | 15 namespace chromeos { |
18 | 16 |
19 namespace { | 17 namespace { |
20 | 18 |
21 // The number of pixels the focus ring is outset from the object it outlines, | 19 // The number of pixels the focus ring is outset from the object it outlines, |
22 // which also determines the border radius of the rounded corners. | 20 // which also determines the border radius of the rounded corners. |
23 // TODO(dmazzoni): take display resolution into account. | 21 // TODO(dmazzoni): take display resolution into account. |
24 const int kAccessibilityFocusRingMargin = 7; | 22 const int kAccessibilityFocusRingMargin = 7; |
25 | 23 |
(...skipping 27 matching lines...) Expand all Loading... |
53 | 51 |
54 } // namespace | 52 } // namespace |
55 | 53 |
56 // static | 54 // static |
57 AccessibilityFocusRingController* | 55 AccessibilityFocusRingController* |
58 AccessibilityFocusRingController::GetInstance() { | 56 AccessibilityFocusRingController::GetInstance() { |
59 return base::Singleton<AccessibilityFocusRingController>::get(); | 57 return base::Singleton<AccessibilityFocusRingController>::get(); |
60 } | 58 } |
61 | 59 |
62 AccessibilityFocusRingController::AccessibilityFocusRingController() | 60 AccessibilityFocusRingController::AccessibilityFocusRingController() |
63 : compositor_(nullptr), cursor_opacity_(0), cursor_compositor_(nullptr) {} | 61 : cursor_opacity_(0) {} |
64 | 62 |
65 AccessibilityFocusRingController::~AccessibilityFocusRingController() { | 63 AccessibilityFocusRingController::~AccessibilityFocusRingController() { |
66 } | 64 } |
67 | 65 |
68 void AccessibilityFocusRingController::SetFocusRing( | 66 void AccessibilityFocusRingController::SetFocusRing( |
69 const std::vector<gfx::Rect>& rects) { | 67 const std::vector<gfx::Rect>& rects) { |
70 rects_ = rects; | 68 rects_ = rects; |
71 Update(); | 69 Update(); |
72 } | 70 } |
73 | 71 |
74 void AccessibilityFocusRingController::Update() { | 72 void AccessibilityFocusRingController::Update() { |
75 previous_rings_.swap(rings_); | 73 previous_rings_.swap(rings_); |
76 rings_.clear(); | 74 rings_.clear(); |
77 RectsToRings(rects_, &rings_); | 75 RectsToRings(rects_, &rings_); |
78 layers_.resize(rings_.size()); | 76 layers_.resize(rings_.size()); |
79 if (rings_.empty()) | 77 if (rings_.empty()) |
80 return; | 78 return; |
81 | 79 |
82 for (size_t i = 0; i < rings_.size(); ++i) { | 80 for (size_t i = 0; i < rings_.size(); ++i) { |
83 if (!layers_[i]) | 81 if (!layers_[i]) |
84 layers_[i] = new AccessibilityFocusRingLayer(this); | 82 layers_[i] = new AccessibilityFocusRingLayer(this); |
85 | 83 |
86 if (i > 0) { | 84 if (i > 0) { |
87 // Focus rings other than the first one don't animate. | 85 // Focus rings other than the first one don't animate. |
88 layers_[i]->Set(rings_[i]); | 86 layers_[i]->Set(rings_[i]); |
89 } | 87 } |
90 } | 88 } |
91 | 89 |
92 ui::Compositor* compositor = CompositorForBounds(rings_[0].GetBounds()); | 90 if (layers_[0]->CanAnimate()) { |
93 if (compositor != compositor_) { | |
94 RemoveAnimationObservers(); | |
95 compositor_ = compositor; | |
96 AddAnimationObservers(); | |
97 } | |
98 | |
99 if (compositor_ && compositor_->HasAnimationObserver(this)) { | |
100 focus_change_time_ = base::TimeTicks::Now(); | 91 focus_change_time_ = base::TimeTicks::Now(); |
101 } else { | 92 } else { |
102 // If we can't animate, set the location of the first ring. | 93 // If we can't animate, set the location of the first ring. |
103 layers_[0]->Set(rings_[0]); | 94 layers_[0]->Set(rings_[0]); |
104 } | 95 } |
105 } | 96 } |
106 | 97 |
107 ui::Compositor* AccessibilityFocusRingController::CompositorForBounds( | |
108 const gfx::Rect& bounds) { | |
109 display::Display display = | |
110 display::Screen::GetScreen()->GetDisplayMatching(bounds); | |
111 aura::Window* root_window = ash::Shell::GetInstance() | |
112 ->window_tree_host_manager() | |
113 ->GetRootWindowForDisplayId(display.id()); | |
114 return root_window->layer()->GetCompositor(); | |
115 } | |
116 | |
117 void AccessibilityFocusRingController::RemoveAnimationObservers() { | |
118 if (compositor_ && compositor_->HasAnimationObserver(this)) | |
119 compositor_->RemoveAnimationObserver(this); | |
120 if (cursor_compositor_ && cursor_compositor_->HasAnimationObserver(this)) | |
121 cursor_compositor_->RemoveAnimationObserver(this); | |
122 } | |
123 | |
124 void AccessibilityFocusRingController::AddAnimationObservers() { | |
125 if (compositor_ && !compositor_->HasAnimationObserver(this)) | |
126 compositor_->AddAnimationObserver(this); | |
127 if (cursor_compositor_ && !cursor_compositor_->HasAnimationObserver(this)) | |
128 cursor_compositor_->AddAnimationObserver(this); | |
129 } | |
130 | |
131 void AccessibilityFocusRingController::SetCursorRing( | 98 void AccessibilityFocusRingController::SetCursorRing( |
132 const gfx::Point& location) { | 99 const gfx::Point& location) { |
133 cursor_location_ = location; | 100 cursor_location_ = location; |
134 cursor_change_time_ = base::TimeTicks::Now(); | 101 cursor_change_time_ = base::TimeTicks::Now(); |
135 if (cursor_opacity_ == 0) | 102 if (cursor_opacity_ == 0) |
136 cursor_start_time_ = cursor_change_time_; | 103 cursor_start_time_ = cursor_change_time_; |
137 | 104 |
138 if (!cursor_layer_) { | 105 if (!cursor_layer_) { |
139 cursor_layer_.reset(new AccessibilityCursorRingLayer( | 106 cursor_layer_.reset(new AccessibilityCursorRingLayer( |
140 this, kCursorRingColorRed, kCursorRingColorGreen, | 107 this, kCursorRingColorRed, kCursorRingColorGreen, |
141 kCursorRingColorBlue)); | 108 kCursorRingColorBlue)); |
142 } | 109 } |
143 cursor_layer_->Set(location); | 110 cursor_layer_->Set(location); |
144 | |
145 ui::Compositor* compositor = | |
146 CompositorForBounds(gfx::Rect(location.x(), location.y(), 0, 0)); | |
147 if (compositor != cursor_compositor_) { | |
148 RemoveAnimationObservers(); | |
149 cursor_compositor_ = compositor; | |
150 AddAnimationObservers(); | |
151 } | |
152 } | 111 } |
153 | 112 |
154 void AccessibilityFocusRingController::SetCaretRing( | 113 void AccessibilityFocusRingController::SetCaretRing( |
155 const gfx::Point& location) { | 114 const gfx::Point& location) { |
156 caret_location_ = location; | 115 caret_location_ = location; |
157 | 116 |
158 if (!caret_layer_) { | 117 if (!caret_layer_) { |
159 caret_layer_.reset(new AccessibilityCursorRingLayer( | 118 caret_layer_.reset(new AccessibilityCursorRingLayer( |
160 this, kCaretRingColorRed, kCaretRingColorGreen, kCaretRingColorBlue)); | 119 this, kCaretRingColorRed, kCaretRingColorGreen, kCaretRingColorBlue)); |
161 } | 120 } |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
352 r2.y() <= r1.bottom() + slop && | 311 r2.y() <= r1.bottom() + slop && |
353 r2.bottom() >= r1.y() - slop); | 312 r2.bottom() >= r1.y() - slop); |
354 } | 313 } |
355 | 314 |
356 void AccessibilityFocusRingController::OnDeviceScaleFactorChanged() { | 315 void AccessibilityFocusRingController::OnDeviceScaleFactorChanged() { |
357 Update(); | 316 Update(); |
358 } | 317 } |
359 | 318 |
360 void AccessibilityFocusRingController::OnAnimationStep( | 319 void AccessibilityFocusRingController::OnAnimationStep( |
361 base::TimeTicks timestamp) { | 320 base::TimeTicks timestamp) { |
362 if (!rings_.empty() && compositor_) | 321 if (!rings_.empty() && layers_[0]->CanAnimate()) |
363 AnimateFocusRings(timestamp); | 322 AnimateFocusRings(timestamp); |
364 | 323 |
365 if (cursor_layer_ && cursor_compositor_) | 324 if (cursor_layer_ && cursor_layer_->CanAnimate()) |
366 AnimateCursorRing(timestamp); | 325 AnimateCursorRing(timestamp); |
367 } | 326 } |
368 | 327 |
369 void AccessibilityFocusRingController::AnimateFocusRings( | 328 void AccessibilityFocusRingController::AnimateFocusRings( |
370 base::TimeTicks timestamp) { | 329 base::TimeTicks timestamp) { |
371 CHECK(!rings_.empty()); | 330 CHECK(!rings_.empty()); |
372 CHECK(!layers_.empty()); | 331 CHECK(!layers_.empty()); |
373 CHECK(layers_[0]); | 332 CHECK(layers_[0]); |
374 | 333 |
375 // It's quite possible for the first 1 or 2 animation frames to be | 334 // It's quite possible for the first 1 or 2 animation frames to be |
376 // for a timestamp that's earlier than the time we received the | 335 // for a timestamp that's earlier than the time we received the |
377 // focus change, so we just treat those as a delta of zero. | 336 // focus change, so we just treat those as a delta of zero. |
378 if (timestamp < focus_change_time_) | 337 if (timestamp < focus_change_time_) |
379 timestamp = focus_change_time_; | 338 timestamp = focus_change_time_; |
380 | 339 |
381 base::TimeDelta delta = timestamp - focus_change_time_; | 340 base::TimeDelta delta = timestamp - focus_change_time_; |
382 base::TimeDelta transition_time = | 341 base::TimeDelta transition_time = |
383 base::TimeDelta::FromMilliseconds(kTransitionTimeMilliseconds); | 342 base::TimeDelta::FromMilliseconds(kTransitionTimeMilliseconds); |
384 if (delta >= transition_time) { | 343 if (delta >= transition_time) { |
385 layers_[0]->Set(rings_[0]); | 344 layers_[0]->Set(rings_[0]); |
386 | |
387 RemoveAnimationObservers(); | |
388 compositor_ = nullptr; | |
389 AddAnimationObservers(); | |
390 return; | 345 return; |
391 } | 346 } |
392 | 347 |
393 double fraction = delta.InSecondsF() / transition_time.InSecondsF(); | 348 double fraction = delta.InSecondsF() / transition_time.InSecondsF(); |
394 | 349 |
395 // Ease-in effect. | 350 // Ease-in effect. |
396 fraction = pow(fraction, 0.3); | 351 fraction = pow(fraction, 0.3); |
397 | 352 |
398 // Handle corner case where we're animating but we don't have previous | 353 // Handle corner case where we're animating but we don't have previous |
399 // rings. | 354 // rings. |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
433 cursor_opacity_ = 1.0; | 388 cursor_opacity_ = 1.0; |
434 } else { | 389 } else { |
435 cursor_opacity_ = 1.0 - (change_delta.InSecondsF() / | 390 cursor_opacity_ = 1.0 - (change_delta.InSecondsF() / |
436 (fade_in_time + fade_out_time).InSecondsF()); | 391 (fade_in_time + fade_out_time).InSecondsF()); |
437 if (cursor_opacity_ < 0.0) | 392 if (cursor_opacity_ < 0.0) |
438 cursor_opacity_ = 0.0; | 393 cursor_opacity_ = 0.0; |
439 } | 394 } |
440 cursor_layer_->SetOpacity(cursor_opacity_); | 395 cursor_layer_->SetOpacity(cursor_opacity_); |
441 } | 396 } |
442 | 397 |
443 void AccessibilityFocusRingController::OnCompositingShuttingDown( | |
444 ui::Compositor* compositor) { | |
445 if (compositor == compositor_ || compositor == cursor_compositor_) | |
446 compositor->RemoveAnimationObserver(this); | |
447 | |
448 if (compositor == compositor_) | |
449 compositor_ = nullptr; | |
450 if (compositor == cursor_compositor_) | |
451 cursor_compositor_ = nullptr; | |
452 } | |
453 | |
454 } // namespace chromeos | 398 } // namespace chromeos |
OLD | NEW |