| 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 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 179 | 151 |
| 180 // Paint inner circle. | 152 // Paint inner circle. |
| 181 PaintAutoclickRingArc(canvas, center, kAutoclickRingInnerRadius, | 153 PaintAutoclickRingArc(canvas, center, kAutoclickRingInnerRadius, |
| 182 kAutoclickRingInnerStartAngle, current_angle_); | 154 kAutoclickRingInnerStartAngle, current_angle_); |
| 183 // Paint outer circle. | 155 // Paint outer circle. |
| 184 PaintAutoclickRingCircle(canvas, center, kAutoclickRingOuterRadius); | 156 PaintAutoclickRingCircle(canvas, center, kAutoclickRingOuterRadius); |
| 185 | 157 |
| 186 canvas->Restore(); | 158 canvas->Restore(); |
| 187 } | 159 } |
| 188 | 160 |
| 189 std::unique_ptr<views::Widget> widget_; | 161 views::Widget* widget_; |
| 190 int current_angle_; | 162 int current_angle_; |
| 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), |
| 201 tap_down_target_(nullptr), | 173 ring_widget_(nullptr), |
| 202 current_animation_type_(AnimationType::NONE) {} | 174 current_animation_type_(AnimationType::NONE) {} |
| 203 | 175 |
| 204 AutoclickRingHandler::~AutoclickRingHandler() { | 176 AutoclickRingHandler::~AutoclickRingHandler() { |
| 205 StopAutoclickRing(); | 177 StopAutoclickRing(); |
| 206 } | 178 } |
| 207 | 179 |
| 208 void AutoclickRingHandler::StartGesture( | 180 void AutoclickRingHandler::StartGesture( |
| 209 base::TimeDelta duration, | 181 base::TimeDelta duration, |
| 210 const gfx::Point& center_point_in_screen) { | 182 const gfx::Point& center_point_in_screen, |
| 211 aura::Window* target = GetTargetWindow(); | 183 views::Widget* widget) { |
| 212 if (tap_down_target_ && tap_down_target_ != target) | |
| 213 return; | |
| 214 StopAutoclickRing(); | 184 StopAutoclickRing(); |
| 215 SetTapDownTarget(); | |
| 216 tap_down_location_ = center_point_in_screen; | 185 tap_down_location_ = center_point_in_screen; |
| 186 ring_widget_ = widget; |
| 217 current_animation_type_ = AnimationType::GROW_ANIMATION; | 187 current_animation_type_ = AnimationType::GROW_ANIMATION; |
| 218 animation_duration_ = duration; | 188 animation_duration_ = duration; |
| 219 StartAnimation(base::TimeDelta()); | 189 StartAnimation(base::TimeDelta()); |
| 220 } | 190 } |
| 221 | 191 |
| 222 void AutoclickRingHandler::StopGesture() { | 192 void AutoclickRingHandler::StopGesture() { |
| 223 aura::Window* target = GetTargetWindow(); | |
| 224 if (tap_down_target_ && tap_down_target_ != target) | |
| 225 return; | |
| 226 StopAutoclickRing(); | 193 StopAutoclickRing(); |
| 227 } | 194 } |
| 228 | 195 |
| 229 void AutoclickRingHandler::SetGestureCenter( | 196 void AutoclickRingHandler::SetGestureCenter( |
| 230 const gfx::Point& center_point_in_screen) { | 197 const gfx::Point& center_point_in_screen, |
| 198 views::Widget* widget) { |
| 231 tap_down_location_ = center_point_in_screen; | 199 tap_down_location_ = center_point_in_screen; |
| 200 ring_widget_ = widget; |
| 232 } | 201 } |
| 233 //////////////////////////////////////////////////////////////////////////////// | 202 //////////////////////////////////////////////////////////////////////////////// |
| 234 | 203 |
| 235 // AutoclickRingHandler, private | 204 // 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) { | 205 void AutoclickRingHandler::StartAnimation(base::TimeDelta delay) { |
| 249 int delay_ms = int{delay.InMilliseconds()}; | 206 int delay_ms = int{delay.InMilliseconds()}; |
| 250 switch (current_animation_type_) { | 207 switch (current_animation_type_) { |
| 251 case AnimationType::GROW_ANIMATION: { | 208 case AnimationType::GROW_ANIMATION: { |
| 252 aura::Window* root_window = tap_down_target_->GetRootWindow(); | 209 view_.reset(new AutoclickRingView(tap_down_location_, ring_widget_)); |
| 253 view_.reset(new AutoclickRingView(tap_down_location_, root_window)); | |
| 254 SetDuration(delay_ms); | 210 SetDuration(delay_ms); |
| 255 Start(); | 211 Start(); |
| 256 break; | 212 break; |
| 257 } | 213 } |
| 258 case AnimationType::SHRINK_ANIMATION: { | 214 case AnimationType::SHRINK_ANIMATION: { |
| 259 aura::Window* root_window = tap_down_target_->GetRootWindow(); | 215 view_.reset(new AutoclickRingView(tap_down_location_, ring_widget_)); |
| 260 view_.reset(new AutoclickRingView(tap_down_location_, root_window)); | |
| 261 SetDuration(delay_ms); | 216 SetDuration(delay_ms); |
| 262 Start(); | 217 Start(); |
| 263 break; | 218 break; |
| 264 } | 219 } |
| 265 case AnimationType::NONE: | 220 case AnimationType::NONE: |
| 266 NOTREACHED(); | 221 NOTREACHED(); |
| 267 break; | 222 break; |
| 268 } | 223 } |
| 269 } | 224 } |
| 270 | 225 |
| 271 void AutoclickRingHandler::StopAutoclickRing() { | 226 void AutoclickRingHandler::StopAutoclickRing() { |
| 272 // Since, Animation::Stop() calls AnimationStopped(), we need to reset the | 227 // Since, Animation::Stop() calls AnimationStopped(), we need to reset the |
| 273 // |current_animation_type_| before Stop(), otherwise AnimationStopped() may | 228 // |current_animation_type_| before Stop(), otherwise AnimationStopped() may |
| 274 // start the timer again. | 229 // start the timer again. |
| 275 current_animation_type_ = AnimationType::NONE; | 230 current_animation_type_ = AnimationType::NONE; |
| 276 Stop(); | 231 Stop(); |
| 277 view_.reset(); | 232 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 } | 233 } |
| 291 | 234 |
| 292 void AutoclickRingHandler::AnimateToState(double state) { | 235 void AutoclickRingHandler::AnimateToState(double state) { |
| 293 DCHECK(view_.get()); | 236 DCHECK(view_.get()); |
| 294 switch (current_animation_type_) { | 237 switch (current_animation_type_) { |
| 295 case AnimationType::GROW_ANIMATION: | 238 case AnimationType::GROW_ANIMATION: |
| 296 view_->SetNewLocation(tap_down_location_, GetTargetWindow()); | 239 view_->SetNewLocation(tap_down_location_); |
| 297 view_->UpdateWithGrowAnimation(this); | 240 view_->UpdateWithGrowAnimation(this); |
| 298 break; | 241 break; |
| 299 case AnimationType::SHRINK_ANIMATION: | 242 case AnimationType::SHRINK_ANIMATION: |
| 300 view_->SetNewLocation(tap_down_location_, GetTargetWindow()); | 243 view_->SetNewLocation(tap_down_location_); |
| 301 view_->UpdateWithShrinkAnimation(this); | 244 view_->UpdateWithShrinkAnimation(this); |
| 302 break; | 245 break; |
| 303 case AnimationType::NONE: | 246 case AnimationType::NONE: |
| 304 NOTREACHED(); | 247 NOTREACHED(); |
| 305 break; | 248 break; |
| 306 } | 249 } |
| 307 } | 250 } |
| 308 | 251 |
| 309 void AutoclickRingHandler::AnimationStopped() { | 252 void AutoclickRingHandler::AnimationStopped() { |
| 310 switch (current_animation_type_) { | 253 switch (current_animation_type_) { |
| 311 case AnimationType::GROW_ANIMATION: | 254 case AnimationType::GROW_ANIMATION: |
| 312 current_animation_type_ = AnimationType::SHRINK_ANIMATION; | 255 current_animation_type_ = AnimationType::SHRINK_ANIMATION; |
| 313 StartAnimation(animation_duration_); | 256 StartAnimation(animation_duration_); |
| 314 break; | 257 break; |
| 315 case AnimationType::SHRINK_ANIMATION: | 258 case AnimationType::SHRINK_ANIMATION: |
| 316 current_animation_type_ = AnimationType::NONE; | 259 current_animation_type_ = AnimationType::NONE; |
| 317 break; | 260 break; |
| 318 case AnimationType::NONE: | 261 case AnimationType::NONE: |
| 319 // fall through to reset the view. | 262 // fall through to reset the view. |
| 320 view_.reset(); | 263 view_.reset(); |
| 321 SetTapDownTarget(nullptr); | |
| 322 break; | 264 break; |
| 323 } | 265 } |
| 324 } | 266 } |
| 325 | 267 |
| 326 void AutoclickRingHandler::OnWindowDestroying(aura::Window* window) { | 268 } // namespace ash |
| 327 DCHECK_EQ(tap_down_target_, window); | |
| 328 StopAutoclickRing(); | |
| 329 } | |
| 330 | |
| 331 } // namespace chromeos | |
| OLD | NEW |