Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(565)

Unified Diff: content/browser/renderer_host/input/touch_handle.cc

Issue 335943002: [Android] Composited selection handle rendering (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@input_native_handles_final
Patch Set: Rebase Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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..63b6d961b1b66036533977a78d407304c3d7ec84
--- /dev/null
+++ b/content/browser/renderer_host/input/touch_handle.cc
@@ -0,0 +1,208 @@
+// 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),
+ enabled_(true),
+ is_visible_(false),
+ is_dragging_(false) {
+ DCHECK_NE(orientation, TOUCH_HANDLE_ORIENTATION_UNDEFINED);
+ drawable_->SetEnabled(enabled_);
+ drawable_->SetOrientation(orientation_);
+ drawable_->SetAlpha(alpha_);
+ drawable_->SetVisible(is_visible_);
+ drawable_->SetFocus(position_);
+}
+
+TouchHandle::~TouchHandle() {
+}
+
+void TouchHandle::SetEnabled(bool enabled) {
+ if (enabled_ == enabled)
+ return;
+ enabled_ = enabled;
+ drawable_->SetEnabled(enabled);
+ if (!enabled_) {
+ EndFade();
cjhopman 2014/07/14 18:23:52 I think that, since EndDrag() can trigger a fade,
jdduke (slow) 2014/07/15 15:44:24 You're absolutely right, I've been running tests l
+ EndDrag();
+ }
+}
+
+void TouchHandle::SetVisible(bool visible, AnimationStyle animation_style) {
+ if (is_visible_ == visible)
+ return;
+ is_visible_ = visible;
+ if (!enabled_ || animation_style == ANIMATION_NONE) {
+ EndFade();
+ } else {
+ // The fade will be rescheduled once dragging completes.
+ if (!is_dragging_)
+ BeginFade();
+ }
+}
+
+void TouchHandle::SetPosition(const gfx::PointF& position) {
+ if (position_ == position)
+ return;
+ position_ = position;
+ // Suppress repositioning a handle while invisible or fading to prevent it
+ // from "ghosting" outside the visible bounds. The position will be pushed to
+ // the drawable when the handle regains visibility (see |{Begin|End}Fade|).
cjhopman 2014/07/14 18:23:52 For handling the deferred position while invisible
jdduke (slow) 2014/07/15 15:44:24 That would be a better place, but we still need th
+ if (is_visible_)
cjhopman 2014/07/14 18:23:52 This allows changing the position while fading in
jdduke (slow) 2014/07/15 15:44:24 Hmm, yeah we only want to defer while fading *out*
+ 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);
+}
+
+bool TouchHandle::WillHandleTouchEvent(const ui::MotionEvent& event) {
+ if (!enabled_)
+ return false;
+
+ 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) {
+ EndFade();
+ return false;
+ }
+
+ return true;
+}
+
+void TouchHandle::BeginDrag() {
+ DCHECK(enabled_);
+ 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_);
+
+ BeginFade();
+}
+
+void TouchHandle::BeginFade() {
+ DCHECK(enabled_);
+
+ if (is_visible_)
+ drawable_->SetFocus(position_);
+
+ 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::EndFade() {
+ if (is_visible_)
+ drawable_->SetFocus(position_);
+
+ fade_end_time_ = base::TimeTicks();
+ SetAlpha(is_visible_ ? 1.f : 0.f);
+ drawable_->SetVisible(is_visible_);
+}
+
+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

Powered by Google App Engine
This is Rietveld 408576698