1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "content/browser/renderer_host/input/gesture_text_selector.h"
6
7#include "ui/events/event_constants.h"
8#include "ui/events/gesture_detection/gesture_event_data.h"
9#include "ui/events/gesture_detection/motion_event.h"
10
11namespace content {
12
13GestureTextSelector::GestureTextSelector(GestureTextSelectorClient* client)
14    : client_(client),
15      text_selection_triggered_(false),
16      anchor_x_(0.0f),
17      anchor_y_(0.0f) {
18}
19
20GestureTextSelector::~GestureTextSelector() {
21}
22
23bool GestureTextSelector::OnTouchEvent(const ui::MotionEvent& event) {
24  if (event.GetAction() == ui::MotionEvent::ACTION_DOWN) {
25    // Only trigger selection on ACTION_DOWN to prevent partial touch or gesture
26    // sequences from being forwarded.
27    text_selection_triggered_ = ShouldStartTextSelection(event);
28  }
29  return text_selection_triggered_;
30}
31
32bool GestureTextSelector::OnGestureEvent(const ui::GestureEventData& gesture) {
33  if (!text_selection_triggered_)
34    return false;
35
36  switch (gesture.type()) {
37    case ui::ET_GESTURE_TAP: {
38      client_->LongPress(gesture.time, gesture.x, gesture.y);
39      break;
40    }
41    case ui::ET_GESTURE_SCROLL_BEGIN: {
42      client_->Unselect();
43      anchor_x_ = gesture.x;
44      anchor_y_ = gesture.y;
45      break;
46    }
47    case ui::ET_GESTURE_SCROLL_UPDATE: {
48      // TODO(changwan): check if we can show handles on ET_GESTURE_SCROLL_END
49      // instead. Currently it is not possible as ShowSelectionHandles should
50      // be called before we change the selection.
51      client_->ShowSelectionHandlesAutomatically();
52      client_->SelectRange(anchor_x_, anchor_y_, gesture.x, gesture.y);
53      break;
54    }
55    default:
56      // Suppress all other gestures when we are selecting text.
57      break;
58  }
59  return true;
60}
61
62// static
63bool GestureTextSelector::ShouldStartTextSelection(
64    const ui::MotionEvent& event) {
65  DCHECK_GT(event.GetPointerCount(), 0u);
66  // Currently we are supporting stylus-only cases.
67  const bool is_stylus =
68      event.GetToolType(0) == ui::MotionEvent::TOOL_TYPE_STYLUS;
69  const bool is_only_secondary_button_pressed =
70      event.GetButtonState() == ui::MotionEvent::BUTTON_SECONDARY;
71  return is_stylus && is_only_secondary_button_pressed;
72}
73
74}  // namespace content
75