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

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: Tweaks to dragging and visibility 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..193812b36f73d317a482aed0072dbbde868520c2
--- /dev/null
+++ b/content/browser/renderer_host/input/touch_handle.cc
@@ -0,0 +1,217 @@
+// 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),
+ animate_deferred_fade_(false),
+ 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;
+ if (!enabled) {
+ EndDrag();
+ EndFade();
+ }
+ enabled_ = enabled;
+ drawable_->SetEnabled(enabled);
+}
+
+void TouchHandle::SetVisible(bool visible, AnimationStyle animation_style) {
+ if (is_visible_ == visible)
+ return;
+
+ is_visible_ = visible;
+
+ // Handle repositioning may have been deferred while previously invisible.
+ if (visible)
+ drawable_->SetFocus(position_);
+
+ bool animate = animation_style != ANIMATION_NONE;
+ if (is_dragging_) {
+ animate_deferred_fade_ = animate;
+ return;
+ }
+
+ if (enabled_ && animate)
+ BeginFade();
+ else
+ EndFade();
+}
+
+void TouchHandle::SetPosition(const gfx::PointF& position) {
+ if (position_ == position)
+ return;
+ position_ = position;
+ // Suppress repositioning a handle while invisible or fading out to prevent it
+ // from "ghosting" outside the visible bounds. The position will be pushed to
+ // the drawable when the handle regains visibility (see |SetVisible()|).
+ if (is_visible_)
+ 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;
cjhopman 2014/07/15 18:40:28 If you reset deferred_orientation in whatever call
jdduke (slow) 2014/07/15 21:51:56 Done.
+ 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();
cjhopman 2014/07/15 18:40:28 The handle could be fading in at this point. It's
jdduke (slow) 2014/07/15 21:51:56 Done.
+ } 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))
cjhopman 2014/07/15 18:40:28 Should we delay dragging during this period? Delay
jdduke (slow) 2014/07/15 21:51:56 Well, we really ought to be using a proper touch s
+ 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_);
+
+ // As a fade may have been deferred while dragging, trigger now if necessary.
+ if (enabled_ && animate_deferred_fade_)
+ BeginFade();
+ else
+ EndFade();
+}
+
+void TouchHandle::BeginFade() {
+ DCHECK(enabled_);
+ animate_deferred_fade_ = false;
+ const float target_alpha = is_visible_ ? 1.f : 0.f;
+ if (target_alpha == alpha_)
cjhopman 2014/07/15 18:40:28 If the handle is visible and I do fade out immedia
jdduke (slow) 2014/07/15 21:51:56 I'll terminate the fade here if (target_alpha == a
+ return;
+
+ drawable_->SetVisible(true);
+ fade_end_time_ = base::TimeTicks::Now() +
+ base::TimeDelta::FromMillisecondsD(
+ kFadeDurationMs * std::abs(target_alpha - alpha_));
cjhopman 2014/07/15 18:40:28 If i fade out a handle, then reposition it, then f
jdduke (slow) 2014/07/15 21:51:56 Hmm, preserving the fade alpha is somewhat desirab
+ fade_start_position_ = position_;
+ client_->SetNeedsAnimate();
+}
+
+void TouchHandle::EndFade() {
+ animate_deferred_fade_ = false;
+ 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
« no previous file with comments | « content/browser/renderer_host/input/touch_handle.h ('k') | content/browser/renderer_host/input/touch_handle_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698