diff options
Diffstat (limited to 'chromium/content/browser/renderer_host/input/gesture_text_selector.cc')
-rw-r--r-- | chromium/content/browser/renderer_host/input/gesture_text_selector.cc | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/chromium/content/browser/renderer_host/input/gesture_text_selector.cc b/chromium/content/browser/renderer_host/input/gesture_text_selector.cc new file mode 100644 index 00000000000..67c4fe7ebb0 --- /dev/null +++ b/chromium/content/browser/renderer_host/input/gesture_text_selector.cc @@ -0,0 +1,115 @@ +// 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/gesture_text_selector.h" + +#include "ui/events/event_constants.h" +#include "ui/events/gesture_detection/gesture_detector.h" +#include "ui/events/gesture_detection/gesture_provider_config_helper.h" +#include "ui/events/gesture_detection/motion_event.h" + +using ui::GestureDetector; +using ui::MotionEvent; + +namespace content { +namespace { +scoped_ptr<GestureDetector> CreateGestureDetector( + ui::GestureListener* listener) { + GestureDetector::Config config = + ui::DefaultGestureProviderConfig().gesture_detector_config; + + ui::DoubleTapListener* null_double_tap_listener = nullptr; + + // Doubletap, showpress and longpress detection are not required, and + // should be explicitly disabled for efficiency. + scoped_ptr<ui::GestureDetector> detector( + new ui::GestureDetector(config, listener, null_double_tap_listener)); + detector->set_longpress_enabled(false); + detector->set_showpress_enabled(false); + + return detector.Pass(); +} + +} // namespace + +GestureTextSelector::GestureTextSelector(GestureTextSelectorClient* client) + : client_(client), + text_selection_triggered_(false), + secondary_button_pressed_(false), + anchor_x_(0.0f), + anchor_y_(0.0f) { + DCHECK(client); +} + +GestureTextSelector::~GestureTextSelector() { +} + +bool GestureTextSelector::OnTouchEvent(const MotionEvent& event) { + if (event.GetAction() == MotionEvent::ACTION_DOWN) { + // Only trigger selection on ACTION_DOWN to prevent partial touch or gesture + // sequences from being forwarded. + text_selection_triggered_ = ShouldStartTextSelection(event); + secondary_button_pressed_ = + event.GetButtonState() == MotionEvent::BUTTON_SECONDARY; + anchor_x_ = event.GetX(); + anchor_y_ = event.GetY(); + } + + if (!text_selection_triggered_) + return false; + + if (event.GetAction() == MotionEvent::ACTION_MOVE) { + secondary_button_pressed_ = + event.GetButtonState() == MotionEvent::BUTTON_SECONDARY; + if (!secondary_button_pressed_) { + anchor_x_ = event.GetX(); + anchor_y_ = event.GetY(); + } + } + + if (!gesture_detector_) + gesture_detector_ = CreateGestureDetector(this); + + gesture_detector_->OnTouchEvent(event); + + // Always return true, even if |gesture_detector_| technically doesn't + // consume the event, to prevent a partial touch stream from being forwarded. + return true; +} + +bool GestureTextSelector::OnSingleTapUp(const MotionEvent& e) { + DCHECK(text_selection_triggered_); + client_->LongPress(e.GetEventTime(), e.GetX(), e.GetY()); + return true; +} + +bool GestureTextSelector::OnScroll(const MotionEvent& e1, + const MotionEvent& e2, + float distance_x, + float distance_y) { + DCHECK(text_selection_triggered_); + + // Return if Stylus button is not pressed. + if (!secondary_button_pressed_) + return true; + + // TODO(changwan): check if we can show handles after the scroll finishes + // instead. Currently it is not possible as ShowSelectionHandles should + // be called before we change the selection. + client_->ShowSelectionHandlesAutomatically(); + client_->SelectRange(anchor_x_, anchor_y_, e2.GetX(), e2.GetY()); + return true; +} + +// static +bool GestureTextSelector::ShouldStartTextSelection(const MotionEvent& event) { + DCHECK_GT(event.GetPointerCount(), 0u); + // Currently we are supporting stylus-only cases. + const bool is_stylus = event.GetToolType(0) == MotionEvent::TOOL_TYPE_STYLUS; + const bool is_only_secondary_button_pressed = + event.GetButtonState() == MotionEvent::BUTTON_SECONDARY; + return is_stylus && is_only_secondary_button_pressed; +} + +} // namespace content |