Chromium Code Reviews| Index: content/browser/renderer_host/input/touch_handle.cc |
| diff --git a/content/browser/renderer_host/input/touch_handle.cc b/content/browser/renderer_host/input/touch_handle.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..46aad50bf8a1375645bf1699aa47b1deee87f556 |
| --- /dev/null |
| +++ b/content/browser/renderer_host/input/touch_handle.cc |
| @@ -0,0 +1,191 @@ |
| +// Copyright 2014 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "content/browser/renderer_host/input/touch_handle.h" |
| + |
| +namespace content { |
| + |
| +namespace { |
| + |
| +// Maximum duration of a fade sequence. |
| +const double kFadeDurationMs = 200; |
| + |
| +// Maximum amount of travel for a fade sequence. This avoids handle "ghosting" |
| +// when the handle is moving rapidly while the fade is active. |
| +const double kFadeDistanceSquared = 20.f * 20.f; |
| + |
| +} // namespace |
| + |
| +// Responsible for rendering a selection or insertion handle for text editing. |
| +TouchHandle::TouchHandle(TouchHandleClient* client, |
| + TouchHandleOrientation orientation) |
| + : drawable_(client->CreateDrawable()), |
| + client_(client), |
| + orientation_(orientation), |
| + deferred_orientation_(TOUCH_HANDLE_ORIENTATION_UNDEFINED), |
| + alpha_(0.f), |
| + is_visible_(false), |
| + is_dragging_(false) { |
| + DCHECK_NE(orientation, TOUCH_HANDLE_ORIENTATION_UNDEFINED); |
| + drawable_->SetOrientation(orientation_); |
|
cjhopman
2014/07/09 22:29:12
Should these initial values be arguments to client
jdduke (slow)
2014/07/10 02:08:39
I'll push through the position_ for completeness.
|
| + drawable_->SetAlpha(alpha_); |
| + drawable_->SetVisible(is_visible_); |
| +} |
| + |
| +TouchHandle::~TouchHandle() { |
| +} |
| + |
| +void TouchHandle::SetVisible(bool visible, AnimationStyle animation_style) { |
| + if (is_visible_ == visible) |
| + return; |
| + is_visible_ = visible; |
| + if (animation_style == ANIMATION_NONE) { |
| + drawable_->SetVisible(visible); |
| + CancelFade(); |
| + } else { |
| + // The fade will be rescheduled once dragging completes. |
| + if (!is_dragging_) |
| + ScheduleFade(); |
| + } |
| +} |
| + |
| +void TouchHandle::SetPosition(const gfx::PointF& position) { |
| + if (position_ == position) |
| + return; |
| + position_ = position; |
| + // Avoid positioning handles outside their visible bounds during a fade. |
| + if (!fade_end_time_.is_null() && !is_visible_) |
| + return; |
| + drawable_->SetFocus(position_); |
| +} |
| + |
| +void TouchHandle::SetOrientation(TouchHandleOrientation orientation) { |
| + DCHECK_NE(orientation, TOUCH_HANDLE_ORIENTATION_UNDEFINED); |
| + if (is_dragging_) { |
| + deferred_orientation_ = orientation; |
| + return; |
| + } |
| + |
| + deferred_orientation_ = TOUCH_HANDLE_ORIENTATION_UNDEFINED; |
| + |
| + if (orientation_ == orientation) |
| + return; |
| + |
| + orientation_ = orientation; |
| + drawable_->SetOrientation(orientation); |
| +} |
| + |
| +void TouchHandle::Hide() { |
| + SetVisible(false, ANIMATION_NONE); |
| + CancelFade(); |
| + is_dragging_ = false; |
| +} |
| + |
| +bool TouchHandle::WillHandleTouchEvent(const ui::MotionEvent& event) { |
| + if (!is_dragging_ && event.GetAction() != ui::MotionEvent::ACTION_DOWN) |
| + return false; |
| + |
| + switch (event.GetAction()) { |
| + case ui::MotionEvent::ACTION_DOWN: { |
| + gfx::PointF touch_position = gfx::PointF(event.GetX(), event.GetY()); |
| + if (!is_visible_ || !drawable_->ContainsPoint(touch_position)) |
| + return false; |
| + touch_down_position_ = touch_position; |
| + touch_to_focus_offset_ = position_ - touch_down_position_; |
| + touch_down_time_ = event.GetEventTime(); |
| + BeginDrag(); |
| + } break; |
| + |
| + case ui::MotionEvent::ACTION_MOVE: { |
| + gfx::PointF new_position = |
| + gfx::PointF(event.GetX(), event.GetY()) + touch_to_focus_offset_; |
| + client_->OnHandleDragUpdate(*this, new_position); |
| + } break; |
| + |
| + case ui::MotionEvent::ACTION_UP: { |
| + base::TimeDelta delay = event.GetEventTime() - touch_down_time_; |
| + if (delay < base::TimeDelta::FromMilliseconds(180)) |
| + client_->OnHandleTapped(*this); |
| + |
| + EndDrag(); |
| + } break; |
| + |
| + case ui::MotionEvent::ACTION_CANCEL: |
| + EndDrag(); |
| + break; |
| + |
| + default: |
| + break; |
| + }; |
| + return true; |
| +} |
| + |
| +bool TouchHandle::Animate(base::TimeTicks frame_time) { |
| + if (fade_end_time_ == base::TimeTicks()) |
| + return false; |
| + |
| + float time_u = |
| + 1.f - (fade_end_time_ - frame_time).InMillisecondsF() / kFadeDurationMs; |
| + float position_u = |
| + (position_ - fade_start_position_).LengthSquared() / kFadeDistanceSquared; |
| + float u = std::max(time_u, position_u); |
| + SetAlpha(is_visible_ ? u : 1.f - u); |
| + |
| + if (u >= 1.f) { |
| + CancelFade(); |
| + return false; |
| + } |
| + |
| + return true; |
| +} |
| + |
| +void TouchHandle::BeginDrag() { |
| + if (is_dragging_) |
| + return; |
| + is_dragging_ = true; |
| + client_->OnHandleDragBegin(*this); |
| +} |
| + |
| +void TouchHandle::EndDrag() { |
| + if (!is_dragging_) |
| + return; |
| + |
| + is_dragging_ = false; |
| + client_->OnHandleDragEnd(*this); |
| + |
| + if (deferred_orientation_ != TOUCH_HANDLE_ORIENTATION_UNDEFINED) |
| + SetOrientation(deferred_orientation_); |
| + |
| + ScheduleFade(); |
| +} |
| + |
| +void TouchHandle::ScheduleFade() { |
| + const float target_alpha = is_visible_ ? 1.f : 0.f; |
| + if (target_alpha == alpha_) |
| + return; |
| + |
| + drawable_->SetVisible(true); |
| + fade_end_time_ = base::TimeTicks::Now() + |
| + base::TimeDelta::FromMillisecondsD( |
| + kFadeDurationMs * std::abs(target_alpha - alpha_)); |
| + fade_start_position_ = position_; |
| + client_->SetNeedsAnimate(); |
| +} |
| + |
| +void TouchHandle::CancelFade() { |
| + fade_end_time_ = base::TimeTicks(); |
| + SetAlpha(is_visible_ ? 1.f : 0.f); |
| + drawable_->SetVisible(is_visible_); |
| + drawable_->SetFocus(position_); |
| +} |
| + |
| +void TouchHandle::SetAlpha(float alpha) { |
| + alpha = std::max(0.f, std::min(1.f, alpha)); |
| + if (alpha_ == alpha) |
| + return; |
| + alpha_ = alpha; |
| + drawable_->SetAlpha(alpha); |
| +} |
| + |
| +} // namespace content |