Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 "ui/touch_selection/longpress_drag_selector.h" | |
| 6 | |
| 7 #include "testing/gtest/include/gtest/gtest.h" | |
| 8 #include "ui/events/test/motion_event_test_utils.h" | |
| 9 | |
| 10 using ui::test::MockMotionEvent; | |
| 11 | |
| 12 namespace ui { | |
| 13 namespace { | |
| 14 | |
| 15 const double kSlop = 10.; | |
| 16 | |
| 17 } // namespace | |
| 18 | |
| 19 class LongPressDragSelectorTest : public testing::Test, | |
| 20 public LongPressDragSelectorClient { | |
| 21 public: | |
| 22 LongPressDragSelectorTest() | |
| 23 : dragging_(false), active_state_changed_(false) {} | |
| 24 | |
| 25 ~LongPressDragSelectorTest() override {} | |
| 26 | |
| 27 // LongPressDragSelectorClient implementation. | |
|
mfomitchev
2015/05/13 20:52:25
Can we put the LongPressDragSelectorClient methods
jdduke (slow)
2015/05/14 18:29:26
Done.
| |
| 28 void OnDragBegin(const TouchSelectionDraggable& handler, | |
| 29 const gfx::PointF& drag_position) override { | |
| 30 dragging_ = true; | |
| 31 drag_position_ = drag_position; | |
| 32 } | |
| 33 | |
| 34 void OnDragUpdate(const TouchSelectionDraggable& handler, | |
| 35 const gfx::PointF& drag_position) override { | |
| 36 drag_position_ = drag_position; | |
| 37 } | |
| 38 | |
| 39 void OnDragEnd(const TouchSelectionDraggable& handler) override { | |
| 40 dragging_ = false; | |
| 41 } | |
| 42 | |
| 43 bool IsWithinTapSlop(const gfx::Vector2dF& delta) const override { | |
| 44 return delta.LengthSquared() < (kSlop * kSlop); | |
| 45 } | |
| 46 | |
| 47 void OnLongPressDragActiveStateChanged() override { | |
| 48 active_state_changed_ = true; | |
| 49 } | |
| 50 | |
| 51 gfx::PointF GetSelectionStart() const override { return selection_start_; } | |
| 52 | |
| 53 gfx::PointF GetSelectionEnd() const override { return selection_end_; } | |
| 54 | |
| 55 void SetSelection(const gfx::PointF& start, const gfx::PointF& end) { | |
| 56 selection_start_ = start; | |
| 57 selection_end_ = end; | |
| 58 } | |
| 59 | |
| 60 bool GetAndResetActiveStateChanged() { | |
| 61 bool active_state_changed = active_state_changed_; | |
| 62 active_state_changed_ = false; | |
| 63 return active_state_changed; | |
| 64 } | |
| 65 | |
| 66 bool IsDragging() const { return dragging_; } | |
| 67 const gfx::PointF& DragPosition() const { return drag_position_; } | |
| 68 | |
| 69 private: | |
| 70 bool dragging_; | |
| 71 bool active_state_changed_; | |
| 72 gfx::PointF drag_position_; | |
| 73 | |
| 74 gfx::PointF selection_start_; | |
| 75 gfx::PointF selection_end_; | |
| 76 }; | |
| 77 | |
| 78 TEST_F(LongPressDragSelectorTest, BasicDrag) { | |
| 79 LongPressDragSelector selector(this); | |
| 80 MockMotionEvent event; | |
| 81 | |
| 82 // Start a touch sequence. | |
| 83 EXPECT_FALSE(selector.WillHandleTouchEvent(event.PressPoint(0, 0))); | |
| 84 EXPECT_FALSE(GetAndResetActiveStateChanged()); | |
| 85 | |
| 86 // Activate a longpress-triggered selection. | |
| 87 gfx::PointF selection_start(0, 10); | |
| 88 gfx::PointF selection_end(10, 10); | |
| 89 selector.OnLongPressEvent(event.GetEventTime(), gfx::PointF()); | |
| 90 EXPECT_TRUE(GetAndResetActiveStateChanged()); | |
| 91 | |
| 92 // Motion should not be consumed until a selection is detected. | |
| 93 EXPECT_FALSE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, 0))); | |
| 94 SetSelection(selection_start, selection_end); | |
| 95 selector.OnSelectionActivated(); | |
| 96 EXPECT_FALSE(IsDragging()); | |
| 97 | |
| 98 // Initiate drag motion. The motion is downward, so the end selection point | |
|
mfomitchev
2015/05/13 20:52:25
The comment about downward motion would probably f
jdduke (slow)
2015/05/14 18:29:26
Done.
| |
| 99 // should be moved. Note that the first move event after activation is used to | |
| 100 // initialize the drag start anchor. | |
| 101 EXPECT_TRUE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, 0))); | |
| 102 EXPECT_FALSE(IsDragging()); | |
| 103 | |
| 104 // The first slop exceeding motion will start the drag. | |
| 105 EXPECT_TRUE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, kSlop))); | |
| 106 EXPECT_TRUE(IsDragging()); | |
| 107 EXPECT_EQ(selection_end, DragPosition()); | |
| 108 | |
| 109 // Subsequent motion will extend the selection. | |
| 110 EXPECT_TRUE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, kSlop * 2))); | |
| 111 EXPECT_TRUE(IsDragging()); | |
| 112 EXPECT_EQ(selection_end + gfx::Vector2dF(0, kSlop), DragPosition()); | |
| 113 EXPECT_TRUE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, kSlop * 3))); | |
| 114 EXPECT_TRUE(IsDragging()); | |
| 115 EXPECT_EQ(selection_end + gfx::Vector2dF(0, kSlop * 2), DragPosition()); | |
| 116 | |
| 117 // Release the touch sequence, ending the drag. The selector will never | |
| 118 // consume the start/end events, only move events after a longpress. | |
| 119 EXPECT_FALSE(selector.WillHandleTouchEvent(event.ReleasePoint())); | |
| 120 EXPECT_FALSE(IsDragging()); | |
| 121 EXPECT_TRUE(GetAndResetActiveStateChanged()); | |
| 122 } | |
| 123 | |
| 124 TEST_F(LongPressDragSelectorTest, BasicReverseDrag) { | |
| 125 LongPressDragSelector selector(this); | |
| 126 MockMotionEvent event; | |
| 127 | |
| 128 // Start a touch sequence. | |
| 129 EXPECT_FALSE(selector.WillHandleTouchEvent(event.PressPoint(0, 0))); | |
| 130 EXPECT_FALSE(GetAndResetActiveStateChanged()); | |
| 131 | |
| 132 // Activate a longpress-triggered selection. | |
| 133 gfx::PointF selection_start(0, 10); | |
| 134 gfx::PointF selection_end(10, 10); | |
| 135 selector.OnLongPressEvent(event.GetEventTime(), gfx::PointF()); | |
| 136 EXPECT_TRUE(GetAndResetActiveStateChanged()); | |
| 137 SetSelection(selection_start, selection_end); | |
| 138 selector.OnSelectionActivated(); | |
| 139 EXPECT_FALSE(IsDragging()); | |
| 140 | |
| 141 // Initiate drag motion. The initial motion is leftward, toward the selection | |
| 142 // start, so that should be the drag point. | |
| 143 EXPECT_TRUE(selector.WillHandleTouchEvent(event.MovePoint(0, kSlop, 0))); | |
|
mfomitchev
2015/05/13 20:52:25
I don't get it - kSlop is greater than 0, so why i
jdduke (slow)
2015/05/14 18:29:26
Yeah, the comment is in a bad position, I'll chang
| |
| 144 EXPECT_FALSE(IsDragging()); | |
| 145 | |
| 146 EXPECT_TRUE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, 0))); | |
| 147 EXPECT_TRUE(IsDragging()); | |
| 148 EXPECT_EQ(selection_start, DragPosition()); | |
| 149 | |
| 150 EXPECT_TRUE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, -kSlop))); | |
| 151 EXPECT_TRUE(IsDragging()); | |
| 152 EXPECT_EQ(selection_start + gfx::Vector2dF(0, -kSlop), DragPosition()); | |
| 153 | |
| 154 // Release the touch sequence, ending the drag. | |
| 155 EXPECT_FALSE(selector.WillHandleTouchEvent(event.ReleasePoint())); | |
| 156 EXPECT_FALSE(IsDragging()); | |
| 157 EXPECT_TRUE(GetAndResetActiveStateChanged()); | |
| 158 } | |
| 159 | |
| 160 TEST_F(LongPressDragSelectorTest, NoActiveTouch) { | |
| 161 LongPressDragSelector selector(this); | |
| 162 MockMotionEvent event; | |
| 163 | |
| 164 // Activate a longpress-triggered selection. | |
| 165 gfx::PointF selection_start(0, 10); | |
| 166 gfx::PointF selection_end(10, 10); | |
| 167 selector.OnLongPressEvent(event.GetEventTime(), gfx::PointF()); | |
| 168 SetSelection(selection_start, selection_end); | |
| 169 selector.OnSelectionActivated(); | |
| 170 EXPECT_FALSE(GetAndResetActiveStateChanged()); | |
| 171 EXPECT_FALSE(IsDragging()); | |
| 172 | |
| 173 // Start a new touch sequence; it shouldn't initiate selection drag as there | |
| 174 // was no active touch sequence when the longpress selection started. | |
| 175 EXPECT_FALSE(selector.WillHandleTouchEvent(event.PressPoint(0, 0))); | |
| 176 EXPECT_FALSE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, 0))); | |
| 177 EXPECT_FALSE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, kSlop))); | |
| 178 EXPECT_FALSE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, kSlop * 2))); | |
| 179 EXPECT_FALSE(IsDragging()); | |
| 180 EXPECT_EQ(gfx::PointF(), DragPosition()); | |
| 181 } | |
| 182 | |
| 183 TEST_F(LongPressDragSelectorTest, NoLongPress) { | |
| 184 LongPressDragSelector selector(this); | |
| 185 MockMotionEvent event; | |
| 186 | |
| 187 // Start a touch sequence. | |
| 188 EXPECT_FALSE(selector.WillHandleTouchEvent(event.PressPoint(0, 0))); | |
| 189 EXPECT_FALSE(GetAndResetActiveStateChanged()); | |
| 190 | |
| 191 // Activate a selection without a preceding longpress. | |
| 192 gfx::PointF selection_start(0, 10); | |
| 193 gfx::PointF selection_end(10, 10); | |
| 194 SetSelection(selection_start, selection_end); | |
| 195 selector.OnSelectionActivated(); | |
| 196 EXPECT_FALSE(GetAndResetActiveStateChanged()); | |
| 197 EXPECT_FALSE(IsDragging()); | |
| 198 | |
| 199 // Touch movement should not initiate selection drag. | |
| 200 EXPECT_FALSE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, 0))); | |
| 201 EXPECT_FALSE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, kSlop))); | |
| 202 EXPECT_FALSE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, kSlop * 2))); | |
| 203 EXPECT_FALSE(IsDragging()); | |
| 204 EXPECT_EQ(gfx::PointF(), DragPosition()); | |
| 205 } | |
| 206 | |
| 207 TEST_F(LongPressDragSelectorTest, NoValidLongPress) { | |
| 208 LongPressDragSelector selector(this); | |
| 209 MockMotionEvent event; | |
| 210 | |
| 211 // Start a touch sequence. | |
| 212 EXPECT_FALSE(selector.WillHandleTouchEvent(event.PressPoint(0, 0))); | |
| 213 EXPECT_FALSE(GetAndResetActiveStateChanged()); | |
| 214 | |
| 215 gfx::PointF selection_start(0, 10); | |
| 216 gfx::PointF selection_end(10, 10); | |
| 217 SetSelection(selection_start, selection_end); | |
| 218 | |
| 219 // Activate a longpress-triggered selection, but at a time different than the | |
|
mfomitchev
2015/05/13 20:52:25
different -> before ?
jdduke (slow)
2015/05/14 18:29:26
Done.
| |
| 220 // current touch down event. | |
| 221 selector.OnLongPressEvent( | |
| 222 event.GetEventTime() - base::TimeDelta::FromSeconds(1), gfx::PointF()); | |
| 223 selector.OnSelectionActivated(); | |
| 224 EXPECT_FALSE(GetAndResetActiveStateChanged()); | |
| 225 EXPECT_FALSE(IsDragging()); | |
| 226 | |
| 227 // Activate a longpress-triggered selection, but at a place different than the | |
| 228 // current touch down event. | |
| 229 selector.OnLongPressEvent(event.GetEventTime(), gfx::PointF(kSlop * 2, 0)); | |
|
mfomitchev
2015/05/13 20:52:25
Can we do kSlop here instead of kSlop * 2?
jdduke (slow)
2015/05/14 18:29:26
Done.
| |
| 230 selector.OnSelectionActivated(); | |
| 231 EXPECT_FALSE(GetAndResetActiveStateChanged()); | |
| 232 EXPECT_FALSE(IsDragging()); | |
| 233 | |
| 234 // Touch movement should not initiate selection drag. | |
| 235 EXPECT_FALSE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, 0))); | |
| 236 EXPECT_FALSE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, kSlop))); | |
| 237 EXPECT_FALSE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, kSlop * 2))); | |
| 238 EXPECT_FALSE(IsDragging()); | |
| 239 EXPECT_EQ(gfx::PointF(), DragPosition()); | |
| 240 } | |
| 241 | |
| 242 TEST_F(LongPressDragSelectorTest, NoSelection) { | |
| 243 LongPressDragSelector selector(this); | |
| 244 MockMotionEvent event; | |
| 245 | |
| 246 // Start a touch sequence. | |
| 247 EXPECT_FALSE(selector.WillHandleTouchEvent(event.PressPoint(0, 0))); | |
| 248 EXPECT_FALSE(GetAndResetActiveStateChanged()); | |
| 249 | |
| 250 // Trigger a longpress. This will notify the client that detection is active, | |
| 251 // but until there's a longpress no drag selection should occur. | |
| 252 selector.OnLongPressEvent(event.GetEventTime(), gfx::PointF()); | |
| 253 EXPECT_TRUE(GetAndResetActiveStateChanged()); | |
| 254 EXPECT_FALSE(IsDragging()); | |
| 255 | |
| 256 // Touch movement should not initiate selection drag, as there is no active | |
| 257 // selection. | |
| 258 EXPECT_FALSE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, 0))); | |
| 259 EXPECT_FALSE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, kSlop))); | |
| 260 EXPECT_FALSE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, kSlop * 2))); | |
| 261 EXPECT_FALSE(IsDragging()); | |
| 262 EXPECT_EQ(gfx::PointF(), DragPosition()); | |
| 263 | |
| 264 EXPECT_FALSE(selector.WillHandleTouchEvent(event.ReleasePoint())); | |
| 265 EXPECT_TRUE(GetAndResetActiveStateChanged()); | |
| 266 } | |
| 267 | |
| 268 TEST_F(LongPressDragSelectorTest, NoDragMotion) { | |
| 269 LongPressDragSelector selector(this); | |
| 270 MockMotionEvent event; | |
| 271 | |
| 272 // Start a touch sequence. | |
| 273 EXPECT_FALSE(selector.WillHandleTouchEvent(event.PressPoint(0, 0))); | |
| 274 EXPECT_FALSE(GetAndResetActiveStateChanged()); | |
| 275 | |
| 276 // Activate a longpress-triggered selection. | |
| 277 selector.OnLongPressEvent(event.GetEventTime(), gfx::PointF()); | |
| 278 EXPECT_TRUE(GetAndResetActiveStateChanged()); | |
| 279 gfx::PointF selection_start(0, 10); | |
| 280 gfx::PointF selection_end(10, 10); | |
| 281 SetSelection(selection_start, selection_end); | |
| 282 selector.OnSelectionActivated(); | |
| 283 EXPECT_FALSE(IsDragging()); | |
| 284 | |
| 285 // Touch movement within the slop region should not initiate selection drag. | |
| 286 EXPECT_TRUE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, 0))); | |
| 287 EXPECT_TRUE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, kSlop / 2))); | |
| 288 EXPECT_TRUE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, -kSlop / 2))); | |
| 289 EXPECT_FALSE(IsDragging()); | |
| 290 EXPECT_EQ(gfx::PointF(), DragPosition()); | |
| 291 | |
| 292 EXPECT_FALSE(selector.WillHandleTouchEvent(event.ReleasePoint())); | |
| 293 EXPECT_TRUE(GetAndResetActiveStateChanged()); | |
| 294 } | |
| 295 | |
| 296 TEST_F(LongPressDragSelectorTest, SelectionDeactivated) { | |
| 297 LongPressDragSelector selector(this); | |
| 298 MockMotionEvent event; | |
| 299 | |
| 300 // Start a touch sequence. | |
| 301 EXPECT_FALSE(selector.WillHandleTouchEvent(event.PressPoint(0, 0))); | |
| 302 EXPECT_FALSE(GetAndResetActiveStateChanged()); | |
| 303 | |
| 304 // Activate a longpress-triggered selection. | |
| 305 selector.OnLongPressEvent(event.GetEventTime(), gfx::PointF()); | |
| 306 EXPECT_TRUE(GetAndResetActiveStateChanged()); | |
| 307 gfx::PointF selection_start(0, 10); | |
| 308 gfx::PointF selection_end(10, 10); | |
| 309 SetSelection(selection_start, selection_end); | |
| 310 selector.OnSelectionActivated(); | |
| 311 EXPECT_FALSE(IsDragging()); | |
| 312 | |
| 313 // Start a drag selection. | |
| 314 EXPECT_TRUE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, 0))); | |
| 315 EXPECT_TRUE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, kSlop))); | |
| 316 EXPECT_TRUE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, kSlop * 2))); | |
| 317 EXPECT_TRUE(IsDragging()); | |
| 318 | |
| 319 // Clearing the selection should force an end to the drag. | |
| 320 selector.OnSelectionDeactivated(); | |
| 321 EXPECT_TRUE(GetAndResetActiveStateChanged()); | |
| 322 EXPECT_FALSE(IsDragging()); | |
| 323 | |
| 324 // Subsequent motion should not be consumed. | |
| 325 EXPECT_FALSE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, 0))); | |
| 326 EXPECT_FALSE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, kSlop))); | |
| 327 EXPECT_FALSE(selector.WillHandleTouchEvent(event.MovePoint(0, 0, kSlop * 2))); | |
| 328 EXPECT_FALSE(IsDragging()); | |
| 329 EXPECT_FALSE(selector.WillHandleTouchEvent(event.ReleasePoint())); | |
| 330 } | |
| 331 | |
| 332 } // namespace ui | |
| OLD | NEW |