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