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.
5 #include "content/browser/renderer_host/input/stylus_text_selector.h"
7 #include "ui/events/event_constants.h"
8 #include "ui/events/gesture_detection/gesture_detector.h"
9 #include "ui/events/gesture_detection/gesture_provider_config_helper.h"
10 #include "ui/events/gesture_detection/motion_event.h"
12 using ui::GestureDetector
;
13 using ui::MotionEvent
;
17 scoped_ptr
<GestureDetector
> CreateGestureDetector(
18 ui::GestureListener
* listener
) {
19 GestureDetector::Config config
=
20 ui::GetGestureProviderConfig(
21 ui::GestureProviderConfigType::CURRENT_PLATFORM
)
22 .gesture_detector_config
;
24 ui::DoubleTapListener
* null_double_tap_listener
= nullptr;
26 // Doubletap, showpress and longpress detection are not required, and
27 // should be explicitly disabled for efficiency.
28 scoped_ptr
<ui::GestureDetector
> detector(
29 new ui::GestureDetector(config
, listener
, null_double_tap_listener
));
30 detector
->set_longpress_enabled(false);
31 detector
->set_showpress_enabled(false);
33 return detector
.Pass();
38 StylusTextSelector::StylusTextSelector(StylusTextSelectorClient
* client
)
40 text_selection_triggered_(false),
41 secondary_button_pressed_(false),
49 StylusTextSelector::~StylusTextSelector() {
52 bool StylusTextSelector::OnTouchEvent(const MotionEvent
& event
) {
53 // Only trigger selection on ACTION_DOWN to prevent partial touch or gesture
54 // sequences from being forwarded.
55 if (event
.GetAction() == MotionEvent::ACTION_DOWN
)
56 text_selection_triggered_
= ShouldStartTextSelection(event
);
58 if (!text_selection_triggered_
)
61 secondary_button_pressed_
=
62 event
.GetButtonState() == MotionEvent::BUTTON_SECONDARY
;
64 switch (event
.GetAction()) {
65 case MotionEvent::ACTION_DOWN
:
68 anchor_x_
= event
.GetX();
69 anchor_y_
= event
.GetY();
72 case MotionEvent::ACTION_MOVE
:
73 if (!secondary_button_pressed_
) {
75 anchor_x_
= event
.GetX();
76 anchor_y_
= event
.GetY();
80 case MotionEvent::ACTION_UP
:
81 case MotionEvent::ACTION_CANCEL
:
83 client_
->OnStylusSelectEnd();
88 case MotionEvent::ACTION_POINTER_UP
:
89 case MotionEvent::ACTION_POINTER_DOWN
:
93 if (!gesture_detector_
)
94 gesture_detector_
= CreateGestureDetector(this);
96 gesture_detector_
->OnTouchEvent(event
);
98 // Always return true, even if |gesture_detector_| technically doesn't
99 // consume the event. This prevents forwarding of a partial touch stream.
103 bool StylusTextSelector::OnSingleTapUp(const MotionEvent
& e
) {
104 DCHECK(text_selection_triggered_
);
106 client_
->OnStylusSelectTap(e
.GetEventTime(), e
.GetX(), e
.GetY());
110 bool StylusTextSelector::OnScroll(const MotionEvent
& e1
,
111 const MotionEvent
& e2
,
114 DCHECK(text_selection_triggered_
);
116 // Return if Stylus button is not pressed.
117 if (!secondary_button_pressed_
)
123 client_
->OnStylusSelectBegin(anchor_x_
, anchor_y_
, e2
.GetX(), e2
.GetY());
125 client_
->OnStylusSelectUpdate(e2
.GetX(), e2
.GetY());
132 bool StylusTextSelector::ShouldStartTextSelection(const MotionEvent
& event
) {
133 DCHECK_GT(event
.GetPointerCount(), 0u);
134 // Currently we are supporting stylus-only cases.
135 const bool is_stylus
= event
.GetToolType(0) == MotionEvent::TOOL_TYPE_STYLUS
;
136 const bool is_only_secondary_button_pressed
=
137 event
.GetButtonState() == MotionEvent::BUTTON_SECONDARY
;
138 return is_stylus
&& is_only_secondary_button_pressed
;
141 } // namespace content