OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 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 | 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/autoclick_ring_handler.h" | 5 #include "ash/autoclick/common/autoclick_ring_handler.h" |
6 | 6 |
7 #include <memory> | |
8 | |
9 #include "ash/aura/wm_window_aura.h" | |
10 #include "ash/common/shell_window_ids.h" | |
11 #include "ash/common/wm/root_window_finder.h" | |
12 #include "ash/root_window_controller.h" | |
13 #include "ash/shell.h" | |
14 #include "third_party/skia/include/core/SkColor.h" | 7 #include "third_party/skia/include/core/SkColor.h" |
15 #include "third_party/skia/include/core/SkPaint.h" | 8 #include "third_party/skia/include/core/SkPaint.h" |
16 #include "third_party/skia/include/core/SkPath.h" | 9 #include "third_party/skia/include/core/SkPath.h" |
17 #include "third_party/skia/include/core/SkRect.h" | 10 #include "third_party/skia/include/core/SkRect.h" |
18 #include "ui/aura/client/screen_position_client.h" | |
19 #include "ui/aura/env.h" | |
20 #include "ui/aura/window.h" | 11 #include "ui/aura/window.h" |
21 #include "ui/aura/window_event_dispatcher.h" | |
22 #include "ui/compositor/layer.h" | 12 #include "ui/compositor/layer.h" |
23 #include "ui/gfx/canvas.h" | 13 #include "ui/gfx/canvas.h" |
24 #include "ui/gfx/transform.h" | 14 #include "ui/gfx/transform.h" |
25 #include "ui/views/view.h" | 15 #include "ui/views/view.h" |
26 #include "ui/views/widget/widget.h" | |
27 #include "ui/wm/core/coordinate_conversion.h" | |
28 | 16 |
29 namespace chromeos { | 17 namespace ash { |
30 namespace { | 18 namespace { |
31 | 19 |
32 const int kAutoclickRingOuterRadius = 30; | 20 const int kAutoclickRingOuterRadius = 30; |
33 const int kAutoclickRingInnerRadius = 20; | 21 const int kAutoclickRingInnerRadius = 20; |
34 | 22 |
35 // Angles from x-axis at which the outer and inner circles start. | 23 // Angles from x-axis at which the outer and inner circles start. |
36 const int kAutoclickRingInnerStartAngle = -90; | 24 const int kAutoclickRingInnerStartAngle = -90; |
37 | 25 |
38 const int kAutoclickRingGlowWidth = 20; | 26 const int kAutoclickRingGlowWidth = 20; |
39 // The following is half width to avoid division by 2. | 27 // The following is half width to avoid division by 2. |
40 const int kAutoclickRingArcWidth = 2; | 28 const int kAutoclickRingArcWidth = 2; |
41 | 29 |
42 // Start and end values for various animations. | 30 // Start and end values for various animations. |
43 const double kAutoclickRingScaleStartValue = 1.0; | 31 const double kAutoclickRingScaleStartValue = 1.0; |
44 const double kAutoclickRingScaleEndValue = 1.0; | 32 const double kAutoclickRingScaleEndValue = 1.0; |
45 const double kAutoclickRingShrinkScaleEndValue = 0.5; | 33 const double kAutoclickRingShrinkScaleEndValue = 0.5; |
46 | 34 |
47 const double kAutoclickRingOpacityStartValue = 0.1; | 35 const double kAutoclickRingOpacityStartValue = 0.1; |
48 const double kAutoclickRingOpacityEndValue = 0.5; | 36 const double kAutoclickRingOpacityEndValue = 0.5; |
49 const int kAutoclickRingAngleStartValue = -90; | 37 const int kAutoclickRingAngleStartValue = -90; |
50 // The sweep angle is a bit greater than 360 to make sure the circle | 38 // The sweep angle is a bit greater than 360 to make sure the circle |
51 // completes at the end of the animation. | 39 // completes at the end of the animation. |
52 const int kAutoclickRingAngleEndValue = 360; | 40 const int kAutoclickRingAngleEndValue = 360; |
53 | 41 |
54 // Visual constants. | 42 // Visual constants. |
55 const SkColor kAutoclickRingArcColor = SkColorSetARGB(255, 0, 255, 0); | 43 const SkColor kAutoclickRingArcColor = SkColorSetARGB(255, 0, 255, 0); |
56 const SkColor kAutoclickRingCircleColor = SkColorSetARGB(255, 0, 0, 255); | 44 const SkColor kAutoclickRingCircleColor = SkColorSetARGB(255, 0, 0, 255); |
57 const int kAutoclickRingFrameRateHz = 60; | 45 const int kAutoclickRingFrameRateHz = 60; |
58 | 46 |
59 views::Widget* CreateAutoclickRingWidget(aura::Window* root_window) { | |
60 views::Widget* widget = new views::Widget; | |
61 views::Widget::InitParams params; | |
62 params.type = views::Widget::InitParams::TYPE_WINDOW_FRAMELESS; | |
63 params.accept_events = false; | |
64 params.activatable = views::Widget::InitParams::ACTIVATABLE_NO; | |
65 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; | |
66 params.context = root_window; | |
67 params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; | |
68 params.parent = ash::Shell::GetContainer( | |
69 root_window, ash::kShellWindowId_OverlayContainer); | |
70 | |
71 widget->Init(params); | |
72 widget->SetOpacity(1.f); | |
73 return widget; | |
74 } | |
75 | |
76 void PaintAutoclickRingCircle(gfx::Canvas* canvas, | 47 void PaintAutoclickRingCircle(gfx::Canvas* canvas, |
77 gfx::Point& center, | 48 gfx::Point& center, |
78 int radius) { | 49 int radius) { |
79 SkPaint paint; | 50 SkPaint paint; |
80 paint.setStyle(SkPaint::kStroke_Style); | 51 paint.setStyle(SkPaint::kStroke_Style); |
81 paint.setStrokeWidth(2 * kAutoclickRingArcWidth); | 52 paint.setStrokeWidth(2 * kAutoclickRingArcWidth); |
82 paint.setColor(kAutoclickRingCircleColor); | 53 paint.setColor(kAutoclickRingCircleColor); |
83 paint.setAntiAlias(true); | 54 paint.setAntiAlias(true); |
84 | 55 |
85 canvas->DrawCircle(center, radius, paint); | 56 canvas->DrawCircle(center, radius, paint); |
(...skipping 16 matching lines...) Expand all Loading... |
102 start_angle, end_angle - start_angle); | 73 start_angle, end_angle - start_angle); |
103 canvas->DrawPath(arc_path, paint); | 74 canvas->DrawPath(arc_path, paint); |
104 } | 75 } |
105 } // namespace | 76 } // namespace |
106 | 77 |
107 // View of the AutoclickRingHandler. Draws the actual contents and updates as | 78 // View of the AutoclickRingHandler. Draws the actual contents and updates as |
108 // the animation proceeds. It also maintains the views::Widget that the | 79 // the animation proceeds. It also maintains the views::Widget that the |
109 // animation is shown in. | 80 // animation is shown in. |
110 class AutoclickRingHandler::AutoclickRingView : public views::View { | 81 class AutoclickRingHandler::AutoclickRingView : public views::View { |
111 public: | 82 public: |
112 AutoclickRingView(const gfx::Point& event_location, aura::Window* root_window) | 83 AutoclickRingView(const gfx::Point& event_location, |
| 84 views::Widget* ring_widget) |
113 : views::View(), | 85 : views::View(), |
114 widget_(CreateAutoclickRingWidget(root_window)), | 86 widget_(ring_widget), |
115 current_angle_(kAutoclickRingAngleStartValue), | 87 current_angle_(kAutoclickRingAngleStartValue), |
116 current_scale_(kAutoclickRingScaleStartValue) { | 88 current_scale_(kAutoclickRingScaleStartValue) { |
117 widget_->SetContentsView(this); | 89 widget_->SetContentsView(this); |
118 | 90 |
119 // We are owned by the AutoclickRingHandler. | 91 // We are owned by the AutoclickRingHandler. |
120 set_owned_by_client(); | 92 set_owned_by_client(); |
121 SetNewLocation(event_location, root_window); | 93 SetNewLocation(event_location); |
122 } | 94 } |
123 | 95 |
124 ~AutoclickRingView() override {} | 96 ~AutoclickRingView() override {} |
125 | 97 |
126 void SetNewLocation(const gfx::Point& new_event_location, | 98 void SetNewLocation(const gfx::Point& new_event_location) { |
127 aura::Window* root_window) { | |
128 gfx::Point point = new_event_location; | 99 gfx::Point point = new_event_location; |
129 widget_->SetBounds(gfx::Rect( | 100 widget_->SetBounds(gfx::Rect( |
130 point.x() - (kAutoclickRingOuterRadius + kAutoclickRingGlowWidth), | 101 point.x() - (kAutoclickRingOuterRadius + kAutoclickRingGlowWidth), |
131 point.y() - (kAutoclickRingOuterRadius + kAutoclickRingGlowWidth), | 102 point.y() - (kAutoclickRingOuterRadius + kAutoclickRingGlowWidth), |
132 GetPreferredSize().width(), GetPreferredSize().height())); | 103 GetPreferredSize().width(), GetPreferredSize().height())); |
133 widget_->Show(); | 104 widget_->Show(); |
134 widget_->GetNativeView()->layer()->SetOpacity( | 105 widget_->GetNativeView()->layer()->SetOpacity( |
135 kAutoclickRingOpacityStartValue); | 106 kAutoclickRingOpacityStartValue); |
136 } | 107 } |
137 | 108 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
179 | 150 |
180 // Paint inner circle. | 151 // Paint inner circle. |
181 PaintAutoclickRingArc(canvas, center, kAutoclickRingInnerRadius, | 152 PaintAutoclickRingArc(canvas, center, kAutoclickRingInnerRadius, |
182 kAutoclickRingInnerStartAngle, current_angle_); | 153 kAutoclickRingInnerStartAngle, current_angle_); |
183 // Paint outer circle. | 154 // Paint outer circle. |
184 PaintAutoclickRingCircle(canvas, center, kAutoclickRingOuterRadius); | 155 PaintAutoclickRingCircle(canvas, center, kAutoclickRingOuterRadius); |
185 | 156 |
186 canvas->Restore(); | 157 canvas->Restore(); |
187 } | 158 } |
188 | 159 |
189 std::unique_ptr<views::Widget> widget_; | 160 views::Widget* widget_; |
190 int current_angle_; | 161 int current_angle_; |
191 double current_scale_; | 162 double current_scale_; |
192 | 163 |
193 DISALLOW_COPY_AND_ASSIGN(AutoclickRingView); | 164 DISALLOW_COPY_AND_ASSIGN(AutoclickRingView); |
194 }; | 165 }; |
195 | 166 |
196 //////////////////////////////////////////////////////////////////////////////// | 167 //////////////////////////////////////////////////////////////////////////////// |
197 | 168 |
198 // AutoclickRingHandler, public | 169 // AutoclickRingHandler, public |
199 AutoclickRingHandler::AutoclickRingHandler() | 170 AutoclickRingHandler::AutoclickRingHandler() |
200 : gfx::LinearAnimation(kAutoclickRingFrameRateHz, nullptr), | 171 : gfx::LinearAnimation(kAutoclickRingFrameRateHz, nullptr), |
201 tap_down_target_(nullptr), | 172 ring_widget_(nullptr), |
202 current_animation_type_(AnimationType::NONE) {} | 173 current_animation_type_(AnimationType::NONE) {} |
203 | 174 |
204 AutoclickRingHandler::~AutoclickRingHandler() { | 175 AutoclickRingHandler::~AutoclickRingHandler() { |
205 StopAutoclickRing(); | 176 StopAutoclickRing(); |
206 } | 177 } |
207 | 178 |
208 void AutoclickRingHandler::StartGesture( | 179 void AutoclickRingHandler::StartGesture( |
209 base::TimeDelta duration, | 180 base::TimeDelta duration, |
210 const gfx::Point& center_point_in_screen) { | 181 const gfx::Point& center_point_in_screen, |
211 aura::Window* target = GetTargetWindow(); | 182 views::Widget* widget) { |
212 if (tap_down_target_ && tap_down_target_ != target) | |
213 return; | |
214 StopAutoclickRing(); | 183 StopAutoclickRing(); |
215 SetTapDownTarget(); | |
216 tap_down_location_ = center_point_in_screen; | 184 tap_down_location_ = center_point_in_screen; |
| 185 ring_widget_ = widget; |
217 current_animation_type_ = AnimationType::GROW_ANIMATION; | 186 current_animation_type_ = AnimationType::GROW_ANIMATION; |
218 animation_duration_ = duration; | 187 animation_duration_ = duration; |
219 StartAnimation(base::TimeDelta()); | 188 StartAnimation(base::TimeDelta()); |
220 } | 189 } |
221 | 190 |
222 void AutoclickRingHandler::StopGesture() { | 191 void AutoclickRingHandler::StopGesture() { |
223 aura::Window* target = GetTargetWindow(); | |
224 if (tap_down_target_ && tap_down_target_ != target) | |
225 return; | |
226 StopAutoclickRing(); | 192 StopAutoclickRing(); |
227 } | 193 } |
228 | 194 |
229 void AutoclickRingHandler::SetGestureCenter( | 195 void AutoclickRingHandler::SetGestureCenter( |
230 const gfx::Point& center_point_in_screen) { | 196 const gfx::Point& center_point_in_screen, |
| 197 views::Widget* widget) { |
231 tap_down_location_ = center_point_in_screen; | 198 tap_down_location_ = center_point_in_screen; |
| 199 ring_widget_ = widget; |
232 } | 200 } |
233 //////////////////////////////////////////////////////////////////////////////// | 201 //////////////////////////////////////////////////////////////////////////////// |
234 | 202 |
235 // AutoclickRingHandler, private | 203 // AutoclickRingHandler, private |
236 aura::Window* AutoclickRingHandler::GetTargetWindow() { | |
237 aura::Window* target = ash::WmWindowAura::GetAuraWindow( | |
238 ash::wm::GetRootWindowAt(tap_down_location_)); | |
239 DCHECK(target) << "Root window not found while rendering autoclick circle;"; | |
240 return target; | |
241 } | |
242 | |
243 void AutoclickRingHandler::SetTapDownTarget() { | |
244 aura::Window* target = GetTargetWindow(); | |
245 SetTapDownTarget(target); | |
246 } | |
247 | |
248 void AutoclickRingHandler::StartAnimation(base::TimeDelta delay) { | 204 void AutoclickRingHandler::StartAnimation(base::TimeDelta delay) { |
249 int delay_ms = int{delay.InMilliseconds()}; | 205 int delay_ms = static_cast<int>(delay.InMilliseconds()); |
250 switch (current_animation_type_) { | 206 switch (current_animation_type_) { |
251 case AnimationType::GROW_ANIMATION: { | 207 case AnimationType::GROW_ANIMATION: { |
252 aura::Window* root_window = tap_down_target_->GetRootWindow(); | 208 view_.reset(new AutoclickRingView(tap_down_location_, ring_widget_)); |
253 view_.reset(new AutoclickRingView(tap_down_location_, root_window)); | |
254 SetDuration(delay_ms); | 209 SetDuration(delay_ms); |
255 Start(); | 210 Start(); |
256 break; | 211 break; |
257 } | 212 } |
258 case AnimationType::SHRINK_ANIMATION: { | 213 case AnimationType::SHRINK_ANIMATION: { |
259 aura::Window* root_window = tap_down_target_->GetRootWindow(); | 214 view_.reset(new AutoclickRingView(tap_down_location_, ring_widget_)); |
260 view_.reset(new AutoclickRingView(tap_down_location_, root_window)); | |
261 SetDuration(delay_ms); | 215 SetDuration(delay_ms); |
262 Start(); | 216 Start(); |
263 break; | 217 break; |
264 } | 218 } |
265 case AnimationType::NONE: | 219 case AnimationType::NONE: |
266 NOTREACHED(); | 220 NOTREACHED(); |
267 break; | 221 break; |
268 } | 222 } |
269 } | 223 } |
270 | 224 |
271 void AutoclickRingHandler::StopAutoclickRing() { | 225 void AutoclickRingHandler::StopAutoclickRing() { |
272 // Since, Animation::Stop() calls AnimationStopped(), we need to reset the | 226 // Since, Animation::Stop() calls AnimationStopped(), we need to reset the |
273 // |current_animation_type_| before Stop(), otherwise AnimationStopped() may | 227 // |current_animation_type_| before Stop(), otherwise AnimationStopped() may |
274 // start the timer again. | 228 // start the timer again. |
275 current_animation_type_ = AnimationType::NONE; | 229 current_animation_type_ = AnimationType::NONE; |
276 Stop(); | 230 Stop(); |
277 view_.reset(); | 231 view_.reset(); |
278 SetTapDownTarget(nullptr); | |
279 } | |
280 | |
281 void AutoclickRingHandler::SetTapDownTarget(aura::Window* target) { | |
282 if (tap_down_target_ == target) | |
283 return; | |
284 | |
285 if (tap_down_target_) | |
286 tap_down_target_->RemoveObserver(this); | |
287 tap_down_target_ = target; | |
288 if (tap_down_target_) | |
289 tap_down_target_->AddObserver(this); | |
290 } | 232 } |
291 | 233 |
292 void AutoclickRingHandler::AnimateToState(double state) { | 234 void AutoclickRingHandler::AnimateToState(double state) { |
293 DCHECK(view_.get()); | 235 DCHECK(view_.get()); |
294 switch (current_animation_type_) { | 236 switch (current_animation_type_) { |
295 case AnimationType::GROW_ANIMATION: | 237 case AnimationType::GROW_ANIMATION: |
296 view_->SetNewLocation(tap_down_location_, GetTargetWindow()); | 238 view_->SetNewLocation(tap_down_location_); |
297 view_->UpdateWithGrowAnimation(this); | 239 view_->UpdateWithGrowAnimation(this); |
298 break; | 240 break; |
299 case AnimationType::SHRINK_ANIMATION: | 241 case AnimationType::SHRINK_ANIMATION: |
300 view_->SetNewLocation(tap_down_location_, GetTargetWindow()); | 242 view_->SetNewLocation(tap_down_location_); |
301 view_->UpdateWithShrinkAnimation(this); | 243 view_->UpdateWithShrinkAnimation(this); |
302 break; | 244 break; |
303 case AnimationType::NONE: | 245 case AnimationType::NONE: |
304 NOTREACHED(); | 246 NOTREACHED(); |
305 break; | 247 break; |
306 } | 248 } |
307 } | 249 } |
308 | 250 |
309 void AutoclickRingHandler::AnimationStopped() { | 251 void AutoclickRingHandler::AnimationStopped() { |
310 switch (current_animation_type_) { | 252 switch (current_animation_type_) { |
311 case AnimationType::GROW_ANIMATION: | 253 case AnimationType::GROW_ANIMATION: |
312 current_animation_type_ = AnimationType::SHRINK_ANIMATION; | 254 current_animation_type_ = AnimationType::SHRINK_ANIMATION; |
313 StartAnimation(animation_duration_); | 255 StartAnimation(animation_duration_); |
314 break; | 256 break; |
315 case AnimationType::SHRINK_ANIMATION: | 257 case AnimationType::SHRINK_ANIMATION: |
316 current_animation_type_ = AnimationType::NONE; | 258 current_animation_type_ = AnimationType::NONE; |
317 break; | 259 break; |
318 case AnimationType::NONE: | 260 case AnimationType::NONE: |
319 // fall through to reset the view. | 261 // fall through to reset the view. |
320 view_.reset(); | 262 view_.reset(); |
321 SetTapDownTarget(nullptr); | |
322 break; | 263 break; |
323 } | 264 } |
324 } | 265 } |
325 | 266 |
326 void AutoclickRingHandler::OnWindowDestroying(aura::Window* window) { | 267 } // namespace ash |
327 DCHECK_EQ(tap_down_target_, window); | |
328 StopAutoclickRing(); | |
329 } | |
330 | |
331 } // namespace chromeos | |
OLD | NEW |