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" | 16 #include "ui/views/widget/widget.h" |
27 #include "ui/wm/core/coordinate_conversion.h" | |
28 | 17 |
29 namespace chromeos { | 18 namespace ash { |
30 namespace { | 19 namespace { |
31 | 20 |
32 const int kAutoclickRingOuterRadius = 30; | 21 const int kAutoclickRingOuterRadius = 30; |
33 const int kAutoclickRingInnerRadius = 20; | 22 const int kAutoclickRingInnerRadius = 20; |
34 | 23 |
35 // Angles from x-axis at which the outer and inner circles start. | 24 // Angles from x-axis at which the outer and inner circles start. |
36 const int kAutoclickRingInnerStartAngle = -90; | 25 const int kAutoclickRingInnerStartAngle = -90; |
37 | 26 |
38 const int kAutoclickRingGlowWidth = 20; | 27 const int kAutoclickRingGlowWidth = 20; |
39 // The following is half width to avoid division by 2. | 28 // The following is half width to avoid division by 2. |
40 const int kAutoclickRingArcWidth = 2; | 29 const int kAutoclickRingArcWidth = 2; |
41 | 30 |
42 // Start and end values for various animations. | 31 // Start and end values for various animations. |
43 const double kAutoclickRingScaleStartValue = 1.0; | 32 const double kAutoclickRingScaleStartValue = 1.0; |
44 const double kAutoclickRingScaleEndValue = 1.0; | 33 const double kAutoclickRingScaleEndValue = 1.0; |
45 const double kAutoclickRingShrinkScaleEndValue = 0.5; | 34 const double kAutoclickRingShrinkScaleEndValue = 0.5; |
46 | 35 |
47 const double kAutoclickRingOpacityStartValue = 0.1; | 36 const double kAutoclickRingOpacityStartValue = 0.1; |
48 const double kAutoclickRingOpacityEndValue = 0.5; | 37 const double kAutoclickRingOpacityEndValue = 0.5; |
49 const int kAutoclickRingAngleStartValue = -90; | 38 const int kAutoclickRingAngleStartValue = -90; |
50 // The sweep angle is a bit greater than 360 to make sure the circle | 39 // The sweep angle is a bit greater than 360 to make sure the circle |
51 // completes at the end of the animation. | 40 // completes at the end of the animation. |
52 const int kAutoclickRingAngleEndValue = 360; | 41 const int kAutoclickRingAngleEndValue = 360; |
53 | 42 |
54 // Visual constants. | 43 // Visual constants. |
55 const SkColor kAutoclickRingArcColor = SkColorSetARGB(255, 0, 255, 0); | 44 const SkColor kAutoclickRingArcColor = SkColorSetARGB(255, 0, 255, 0); |
56 const SkColor kAutoclickRingCircleColor = SkColorSetARGB(255, 0, 0, 255); | 45 const SkColor kAutoclickRingCircleColor = SkColorSetARGB(255, 0, 0, 255); |
57 const int kAutoclickRingFrameRateHz = 60; | 46 const int kAutoclickRingFrameRateHz = 60; |
58 | 47 |
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, | 48 void PaintAutoclickRingCircle(gfx::Canvas* canvas, |
77 gfx::Point& center, | 49 gfx::Point& center, |
78 int radius) { | 50 int radius) { |
79 SkPaint paint; | 51 SkPaint paint; |
80 paint.setStyle(SkPaint::kStroke_Style); | 52 paint.setStyle(SkPaint::kStroke_Style); |
81 paint.setStrokeWidth(2 * kAutoclickRingArcWidth); | 53 paint.setStrokeWidth(2 * kAutoclickRingArcWidth); |
82 paint.setColor(kAutoclickRingCircleColor); | 54 paint.setColor(kAutoclickRingCircleColor); |
83 paint.setAntiAlias(true); | 55 paint.setAntiAlias(true); |
84 | 56 |
85 canvas->DrawCircle(center, radius, paint); | 57 canvas->DrawCircle(center, radius, paint); |
(...skipping 16 matching lines...) Expand all Loading... |
102 start_angle, end_angle - start_angle); | 74 start_angle, end_angle - start_angle); |
103 canvas->DrawPath(arc_path, paint); | 75 canvas->DrawPath(arc_path, paint); |
104 } | 76 } |
105 } // namespace | 77 } // namespace |
106 | 78 |
107 // View of the AutoclickRingHandler. Draws the actual contents and updates as | 79 // View of the AutoclickRingHandler. Draws the actual contents and updates as |
108 // the animation proceeds. It also maintains the views::Widget that the | 80 // the animation proceeds. It also maintains the views::Widget that the |
109 // animation is shown in. | 81 // animation is shown in. |
110 class AutoclickRingHandler::AutoclickRingView : public views::View { | 82 class AutoclickRingHandler::AutoclickRingView : public views::View { |
111 public: | 83 public: |
112 AutoclickRingView(const gfx::Point& event_location, aura::Window* root_window) | 84 AutoclickRingView(const gfx::Point& event_location, |
| 85 views::Widget* ring_widget) |
113 : views::View(), | 86 : views::View(), |
114 widget_(CreateAutoclickRingWidget(root_window)), | 87 widget_(ring_widget), |
115 current_angle_(kAutoclickRingAngleStartValue), | 88 current_angle_(kAutoclickRingAngleStartValue), |
116 current_scale_(kAutoclickRingScaleStartValue) { | 89 current_scale_(kAutoclickRingScaleStartValue) { |
117 widget_->SetContentsView(this); | 90 widget_->SetContentsView(this); |
118 | 91 |
119 // We are owned by the AutoclickRingHandler. | 92 // We are owned by the AutoclickRingHandler. |
120 set_owned_by_client(); | 93 set_owned_by_client(); |
121 SetNewLocation(event_location, root_window); | 94 SetNewLocation(event_location); |
122 } | 95 } |
123 | 96 |
124 ~AutoclickRingView() override {} | 97 ~AutoclickRingView() override {} |
125 | 98 |
126 void SetNewLocation(const gfx::Point& new_event_location, | 99 void SetNewLocation(const gfx::Point& new_event_location) { |
127 aura::Window* root_window) { | |
128 gfx::Point point = new_event_location; | 100 gfx::Point point = new_event_location; |
129 widget_->SetBounds(gfx::Rect( | 101 widget_->SetBounds(gfx::Rect( |
130 point.x() - (kAutoclickRingOuterRadius + kAutoclickRingGlowWidth), | 102 point.x() - (kAutoclickRingOuterRadius + kAutoclickRingGlowWidth), |
131 point.y() - (kAutoclickRingOuterRadius + kAutoclickRingGlowWidth), | 103 point.y() - (kAutoclickRingOuterRadius + kAutoclickRingGlowWidth), |
132 GetPreferredSize().width(), GetPreferredSize().height())); | 104 GetPreferredSize().width(), GetPreferredSize().height())); |
133 widget_->Show(); | 105 widget_->Show(); |
134 widget_->GetNativeView()->layer()->SetOpacity( | 106 widget_->GetNativeView()->layer()->SetOpacity( |
135 kAutoclickRingOpacityStartValue); | 107 kAutoclickRingOpacityStartValue); |
136 } | 108 } |
137 | 109 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
191 double current_scale_; | 163 double current_scale_; |
192 | 164 |
193 DISALLOW_COPY_AND_ASSIGN(AutoclickRingView); | 165 DISALLOW_COPY_AND_ASSIGN(AutoclickRingView); |
194 }; | 166 }; |
195 | 167 |
196 //////////////////////////////////////////////////////////////////////////////// | 168 //////////////////////////////////////////////////////////////////////////////// |
197 | 169 |
198 // AutoclickRingHandler, public | 170 // AutoclickRingHandler, public |
199 AutoclickRingHandler::AutoclickRingHandler() | 171 AutoclickRingHandler::AutoclickRingHandler() |
200 : gfx::LinearAnimation(kAutoclickRingFrameRateHz, nullptr), | 172 : gfx::LinearAnimation(kAutoclickRingFrameRateHz, nullptr), |
| 173 ring_widget_(nullptr), |
201 tap_down_target_(nullptr), | 174 tap_down_target_(nullptr), |
202 current_animation_type_(AnimationType::NONE) {} | 175 current_animation_type_(AnimationType::NONE) {} |
203 | 176 |
204 AutoclickRingHandler::~AutoclickRingHandler() { | 177 AutoclickRingHandler::~AutoclickRingHandler() { |
205 StopAutoclickRing(); | 178 StopAutoclickRing(); |
206 } | 179 } |
207 | 180 |
208 void AutoclickRingHandler::StartGesture( | 181 void AutoclickRingHandler::StartGesture( |
209 base::TimeDelta duration, | 182 base::TimeDelta duration, |
210 const gfx::Point& center_point_in_screen) { | 183 const gfx::Point& center_point_in_screen, |
211 aura::Window* target = GetTargetWindow(); | 184 aura::Window* target, |
212 if (tap_down_target_ && tap_down_target_ != target) | 185 views::Widget* widget) { |
213 return; | |
214 StopAutoclickRing(); | 186 StopAutoclickRing(); |
215 SetTapDownTarget(); | |
216 tap_down_location_ = center_point_in_screen; | 187 tap_down_location_ = center_point_in_screen; |
| 188 SetTapDownTarget(target); |
| 189 ring_widget_ = widget; |
217 current_animation_type_ = AnimationType::GROW_ANIMATION; | 190 current_animation_type_ = AnimationType::GROW_ANIMATION; |
218 animation_duration_ = duration; | 191 animation_duration_ = duration; |
219 StartAnimation(base::TimeDelta()); | 192 StartAnimation(base::TimeDelta()); |
220 } | 193 } |
221 | 194 |
222 void AutoclickRingHandler::StopGesture() { | 195 void AutoclickRingHandler::StopGesture() { |
223 aura::Window* target = GetTargetWindow(); | |
224 if (tap_down_target_ && tap_down_target_ != target) | |
225 return; | |
226 StopAutoclickRing(); | 196 StopAutoclickRing(); |
227 } | 197 } |
228 | 198 |
229 void AutoclickRingHandler::SetGestureCenter( | 199 void AutoclickRingHandler::SetGestureCenter( |
230 const gfx::Point& center_point_in_screen) { | 200 const gfx::Point& center_point_in_screen, |
| 201 aura::Window* target, |
| 202 views::Widget* widget) { |
231 tap_down_location_ = center_point_in_screen; | 203 tap_down_location_ = center_point_in_screen; |
| 204 SetTapDownTarget(target); |
| 205 ring_widget_ = widget; |
232 } | 206 } |
233 //////////////////////////////////////////////////////////////////////////////// | 207 //////////////////////////////////////////////////////////////////////////////// |
234 | 208 |
235 // AutoclickRingHandler, private | 209 // 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) { | 210 void AutoclickRingHandler::StartAnimation(base::TimeDelta delay) { |
249 int delay_ms = int{delay.InMilliseconds()}; | 211 int delay_ms = int{delay.InMilliseconds()}; |
250 switch (current_animation_type_) { | 212 switch (current_animation_type_) { |
251 case AnimationType::GROW_ANIMATION: { | 213 case AnimationType::GROW_ANIMATION: { |
252 aura::Window* root_window = tap_down_target_->GetRootWindow(); | 214 view_.reset(new AutoclickRingView(tap_down_location_, ring_widget_)); |
253 view_.reset(new AutoclickRingView(tap_down_location_, root_window)); | |
254 SetDuration(delay_ms); | 215 SetDuration(delay_ms); |
255 Start(); | 216 Start(); |
256 break; | 217 break; |
257 } | 218 } |
258 case AnimationType::SHRINK_ANIMATION: { | 219 case AnimationType::SHRINK_ANIMATION: { |
259 aura::Window* root_window = tap_down_target_->GetRootWindow(); | 220 view_.reset(new AutoclickRingView(tap_down_location_, ring_widget_)); |
260 view_.reset(new AutoclickRingView(tap_down_location_, root_window)); | |
261 SetDuration(delay_ms); | 221 SetDuration(delay_ms); |
262 Start(); | 222 Start(); |
263 break; | 223 break; |
264 } | 224 } |
265 case AnimationType::NONE: | 225 case AnimationType::NONE: |
266 NOTREACHED(); | 226 NOTREACHED(); |
267 break; | 227 break; |
268 } | 228 } |
269 } | 229 } |
270 | 230 |
(...skipping 15 matching lines...) Expand all Loading... |
286 tap_down_target_->RemoveObserver(this); | 246 tap_down_target_->RemoveObserver(this); |
287 tap_down_target_ = target; | 247 tap_down_target_ = target; |
288 if (tap_down_target_) | 248 if (tap_down_target_) |
289 tap_down_target_->AddObserver(this); | 249 tap_down_target_->AddObserver(this); |
290 } | 250 } |
291 | 251 |
292 void AutoclickRingHandler::AnimateToState(double state) { | 252 void AutoclickRingHandler::AnimateToState(double state) { |
293 DCHECK(view_.get()); | 253 DCHECK(view_.get()); |
294 switch (current_animation_type_) { | 254 switch (current_animation_type_) { |
295 case AnimationType::GROW_ANIMATION: | 255 case AnimationType::GROW_ANIMATION: |
296 view_->SetNewLocation(tap_down_location_, GetTargetWindow()); | 256 view_->SetNewLocation(tap_down_location_); |
297 view_->UpdateWithGrowAnimation(this); | 257 view_->UpdateWithGrowAnimation(this); |
298 break; | 258 break; |
299 case AnimationType::SHRINK_ANIMATION: | 259 case AnimationType::SHRINK_ANIMATION: |
300 view_->SetNewLocation(tap_down_location_, GetTargetWindow()); | 260 view_->SetNewLocation(tap_down_location_); |
301 view_->UpdateWithShrinkAnimation(this); | 261 view_->UpdateWithShrinkAnimation(this); |
302 break; | 262 break; |
303 case AnimationType::NONE: | 263 case AnimationType::NONE: |
304 NOTREACHED(); | 264 NOTREACHED(); |
305 break; | 265 break; |
306 } | 266 } |
307 } | 267 } |
308 | 268 |
309 void AutoclickRingHandler::AnimationStopped() { | 269 void AutoclickRingHandler::AnimationStopped() { |
310 switch (current_animation_type_) { | 270 switch (current_animation_type_) { |
(...skipping 10 matching lines...) Expand all Loading... |
321 SetTapDownTarget(nullptr); | 281 SetTapDownTarget(nullptr); |
322 break; | 282 break; |
323 } | 283 } |
324 } | 284 } |
325 | 285 |
326 void AutoclickRingHandler::OnWindowDestroying(aura::Window* window) { | 286 void AutoclickRingHandler::OnWindowDestroying(aura::Window* window) { |
327 DCHECK_EQ(tap_down_target_, window); | 287 DCHECK_EQ(tap_down_target_, window); |
328 StopAutoclickRing(); | 288 StopAutoclickRing(); |
329 } | 289 } |
330 | 290 |
331 } // namespace chromeos | 291 } // namespace ash |
OLD | NEW |