15f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// found in the LICENSE file.
45f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
55f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/renderer_host/input/touch_handle.h"
65f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
75f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <cmath>
85f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
95f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)namespace content {
105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)namespace {
125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Maximum duration of a fade sequence.
145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const double kFadeDurationMs = 200;
155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Maximum amount of travel for a fade sequence. This avoids handle "ghosting"
175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// when the handle is moving rapidly while the fade is active.
185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const double kFadeDistanceSquared = 20.f * 20.f;
195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// Avoid using an empty touch rect, as it may fail the intersection test event
216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// if it lies within the other rect's bounds.
226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)const float kMinTouchMajorForHitTesting = 1.f;
236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// The maximum touch size to use when computing whether a touch point is
255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// targetting a touch handle. This is necessary for devices that misreport
265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// touch radii, preventing inappropriately largely touch sizes from completely
275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// breaking handle dragging behavior.
286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)const float kMaxTouchMajorForHitTesting = 36.f;
295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}  // namespace
315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Responsible for rendering a selection or insertion handle for text editing.
335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)TouchHandle::TouchHandle(TouchHandleClient* client,
345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                         TouchHandleOrientation orientation)
355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    : drawable_(client->CreateDrawable()),
365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      client_(client),
375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      orientation_(orientation),
385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      deferred_orientation_(TOUCH_HANDLE_ORIENTATION_UNDEFINED),
395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      alpha_(0.f),
405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      animate_deferred_fade_(false),
415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      enabled_(true),
425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      is_visible_(false),
431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      is_dragging_(false),
441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      is_drag_within_tap_region_(false) {
455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK_NE(orientation, TOUCH_HANDLE_ORIENTATION_UNDEFINED);
465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  drawable_->SetEnabled(enabled_);
475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  drawable_->SetOrientation(orientation_);
485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  drawable_->SetAlpha(alpha_);
495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  drawable_->SetVisible(is_visible_);
505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  drawable_->SetFocus(position_);
515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)TouchHandle::~TouchHandle() {
545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void TouchHandle::SetEnabled(bool enabled) {
575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (enabled_ == enabled)
585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!enabled) {
605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    EndDrag();
615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    EndFade();
625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  enabled_ = enabled;
645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  drawable_->SetEnabled(enabled);
655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void TouchHandle::SetVisible(bool visible, AnimationStyle animation_style) {
685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(enabled_);
695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (is_visible_ == visible)
705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  is_visible_ = visible;
735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Handle repositioning may have been deferred while previously invisible.
755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (visible)
765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    drawable_->SetFocus(position_);
775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  bool animate = animation_style != ANIMATION_NONE;
795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (is_dragging_) {
805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    animate_deferred_fade_ = animate;
815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (animate)
855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    BeginFade();
865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  else
875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    EndFade();
885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void TouchHandle::SetPosition(const gfx::PointF& position) {
915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(enabled_);
925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (position_ == position)
935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  position_ = position;
955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Suppress repositioning a handle while invisible or fading out to prevent it
965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // from "ghosting" outside the visible bounds. The position will be pushed to
975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // the drawable when the handle regains visibility (see |SetVisible()|).
985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (is_visible_)
995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    drawable_->SetFocus(position_);
1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void TouchHandle::SetOrientation(TouchHandleOrientation orientation) {
1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(enabled_);
1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK_NE(orientation, TOUCH_HANDLE_ORIENTATION_UNDEFINED);
1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (is_dragging_) {
1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    deferred_orientation_ = orientation;
1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK_EQ(deferred_orientation_, TOUCH_HANDLE_ORIENTATION_UNDEFINED);
1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (orientation_ == orientation)
1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  orientation_ = orientation;
1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  drawable_->SetOrientation(orientation);
1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool TouchHandle::WillHandleTouchEvent(const ui::MotionEvent& event) {
1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!enabled_)
1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return false;
1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!is_dragging_ && event.GetAction() != ui::MotionEvent::ACTION_DOWN)
1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return false;
1235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  switch (event.GetAction()) {
1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    case ui::MotionEvent::ACTION_DOWN: {
1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      if (!is_visible_)
1275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return false;
1286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      const float touch_size = std::max(
1296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          kMinTouchMajorForHitTesting,
1306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          std::min(kMaxTouchMajorForHitTesting, event.GetTouchMajor()));
1315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      const gfx::RectF touch_rect(event.GetX() - touch_size * .5f,
1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                  event.GetY() - touch_size * .5f,
1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                  touch_size,
1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                  touch_size);
1355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      if (!drawable_->IntersectsWith(touch_rect))
1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return false;
1375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      touch_down_position_ = gfx::PointF(event.GetX(), event.GetY());
1385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      touch_to_focus_offset_ = position_ - touch_down_position_;
1395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      touch_down_time_ = event.GetEventTime();
1405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      BeginDrag();
1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    } break;
1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    case ui::MotionEvent::ACTION_MOVE: {
1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      gfx::PointF touch_move_position(event.GetX(), event.GetY());
1451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (is_drag_within_tap_region_) {
1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        const float tap_slop = client_->GetTapSlop();
1471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        is_drag_within_tap_region_ =
1481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            (touch_move_position - touch_down_position_).LengthSquared() <
1491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            tap_slop * tap_slop;
1501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      }
1511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // Note that we signal drag update even if we're inside the tap region,
1531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // as there are cases where characters are narrower than the slop length.
1541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      client_->OnHandleDragUpdate(*this,
1551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                  touch_move_position + touch_to_focus_offset_);
1565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    } break;
1575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    case ui::MotionEvent::ACTION_UP: {
1591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (is_drag_within_tap_region_ &&
1601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          (event.GetEventTime() - touch_down_time_) <
1611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci              client_->GetTapTimeout()) {
1625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        client_->OnHandleTapped(*this);
1631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      }
1645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      EndDrag();
1665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    } break;
1675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    case ui::MotionEvent::ACTION_CANCEL:
1695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      EndDrag();
1705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      break;
1715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    default:
1735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      break;
1745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  };
1755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return true;
1765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool TouchHandle::Animate(base::TimeTicks frame_time) {
1795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (fade_end_time_ == base::TimeTicks())
1805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return false;
1815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(enabled_);
1835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  float time_u =
1855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      1.f - (fade_end_time_ - frame_time).InMillisecondsF() / kFadeDurationMs;
1865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  float position_u =
1875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      (position_ - fade_start_position_).LengthSquared() / kFadeDistanceSquared;
1885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  float u = std::max(time_u, position_u);
1895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  SetAlpha(is_visible_ ? u : 1.f - u);
1905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (u >= 1.f) {
1925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    EndFade();
1935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return false;
1945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
1955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return true;
1975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void TouchHandle::BeginDrag() {
2005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(enabled_);
2015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (is_dragging_)
2025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
2035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EndFade();
2045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  is_dragging_ = true;
2051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  is_drag_within_tap_region_ = true;
2065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  client_->OnHandleDragBegin(*this);
2075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
2085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void TouchHandle::EndDrag() {
2105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(enabled_);
2115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!is_dragging_)
2125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
2135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  is_dragging_ = false;
2151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  is_drag_within_tap_region_ = false;
2165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  client_->OnHandleDragEnd(*this);
2175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (deferred_orientation_ != TOUCH_HANDLE_ORIENTATION_UNDEFINED) {
2195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    TouchHandleOrientation deferred_orientation = deferred_orientation_;
2205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    deferred_orientation_ = TOUCH_HANDLE_ORIENTATION_UNDEFINED;
2215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    SetOrientation(deferred_orientation);
2225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
2235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (animate_deferred_fade_) {
2255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    BeginFade();
2265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  } else {
2275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // As drawable visibility assignment is deferred while dragging, push the
2285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // change by forcing fade completion.
2295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    EndFade();
2305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
2315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
2325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void TouchHandle::BeginFade() {
2345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(enabled_);
2355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(!is_dragging_);
2365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  animate_deferred_fade_ = false;
2375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const float target_alpha = is_visible_ ? 1.f : 0.f;
2385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (target_alpha == alpha_) {
2395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    EndFade();
2405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
2415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
2425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  drawable_->SetVisible(true);
2445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  fade_end_time_ = base::TimeTicks::Now() +
2455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                   base::TimeDelta::FromMillisecondsD(
2465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                       kFadeDurationMs * std::abs(target_alpha - alpha_));
2475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  fade_start_position_ = position_;
2485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  client_->SetNeedsAnimate();
2495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
2505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void TouchHandle::EndFade() {
2525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(enabled_);
2535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  animate_deferred_fade_ = false;
2545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  fade_end_time_ = base::TimeTicks();
2555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  SetAlpha(is_visible_ ? 1.f : 0.f);
2565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  drawable_->SetVisible(is_visible_);
2575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
2585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void TouchHandle::SetAlpha(float alpha) {
2605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  alpha = std::max(0.f, std::min(1.f, alpha));
2615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (alpha_ == alpha)
2625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
2635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  alpha_ = alpha;
2645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  drawable_->SetAlpha(alpha);
2655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
2665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}  // namespace content
268