touch_selection_controller.h 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  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. #ifndef UI_TOUCH_SELECTION_TOUCH_SELECTION_CONTROLLER_H_
  5. #define UI_TOUCH_SELECTION_TOUCH_SELECTION_CONTROLLER_H_
  6. #include "base/memory/raw_ptr.h"
  7. #include "base/time/time.h"
  8. #include "ui/gfx/geometry/point.h"
  9. #include "ui/gfx/geometry/point_f.h"
  10. #include "ui/gfx/geometry/rect_f.h"
  11. #include "ui/gfx/geometry/vector2d_f.h"
  12. #include "ui/gfx/selection_bound.h"
  13. #include "ui/touch_selection/longpress_drag_selector.h"
  14. #include "ui/touch_selection/selection_event_type.h"
  15. #include "ui/touch_selection/touch_handle.h"
  16. #include "ui/touch_selection/touch_handle_orientation.h"
  17. #include "ui/touch_selection/ui_touch_selection_export.h"
  18. namespace ui {
  19. class MotionEvent;
  20. // Interface through which |TouchSelectionController| issues selection-related
  21. // commands, notifications and requests.
  22. class UI_TOUCH_SELECTION_EXPORT TouchSelectionControllerClient {
  23. public:
  24. virtual ~TouchSelectionControllerClient() {}
  25. virtual bool SupportsAnimation() const = 0;
  26. virtual void SetNeedsAnimate() = 0;
  27. virtual void MoveCaret(const gfx::PointF& position) = 0;
  28. virtual void MoveRangeSelectionExtent(const gfx::PointF& extent) = 0;
  29. virtual void SelectBetweenCoordinates(const gfx::PointF& base,
  30. const gfx::PointF& extent) = 0;
  31. virtual void OnSelectionEvent(SelectionEventType event) = 0;
  32. virtual void OnDragUpdate(const TouchSelectionDraggable::Type type,
  33. const gfx::PointF& position) = 0;
  34. virtual std::unique_ptr<TouchHandleDrawable> CreateDrawable() = 0;
  35. virtual void DidScroll() = 0;
  36. virtual void ShowTouchSelectionContextMenu(const gfx::Point& location) {}
  37. };
  38. // Controller for manipulating text selection via touch input.
  39. class UI_TOUCH_SELECTION_EXPORT TouchSelectionController
  40. : public TouchHandleClient,
  41. public LongPressDragSelectorClient {
  42. public:
  43. enum ActiveStatus {
  44. INACTIVE,
  45. INSERTION_ACTIVE,
  46. SELECTION_ACTIVE,
  47. };
  48. struct UI_TOUCH_SELECTION_EXPORT Config {
  49. Config();
  50. ~Config();
  51. // Maximum allowed time for handle tap detection. Defaults to 300 ms.
  52. base::TimeDelta max_tap_duration;
  53. // Defaults to 8 DIPs.
  54. float tap_slop;
  55. // Controls whether adaptive orientation for selection handles is enabled.
  56. // Defaults to false.
  57. bool enable_adaptive_handle_orientation;
  58. // Controls whether drag selection after a longpress is enabled.
  59. // Defaults to false.
  60. bool enable_longpress_drag_selection;
  61. // Should we hide the active handle.
  62. bool hide_active_handle;
  63. };
  64. TouchSelectionController(TouchSelectionControllerClient* client,
  65. const Config& config);
  66. TouchSelectionController(const TouchSelectionController&) = delete;
  67. TouchSelectionController& operator=(const TouchSelectionController&) = delete;
  68. ~TouchSelectionController() override;
  69. // To be called when the selection bounds have changed.
  70. // Note that such updates will trigger handle updates only if preceded
  71. // by an appropriate call to allow automatic showing.
  72. void OnSelectionBoundsChanged(const gfx::SelectionBound& start,
  73. const gfx::SelectionBound& end);
  74. // To be called when the viewport rect has been changed. This is used for
  75. // setting the state of the handles.
  76. void OnViewportChanged(const gfx::RectF viewport_rect);
  77. // Allows touch-dragging of the handle.
  78. // Returns true iff the event was consumed, in which case the caller should
  79. // cease further handling of the event.
  80. bool WillHandleTouchEvent(const MotionEvent& event);
  81. // To be called before forwarding a tap event.
  82. // |tap_count| is tap index in a repeated sequence, i.e., 1 for the first
  83. // tap, 2 for the second tap, etc...
  84. void HandleTapEvent(const gfx::PointF& location, int tap_count);
  85. // To be called before forwarding a longpress event.
  86. void HandleLongPressEvent(base::TimeTicks event_time,
  87. const gfx::PointF& location);
  88. // To be called before forwarding a gesture scroll begin event to prevent
  89. // long-press drag.
  90. void OnScrollBeginEvent();
  91. // Hide the handles and suppress bounds updates until the next explicit
  92. // showing allowance.
  93. void HideAndDisallowShowingAutomatically();
  94. // Override the handle visibility according to |hidden|.
  95. void SetTemporarilyHidden(bool hidden);
  96. // Ticks an active animation, as requested to the client by |SetNeedsAnimate|.
  97. // Returns true if an animation is active and requires further ticking.
  98. bool Animate(base::TimeTicks animate_time);
  99. // Returns the rect between the two active selection bounds. If just one of
  100. // the bounds is visible, or both bounds are visible and on the same line,
  101. // the rect is simply a one-dimensional rect of that bound. If no selection
  102. // is active, an empty rect will be returned.
  103. gfx::RectF GetRectBetweenBounds() const;
  104. // Returns the rect between the selection bounds (as above) but clipped by
  105. // occluding layers.
  106. gfx::RectF GetVisibleRectBetweenBounds() const;
  107. // Returns the visible rect of specified touch handle. For an active insertion
  108. // these values will be identical.
  109. gfx::RectF GetStartHandleRect() const;
  110. gfx::RectF GetEndHandleRect() const;
  111. // Return the handle height of visible touch handle. This value will be zero
  112. // when no handle is visible.
  113. float GetTouchHandleHeight() const;
  114. // Returns the focal point of the start and end bounds, as defined by
  115. // their bottom coordinate.
  116. const gfx::PointF& GetStartPosition() const;
  117. const gfx::PointF& GetEndPosition() const;
  118. // To be called when swipe-to-move-cursor motion begins.
  119. void OnSwipeToMoveCursorBegin();
  120. // To be called when swipe-to-move-cursor motion ends.
  121. void OnSwipeToMoveCursorEnd();
  122. const gfx::SelectionBound& start() const { return start_; }
  123. const gfx::SelectionBound& end() const { return end_; }
  124. ActiveStatus active_status() const { return active_status_; }
  125. private:
  126. friend class TouchSelectionControllerTestApi;
  127. enum InputEventType { TAP, REPEATED_TAP, LONG_PRESS, INPUT_EVENT_TYPE_NONE };
  128. bool WillHandleTouchEventImpl(const MotionEvent& event);
  129. // TouchHandleClient implementation.
  130. void OnDragBegin(const TouchSelectionDraggable& draggable,
  131. const gfx::PointF& drag_position) override;
  132. void OnDragUpdate(const TouchSelectionDraggable& draggable,
  133. const gfx::PointF& drag_position) override;
  134. void OnDragEnd(const TouchSelectionDraggable& draggable) override;
  135. bool IsWithinTapSlop(const gfx::Vector2dF& delta) const override;
  136. void OnHandleTapped(const TouchHandle& handle) override;
  137. void SetNeedsAnimate() override;
  138. std::unique_ptr<TouchHandleDrawable> CreateDrawable() override;
  139. base::TimeDelta GetMaxTapDuration() const override;
  140. bool IsAdaptiveHandleOrientationEnabled() const override;
  141. // LongPressDragSelectorClient implementation.
  142. void OnLongPressDragActiveStateChanged() override;
  143. gfx::PointF GetSelectionStart() const override;
  144. gfx::PointF GetSelectionEnd() const override;
  145. void OnInsertionChanged();
  146. void OnSelectionChanged();
  147. // Returns true if insertion mode was newly (re)activated.
  148. bool ActivateInsertionIfNecessary();
  149. void DeactivateInsertion();
  150. // Returns true if selection mode was newly (re)activated.
  151. bool ActivateSelectionIfNecessary();
  152. void DeactivateSelection();
  153. void UpdateHandleLayoutIfNecessary();
  154. bool WillHandleTouchEventForLongPressDrag(const MotionEvent& event);
  155. void SetTemporarilyHiddenForLongPressDrag(bool hidden);
  156. void RefreshHandleVisibility();
  157. // Returns the y-coordinate of middle point of selection bound corresponding
  158. // to the active selection or insertion handle. If there is no active handle,
  159. // returns 0.0.
  160. float GetActiveHandleMiddleY() const;
  161. void HideHandles();
  162. gfx::Vector2dF GetStartLineOffset() const;
  163. gfx::Vector2dF GetEndLineOffset() const;
  164. bool GetStartVisible() const;
  165. bool GetEndVisible() const;
  166. TouchHandle::AnimationStyle GetAnimationStyle(bool was_active) const;
  167. void LogSelectionEnd();
  168. const raw_ptr<TouchSelectionControllerClient> client_;
  169. const Config config_;
  170. InputEventType response_pending_input_event_;
  171. // The bounds at the begin and end of the selection, which might be vertical
  172. // or horizontal line and represents the position of the touch handles or
  173. // caret.
  174. gfx::SelectionBound start_;
  175. gfx::SelectionBound end_;
  176. TouchHandleOrientation start_orientation_;
  177. TouchHandleOrientation end_orientation_;
  178. ActiveStatus active_status_;
  179. std::unique_ptr<TouchHandle> insertion_handle_;
  180. std::unique_ptr<TouchHandle> start_selection_handle_;
  181. std::unique_ptr<TouchHandle> end_selection_handle_;
  182. bool temporarily_hidden_;
  183. // Whether to use the start bound (if false, the end bound) for computing the
  184. // appropriate text line offset when performing a selection drag. This helps
  185. // ensure that the initial selection induced by the drag doesn't "jump"
  186. // between lines.
  187. bool anchor_drag_to_selection_start_;
  188. // Longpress drag allows direct manipulation of longpress-initiated selection.
  189. LongPressDragSelector longpress_drag_selector_;
  190. gfx::RectF viewport_rect_;
  191. base::TimeTicks selection_start_time_;
  192. // Whether a selection handle was dragged during the current 'selection
  193. // session' - i.e. since the current selection has been activated.
  194. bool selection_handle_dragged_;
  195. // Determines whether the entire touch sequence should be consumed or not.
  196. bool consume_touch_sequence_;
  197. bool show_touch_handles_;
  198. };
  199. } // namespace ui
  200. #endif // UI_TOUCH_SELECTION_TOUCH_SELECTION_CONTROLLER_H_