Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(215)

Side by Side Diff: ui/touch_selection/touch_selection_controller_unittest.cc

Issue 996373002: Add Aura handles to be used in unified touch selection (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixed issues with loading resources Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/touch_selection/touch_selection_controller.h" 5 #include "ui/touch_selection/touch_selection_controller.h"
6 6
7 #include <vector> 7 #include <vector>
8 8
9 #include "testing/gmock/include/gmock/gmock.h" 9 #include "testing/gmock/include/gmock/gmock.h"
10 #include "testing/gtest/include/gtest/gtest.h" 10 #include "testing/gtest/include/gtest/gtest.h"
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
109 controller_.reset(new TouchSelectionController( 109 controller_.reset(new TouchSelectionController(
110 this, 110 this,
111 base::TimeDelta::FromMilliseconds(kDefaultTapTimeoutMs), 111 base::TimeDelta::FromMilliseconds(kDefaultTapTimeoutMs),
112 kDefaulTapSlop, 112 kDefaulTapSlop,
113 show_on_tap_for_empty_editable)); 113 show_on_tap_for_empty_editable));
114 } 114 }
115 115
116 void SetAnimationEnabled(bool enabled) { animation_enabled_ = enabled; } 116 void SetAnimationEnabled(bool enabled) { animation_enabled_ = enabled; }
117 void SetDraggingEnabled(bool enabled) { dragging_enabled_ = enabled; } 117 void SetDraggingEnabled(bool enabled) { dragging_enabled_ = enabled; }
118 118
119 void ClearSelection() { 119 bool ClearSelection() {
120 controller_->OnSelectionBoundsChanged(SelectionBound(), 120 return controller_->OnSelectionBoundsUpdated(SelectionBound(),
121 SelectionBound()); 121 SelectionBound());
122 } 122 }
123 123
124 void ClearInsertion() { ClearSelection(); } 124 bool ClearInsertion() { return ClearSelection(); }
125 125
126 void ChangeInsertion(const gfx::RectF& rect, bool visible) { 126 bool ChangeInsertion(const gfx::RectF& rect, bool visible) {
127 SelectionBound bound; 127 SelectionBound bound;
128 bound.set_type(SelectionBound::CENTER); 128 bound.set_type(SelectionBound::CENTER);
129 bound.SetEdge(rect.origin(), rect.bottom_left()); 129 bound.SetEdge(rect.origin(), rect.bottom_left());
130 bound.set_visible(visible); 130 bound.set_visible(visible);
131 controller_->OnSelectionBoundsChanged(bound, bound); 131 return controller_->OnSelectionBoundsUpdated(bound, bound);
132 } 132 }
133 133
134 void ChangeSelection(const gfx::RectF& start_rect, 134 bool ChangeSelection(const gfx::RectF& start_rect,
135 bool start_visible, 135 bool start_visible,
136 const gfx::RectF& end_rect, 136 const gfx::RectF& end_rect,
137 bool end_visible) { 137 bool end_visible) {
138 SelectionBound start_bound, end_bound; 138 SelectionBound start_bound, end_bound;
139 start_bound.set_type(SelectionBound::LEFT); 139 start_bound.set_type(SelectionBound::LEFT);
140 end_bound.set_type(SelectionBound::RIGHT); 140 end_bound.set_type(SelectionBound::RIGHT);
141 start_bound.SetEdge(start_rect.origin(), start_rect.bottom_left()); 141 start_bound.SetEdge(start_rect.origin(), start_rect.bottom_left());
142 end_bound.SetEdge(end_rect.origin(), end_rect.bottom_left()); 142 end_bound.SetEdge(end_rect.origin(), end_rect.bottom_left());
143 start_bound.set_visible(start_visible); 143 start_bound.set_visible(start_visible);
144 end_bound.set_visible(end_visible); 144 end_bound.set_visible(end_visible);
145 controller_->OnSelectionBoundsChanged(start_bound, end_bound); 145 return controller_->OnSelectionBoundsUpdated(start_bound, end_bound);
146 } 146 }
147 147
148 void Animate() { 148 void Animate() {
149 base::TimeTicks now = base::TimeTicks::Now(); 149 base::TimeTicks now = base::TimeTicks::Now();
150 while (needs_animate_) { 150 while (needs_animate_) {
151 needs_animate_ = controller_->Animate(now); 151 needs_animate_ = controller_->Animate(now);
152 now += base::TimeDelta::FromMilliseconds(16); 152 now += base::TimeDelta::FromMilliseconds(16);
153 } 153 }
154 } 154 }
155 155
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
203 bool animation_enabled_; 203 bool animation_enabled_;
204 bool dragging_enabled_; 204 bool dragging_enabled_;
205 scoped_ptr<TouchSelectionController> controller_; 205 scoped_ptr<TouchSelectionController> controller_;
206 }; 206 };
207 207
208 TEST_F(TouchSelectionControllerTest, InsertionBasic) { 208 TEST_F(TouchSelectionControllerTest, InsertionBasic) {
209 gfx::RectF insertion_rect(5, 5, 0, 10); 209 gfx::RectF insertion_rect(5, 5, 0, 10);
210 bool visible = true; 210 bool visible = true;
211 211
212 // Insertion events are ignored until automatic showing is enabled. 212 // Insertion events are ignored until automatic showing is enabled.
213 ChangeInsertion(insertion_rect, visible); 213 EXPECT_FALSE(ChangeInsertion(insertion_rect, visible));
214 EXPECT_THAT(GetAndResetEvents(), IsEmpty()); 214 EXPECT_THAT(GetAndResetEvents(), IsEmpty());
215 EXPECT_EQ(gfx::PointF(), GetLastEventAnchor()); 215 EXPECT_EQ(gfx::PointF(), GetLastEventAnchor());
216 controller().OnTapEvent(); 216 controller().OnTapEvent();
217 217
218 // Insertion events are ignored until the selection region is marked editable. 218 // Insertion events are ignored until the selection region is marked editable.
219 ChangeInsertion(insertion_rect, visible); 219 EXPECT_TRUE(ChangeInsertion(insertion_rect, visible));
220 EXPECT_THAT(GetAndResetEvents(), IsEmpty()); 220 EXPECT_THAT(GetAndResetEvents(), IsEmpty());
221 EXPECT_EQ(gfx::PointF(), GetLastEventAnchor()); 221 EXPECT_EQ(gfx::PointF(), GetLastEventAnchor());
222 222
223 controller().OnTapEvent(); 223 controller().OnTapEvent();
224 controller().OnSelectionEditable(true); 224 controller().OnSelectionEditable(true);
225 ChangeInsertion(insertion_rect, visible); 225 EXPECT_TRUE(ChangeInsertion(insertion_rect, visible));
226 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_SHOWN)); 226 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_SHOWN));
227 EXPECT_EQ(insertion_rect.bottom_left(), GetLastEventAnchor()); 227 EXPECT_EQ(insertion_rect.bottom_left(), GetLastEventAnchor());
228 228
229 insertion_rect.Offset(1, 0); 229 insertion_rect.Offset(1, 0);
230 ChangeInsertion(insertion_rect, visible); 230 EXPECT_TRUE(ChangeInsertion(insertion_rect, visible));
231 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_MOVED)); 231 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_MOVED));
232 EXPECT_EQ(insertion_rect.bottom_left(), GetLastEventAnchor()); 232 EXPECT_EQ(insertion_rect.bottom_left(), GetLastEventAnchor());
233 233
234 insertion_rect.Offset(0, 1); 234 insertion_rect.Offset(0, 1);
235 ChangeInsertion(insertion_rect, visible); 235 EXPECT_TRUE(ChangeInsertion(insertion_rect, visible));
236 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_MOVED)); 236 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_MOVED));
237 EXPECT_EQ(insertion_rect.bottom_left(), GetLastEventAnchor()); 237 EXPECT_EQ(insertion_rect.bottom_left(), GetLastEventAnchor());
238 238
239 ClearInsertion(); 239 EXPECT_TRUE(ClearInsertion());
240 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_CLEARED)); 240 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_CLEARED));
241 } 241 }
242 242
243 TEST_F(TouchSelectionControllerTest, InsertionClearedWhenNoLongerEditable) { 243 TEST_F(TouchSelectionControllerTest, InsertionClearedWhenNoLongerEditable) {
244 gfx::RectF insertion_rect(5, 5, 0, 10); 244 gfx::RectF insertion_rect(5, 5, 0, 10);
245 bool visible = true; 245 bool visible = true;
246 controller().OnTapEvent(); 246 controller().OnTapEvent();
247 controller().OnSelectionEditable(true); 247 controller().OnSelectionEditable(true);
248 248
249 ChangeInsertion(insertion_rect, visible); 249 EXPECT_TRUE(ChangeInsertion(insertion_rect, visible));
250 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_SHOWN)); 250 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_SHOWN));
251 EXPECT_EQ(insertion_rect.bottom_left(), GetLastEventAnchor()); 251 EXPECT_EQ(insertion_rect.bottom_left(), GetLastEventAnchor());
252 252
253 controller().OnSelectionEditable(false); 253 controller().OnSelectionEditable(false);
254 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_CLEARED)); 254 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_CLEARED));
255 } 255 }
256 256
257 TEST_F(TouchSelectionControllerTest, InsertionWithNoShowOnTapForEmptyEditable) { 257 TEST_F(TouchSelectionControllerTest, InsertionWithNoShowOnTapForEmptyEditable) {
258 gfx::RectF insertion_rect(5, 5, 0, 10); 258 gfx::RectF insertion_rect(5, 5, 0, 10);
259 bool visible = true; 259 bool visible = true;
260 controller().OnSelectionEditable(true); 260 controller().OnSelectionEditable(true);
261 261
262 // Taps on an empty editable region should be ignored if the controller is 262 // Taps on an empty editable region should be ignored if the controller is
263 // created with |show_on_tap_for_empty_editable| set to false. 263 // created with |show_on_tap_for_empty_editable| set to false.
264 controller().OnTapEvent(); 264 controller().OnTapEvent();
265 controller().OnSelectionEmpty(true); 265 controller().OnSelectionEmpty(true);
266 ChangeInsertion(insertion_rect, visible); 266 EXPECT_TRUE(ChangeInsertion(insertion_rect, visible));
267 EXPECT_EQ(gfx::PointF(), GetLastEventAnchor()); 267 EXPECT_EQ(gfx::PointF(), GetLastEventAnchor());
268 268
269 // Once the region becomes non-empty, taps should show the insertion handle. 269 // Once the region becomes non-empty, taps should show the insertion handle.
270 controller().OnTapEvent(); 270 controller().OnTapEvent();
271 controller().OnSelectionEmpty(false); 271 controller().OnSelectionEmpty(false);
272 ChangeInsertion(insertion_rect, visible); 272 EXPECT_TRUE(ChangeInsertion(insertion_rect, visible));
273 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_SHOWN)); 273 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_SHOWN));
274 EXPECT_EQ(insertion_rect.bottom_left(), GetLastEventAnchor()); 274 EXPECT_EQ(insertion_rect.bottom_left(), GetLastEventAnchor());
275 275
276 // Reset the selection. 276 // Reset the selection.
277 controller().HideAndDisallowShowingAutomatically(); 277 controller().HideAndDisallowShowingAutomatically();
278 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_CLEARED)); 278 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_CLEARED));
279 279
280 // Long-pressing should show the handle even if the editable region is empty. 280 // Long-pressing should show the handle even if the editable region is empty.
281 insertion_rect.Offset(2, -2); 281 insertion_rect.Offset(2, -2);
282 controller().OnLongPressEvent(); 282 controller().OnLongPressEvent();
283 controller().OnSelectionEmpty(true); 283 controller().OnSelectionEmpty(true);
284 ChangeInsertion(insertion_rect, visible); 284 EXPECT_TRUE(ChangeInsertion(insertion_rect, visible));
285 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_SHOWN)); 285 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_SHOWN));
286 EXPECT_EQ(insertion_rect.bottom_left(), GetLastEventAnchor()); 286 EXPECT_EQ(insertion_rect.bottom_left(), GetLastEventAnchor());
287 287
288 // Single Tap on an empty edit field should clear insertion handle. 288 // Single Tap on an empty edit field should clear insertion handle.
289 controller().OnTapEvent(); 289 controller().OnTapEvent();
290 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_CLEARED)); 290 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_CLEARED));
291 } 291 }
292 292
293 TEST_F(TouchSelectionControllerTest, InsertionWithShowOnTapForEmptyEditable) { 293 TEST_F(TouchSelectionControllerTest, InsertionWithShowOnTapForEmptyEditable) {
294 AllowShowingOnTapForEmptyEditable(); 294 AllowShowingOnTapForEmptyEditable();
295 295
296 gfx::RectF insertion_rect(5, 5, 0, 10); 296 gfx::RectF insertion_rect(5, 5, 0, 10);
297 bool visible = true; 297 bool visible = true;
298 controller().OnSelectionEditable(true); 298 controller().OnSelectionEditable(true);
299 299
300 // Taps on an empty editable region should show the insertion handle if the 300 // Taps on an empty editable region should show the insertion handle if the
301 // controller is created with |show_on_tap_for_empty_editable| set to true. 301 // controller is created with |show_on_tap_for_empty_editable| set to true.
302 controller().OnTapEvent(); 302 controller().OnTapEvent();
303 controller().OnSelectionEmpty(true); 303 controller().OnSelectionEmpty(true);
304 ChangeInsertion(insertion_rect, visible); 304 EXPECT_TRUE(ChangeInsertion(insertion_rect, visible));
305 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_SHOWN)); 305 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_SHOWN));
306 EXPECT_EQ(insertion_rect.bottom_left(), GetLastEventAnchor()); 306 EXPECT_EQ(insertion_rect.bottom_left(), GetLastEventAnchor());
307 } 307 }
308 308
309 TEST_F(TouchSelectionControllerTest, InsertionAppearsAfterTapFollowingTyping) { 309 TEST_F(TouchSelectionControllerTest, InsertionAppearsAfterTapFollowingTyping) {
310 gfx::RectF insertion_rect(5, 5, 0, 10); 310 gfx::RectF insertion_rect(5, 5, 0, 10);
311 bool visible = true; 311 bool visible = true;
312 312
313 // Simulate the user tapping an empty text field. 313 // Simulate the user tapping an empty text field.
314 controller().OnTapEvent(); 314 controller().OnTapEvent();
315 controller().OnSelectionEditable(true); 315 controller().OnSelectionEditable(true);
316 controller().OnSelectionEmpty(true); 316 controller().OnSelectionEmpty(true);
317 ChangeInsertion(insertion_rect, visible); 317 EXPECT_TRUE(ChangeInsertion(insertion_rect, visible));
318 EXPECT_EQ(gfx::PointF(), GetLastEventAnchor()); 318 EXPECT_EQ(gfx::PointF(), GetLastEventAnchor());
319 319
320 // Simulate the cursor moving while a user is typing. 320 // Simulate the cursor moving while a user is typing.
321 insertion_rect.Offset(10, 0); 321 insertion_rect.Offset(10, 0);
322 controller().OnSelectionEmpty(false); 322 controller().OnSelectionEmpty(false);
323 ChangeInsertion(insertion_rect, visible); 323 EXPECT_FALSE(ChangeInsertion(insertion_rect, visible));
324 EXPECT_EQ(gfx::PointF(), GetLastEventAnchor()); 324 EXPECT_EQ(gfx::PointF(), GetLastEventAnchor());
325 325
326 // If the user taps the *same* position as the cursor at the end of the text 326 // If the user taps the *same* position as the cursor at the end of the text
327 // entry, the handle should appear. 327 // entry, the handle should appear.
328 controller().OnTapEvent(); 328 controller().OnTapEvent();
329 ChangeInsertion(insertion_rect, visible); 329 EXPECT_TRUE(ChangeInsertion(insertion_rect, visible));
330 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_SHOWN)); 330 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_SHOWN));
331 EXPECT_EQ(insertion_rect.bottom_left(), GetLastEventAnchor()); 331 EXPECT_EQ(insertion_rect.bottom_left(), GetLastEventAnchor());
332 } 332 }
333 333
334 TEST_F(TouchSelectionControllerTest, InsertionToSelectionTransition) { 334 TEST_F(TouchSelectionControllerTest, InsertionToSelectionTransition) {
335 controller().OnLongPressEvent(); 335 controller().OnLongPressEvent();
336 controller().OnSelectionEditable(true); 336 controller().OnSelectionEditable(true);
337 337
338 gfx::RectF start_rect(5, 5, 0, 10); 338 gfx::RectF start_rect(5, 5, 0, 10);
339 gfx::RectF end_rect(50, 5, 0, 10); 339 gfx::RectF end_rect(50, 5, 0, 10);
340 bool visible = true; 340 bool visible = true;
341 341
342 ChangeInsertion(start_rect, visible); 342 EXPECT_TRUE(ChangeInsertion(start_rect, visible));
343 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_SHOWN)); 343 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_SHOWN));
344 EXPECT_EQ(start_rect.bottom_left(), GetLastEventAnchor()); 344 EXPECT_EQ(start_rect.bottom_left(), GetLastEventAnchor());
345 345
346 ChangeSelection(start_rect, visible, end_rect, visible); 346 EXPECT_TRUE(ChangeSelection(start_rect, visible, end_rect, visible));
347 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_CLEARED, 347 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_CLEARED,
348 SELECTION_SHOWN)); 348 SELECTION_SHOWN));
349 EXPECT_EQ(start_rect.bottom_left(), GetLastEventAnchor()); 349 EXPECT_EQ(start_rect.bottom_left(), GetLastEventAnchor());
350 350
351 ChangeInsertion(end_rect, visible); 351 EXPECT_TRUE(ChangeInsertion(end_rect, visible));
352 EXPECT_THAT(GetAndResetEvents(), ElementsAre(SELECTION_CLEARED, 352 EXPECT_THAT(GetAndResetEvents(), ElementsAre(SELECTION_CLEARED,
353 INSERTION_SHOWN)); 353 INSERTION_SHOWN));
354 EXPECT_EQ(end_rect.bottom_left(), GetLastEventAnchor()); 354 EXPECT_EQ(end_rect.bottom_left(), GetLastEventAnchor());
355 355
356 controller().HideAndDisallowShowingAutomatically(); 356 controller().HideAndDisallowShowingAutomatically();
357 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_CLEARED)); 357 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_CLEARED));
358 358
359 controller().OnTapEvent(); 359 controller().OnTapEvent();
360 ChangeInsertion(end_rect, visible); 360 EXPECT_TRUE(ChangeInsertion(end_rect, visible));
361 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_SHOWN)); 361 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_SHOWN));
362 EXPECT_EQ(end_rect.bottom_left(), GetLastEventAnchor()); 362 EXPECT_EQ(end_rect.bottom_left(), GetLastEventAnchor());
363 } 363 }
364 364
365 TEST_F(TouchSelectionControllerTest, InsertionDragged) { 365 TEST_F(TouchSelectionControllerTest, InsertionDragged) {
366 base::TimeTicks event_time = base::TimeTicks::Now(); 366 base::TimeTicks event_time = base::TimeTicks::Now();
367 controller().OnTapEvent(); 367 controller().OnTapEvent();
368 controller().OnSelectionEditable(true); 368 controller().OnSelectionEditable(true);
369 369
370 // The touch sequence should not be handled if insertion is not active. 370 // The touch sequence should not be handled if insertion is not active.
371 MockMotionEvent event(MockMotionEvent::ACTION_DOWN, event_time, 0, 0); 371 MockMotionEvent event(MockMotionEvent::ACTION_DOWN, event_time, 0, 0);
372 EXPECT_FALSE(controller().WillHandleTouchEvent(event)); 372 EXPECT_FALSE(controller().WillHandleTouchEvent(event));
373 373
374 float line_height = 10.f; 374 float line_height = 10.f;
375 gfx::RectF start_rect(10, 0, 0, line_height); 375 gfx::RectF start_rect(10, 0, 0, line_height);
376 bool visible = true; 376 bool visible = true;
377 ChangeInsertion(start_rect, visible); 377 EXPECT_TRUE(ChangeInsertion(start_rect, visible));
378 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_SHOWN)); 378 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_SHOWN));
379 EXPECT_EQ(start_rect.bottom_left(), GetLastEventAnchor()); 379 EXPECT_EQ(start_rect.bottom_left(), GetLastEventAnchor());
380 380
381 // The touch sequence should be handled only if the drawable reports a hit. 381 // The touch sequence should be handled only if the drawable reports a hit.
382 EXPECT_FALSE(controller().WillHandleTouchEvent(event)); 382 EXPECT_FALSE(controller().WillHandleTouchEvent(event));
383 SetDraggingEnabled(true); 383 SetDraggingEnabled(true);
384 EXPECT_TRUE(controller().WillHandleTouchEvent(event)); 384 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
385 EXPECT_FALSE(GetAndResetCaretMoved()); 385 EXPECT_FALSE(GetAndResetCaretMoved());
386 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_DRAG_STARTED)); 386 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_DRAG_STARTED));
387 387
(...skipping 26 matching lines...) Expand all
414 } 414 }
415 415
416 TEST_F(TouchSelectionControllerTest, InsertionTapped) { 416 TEST_F(TouchSelectionControllerTest, InsertionTapped) {
417 base::TimeTicks event_time = base::TimeTicks::Now(); 417 base::TimeTicks event_time = base::TimeTicks::Now();
418 controller().OnTapEvent(); 418 controller().OnTapEvent();
419 controller().OnSelectionEditable(true); 419 controller().OnSelectionEditable(true);
420 SetDraggingEnabled(true); 420 SetDraggingEnabled(true);
421 421
422 gfx::RectF start_rect(10, 0, 0, 10); 422 gfx::RectF start_rect(10, 0, 0, 10);
423 bool visible = true; 423 bool visible = true;
424 ChangeInsertion(start_rect, visible); 424 EXPECT_TRUE(ChangeInsertion(start_rect, visible));
425 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_SHOWN)); 425 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_SHOWN));
426 426
427 MockMotionEvent event(MockMotionEvent::ACTION_DOWN, event_time, 0, 0); 427 MockMotionEvent event(MockMotionEvent::ACTION_DOWN, event_time, 0, 0);
428 EXPECT_TRUE(controller().WillHandleTouchEvent(event)); 428 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
429 //TODO(AKV): this test case has to be modified once crbug.com/394093 is fixed. 429 //TODO(AKV): this test case has to be modified once crbug.com/394093 is fixed.
430 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_DRAG_STARTED)); 430 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_DRAG_STARTED));
431 431
432 event = MockMotionEvent(MockMotionEvent::ACTION_UP, event_time, 0, 0); 432 event = MockMotionEvent(MockMotionEvent::ACTION_UP, event_time, 0, 0);
433 EXPECT_TRUE(controller().WillHandleTouchEvent(event)); 433 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
434 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_TAPPED, 434 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_TAPPED,
435 INSERTION_DRAG_STOPPED)); 435 INSERTION_DRAG_STOPPED));
436 436
437 // Reset the insertion. 437 // Reset the insertion.
438 ClearInsertion(); 438 EXPECT_TRUE(ClearInsertion());
439 controller().OnTapEvent(); 439 controller().OnTapEvent();
440 ChangeInsertion(start_rect, visible); 440 EXPECT_TRUE(ChangeInsertion(start_rect, visible));
441 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_CLEARED, 441 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_CLEARED,
442 INSERTION_SHOWN)); 442 INSERTION_SHOWN));
443 443
444 // No tap should be signalled if the time between DOWN and UP was too long. 444 // No tap should be signalled if the time between DOWN and UP was too long.
445 event = MockMotionEvent(MockMotionEvent::ACTION_DOWN, event_time, 0, 0); 445 event = MockMotionEvent(MockMotionEvent::ACTION_DOWN, event_time, 0, 0);
446 EXPECT_TRUE(controller().WillHandleTouchEvent(event)); 446 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
447 event = MockMotionEvent(MockMotionEvent::ACTION_UP, 447 event = MockMotionEvent(MockMotionEvent::ACTION_UP,
448 event_time + base::TimeDelta::FromSeconds(1), 448 event_time + base::TimeDelta::FromSeconds(1),
449 0, 449 0,
450 0); 450 0);
451 EXPECT_TRUE(controller().WillHandleTouchEvent(event)); 451 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
452 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_DRAG_STARTED, 452 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_DRAG_STARTED,
453 INSERTION_DRAG_STOPPED)); 453 INSERTION_DRAG_STOPPED));
454 454
455 // Reset the insertion. 455 // Reset the insertion.
456 ClearInsertion(); 456 EXPECT_TRUE(ClearInsertion());
457 controller().OnTapEvent(); 457 controller().OnTapEvent();
458 ChangeInsertion(start_rect, visible); 458 EXPECT_TRUE(ChangeInsertion(start_rect, visible));
459 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_CLEARED, 459 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_CLEARED,
460 INSERTION_SHOWN)); 460 INSERTION_SHOWN));
461 461
462 // No tap should be signalled if the drag was too long. 462 // No tap should be signalled if the drag was too long.
463 event = MockMotionEvent(MockMotionEvent::ACTION_DOWN, event_time, 0, 0); 463 event = MockMotionEvent(MockMotionEvent::ACTION_DOWN, event_time, 0, 0);
464 EXPECT_TRUE(controller().WillHandleTouchEvent(event)); 464 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
465 event = MockMotionEvent(MockMotionEvent::ACTION_MOVE, event_time, 100, 0); 465 event = MockMotionEvent(MockMotionEvent::ACTION_MOVE, event_time, 100, 0);
466 EXPECT_TRUE(controller().WillHandleTouchEvent(event)); 466 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
467 event = MockMotionEvent(MockMotionEvent::ACTION_UP, event_time, 100, 0); 467 event = MockMotionEvent(MockMotionEvent::ACTION_UP, event_time, 100, 0);
468 EXPECT_TRUE(controller().WillHandleTouchEvent(event)); 468 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
469 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_DRAG_STARTED, 469 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_DRAG_STARTED,
470 INSERTION_DRAG_STOPPED)); 470 INSERTION_DRAG_STOPPED));
471 471
472 // Reset the insertion. 472 // Reset the insertion.
473 ClearInsertion(); 473 EXPECT_TRUE(ClearInsertion());
474 controller().OnTapEvent(); 474 controller().OnTapEvent();
475 ChangeInsertion(start_rect, visible); 475 EXPECT_TRUE(ChangeInsertion(start_rect, visible));
476 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_CLEARED, 476 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_CLEARED,
477 INSERTION_SHOWN)); 477 INSERTION_SHOWN));
478 478
479 // No tap should be signalled if the touch sequence is cancelled. 479 // No tap should be signalled if the touch sequence is cancelled.
480 event = MockMotionEvent(MockMotionEvent::ACTION_DOWN, event_time, 0, 0); 480 event = MockMotionEvent(MockMotionEvent::ACTION_DOWN, event_time, 0, 0);
481 EXPECT_TRUE(controller().WillHandleTouchEvent(event)); 481 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
482 event = MockMotionEvent(MockMotionEvent::ACTION_CANCEL, event_time, 0, 0); 482 event = MockMotionEvent(MockMotionEvent::ACTION_CANCEL, event_time, 0, 0);
483 EXPECT_TRUE(controller().WillHandleTouchEvent(event)); 483 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
484 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_DRAG_STARTED, 484 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_DRAG_STARTED,
485 INSERTION_DRAG_STOPPED)); 485 INSERTION_DRAG_STOPPED));
486 } 486 }
487 487
488 TEST_F(TouchSelectionControllerTest, InsertionNotResetByRepeatedTapOrPress) { 488 TEST_F(TouchSelectionControllerTest, InsertionNotResetByRepeatedTapOrPress) {
489 base::TimeTicks event_time = base::TimeTicks::Now(); 489 base::TimeTicks event_time = base::TimeTicks::Now();
490 controller().OnTapEvent(); 490 controller().OnTapEvent();
491 controller().OnSelectionEditable(true); 491 controller().OnSelectionEditable(true);
492 SetDraggingEnabled(true); 492 SetDraggingEnabled(true);
493 493
494 gfx::RectF anchor_rect(10, 0, 0, 10); 494 gfx::RectF anchor_rect(10, 0, 0, 10);
495 bool visible = true; 495 bool visible = true;
496 ChangeInsertion(anchor_rect, visible); 496 EXPECT_TRUE(ChangeInsertion(anchor_rect, visible));
497 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_SHOWN)); 497 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_SHOWN));
498 EXPECT_EQ(anchor_rect.bottom_left(), GetLastEventAnchor()); 498 EXPECT_EQ(anchor_rect.bottom_left(), GetLastEventAnchor());
499 499
500 // Tapping again shouldn't reset the active insertion point. 500 // Tapping again shouldn't reset the active insertion point.
501 controller().OnTapEvent(); 501 controller().OnTapEvent();
502 MockMotionEvent event(MockMotionEvent::ACTION_DOWN, event_time, 0, 0); 502 MockMotionEvent event(MockMotionEvent::ACTION_DOWN, event_time, 0, 0);
503 EXPECT_TRUE(controller().WillHandleTouchEvent(event)); 503 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
504 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_DRAG_STARTED)); 504 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_DRAG_STARTED));
505 EXPECT_EQ(anchor_rect.bottom_left(), GetLastEventAnchor()); 505 EXPECT_EQ(anchor_rect.bottom_left(), GetLastEventAnchor());
506 506
507 event = MockMotionEvent(MockMotionEvent::ACTION_UP, event_time, 0, 0); 507 event = MockMotionEvent(MockMotionEvent::ACTION_UP, event_time, 0, 0);
508 EXPECT_TRUE(controller().WillHandleTouchEvent(event)); 508 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
509 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_TAPPED, 509 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_TAPPED,
510 INSERTION_DRAG_STOPPED)); 510 INSERTION_DRAG_STOPPED));
511 EXPECT_EQ(anchor_rect.bottom_left(), GetLastEventAnchor()); 511 EXPECT_EQ(anchor_rect.bottom_left(), GetLastEventAnchor());
512 512
513 anchor_rect.Offset(5, 15); 513 anchor_rect.Offset(5, 15);
514 ChangeInsertion(anchor_rect, visible); 514 EXPECT_TRUE(ChangeInsertion(anchor_rect, visible));
515 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_MOVED)); 515 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_MOVED));
516 EXPECT_EQ(anchor_rect.bottom_left(), GetLastEventAnchor()); 516 EXPECT_EQ(anchor_rect.bottom_left(), GetLastEventAnchor());
517 517
518 // Pressing shouldn't reset the active insertion point. 518 // Pressing shouldn't reset the active insertion point.
519 controller().OnLongPressEvent(); 519 controller().OnLongPressEvent();
520 controller().OnSelectionEmpty(true); 520 controller().OnSelectionEmpty(true);
521 event = MockMotionEvent(MockMotionEvent::ACTION_DOWN, event_time, 0, 0); 521 event = MockMotionEvent(MockMotionEvent::ACTION_DOWN, event_time, 0, 0);
522 EXPECT_TRUE(controller().WillHandleTouchEvent(event)); 522 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
523 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_DRAG_STARTED)); 523 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_DRAG_STARTED));
524 EXPECT_EQ(anchor_rect.bottom_left(), GetLastEventAnchor()); 524 EXPECT_EQ(anchor_rect.bottom_left(), GetLastEventAnchor());
525 525
526 event = MockMotionEvent(MockMotionEvent::ACTION_UP, event_time, 0, 0); 526 event = MockMotionEvent(MockMotionEvent::ACTION_UP, event_time, 0, 0);
527 EXPECT_TRUE(controller().WillHandleTouchEvent(event)); 527 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
528 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_TAPPED, 528 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_TAPPED,
529 INSERTION_DRAG_STOPPED)); 529 INSERTION_DRAG_STOPPED));
530 EXPECT_EQ(anchor_rect.bottom_left(), GetLastEventAnchor()); 530 EXPECT_EQ(anchor_rect.bottom_left(), GetLastEventAnchor());
531 } 531 }
532 532
533 TEST_F(TouchSelectionControllerTest, SelectionBasic) { 533 TEST_F(TouchSelectionControllerTest, SelectionBasic) {
534 gfx::RectF start_rect(5, 5, 0, 10); 534 gfx::RectF start_rect(5, 5, 0, 10);
535 gfx::RectF end_rect(50, 5, 0, 10); 535 gfx::RectF end_rect(50, 5, 0, 10);
536 bool visible = true; 536 bool visible = true;
537 537
538 // Selection events are ignored until automatic showing is enabled. 538 // Selection events are ignored until automatic showing is enabled.
539 ChangeSelection(start_rect, visible, end_rect, visible); 539 EXPECT_FALSE(ChangeSelection(start_rect, visible, end_rect, visible));
540 EXPECT_EQ(gfx::PointF(), GetLastEventAnchor()); 540 EXPECT_EQ(gfx::PointF(), GetLastEventAnchor());
541 541
542 controller().OnLongPressEvent(); 542 controller().OnLongPressEvent();
543 ChangeSelection(start_rect, visible, end_rect, visible); 543 EXPECT_TRUE(ChangeSelection(start_rect, visible, end_rect, visible));
544 EXPECT_THAT(GetAndResetEvents(), ElementsAre(SELECTION_SHOWN)); 544 EXPECT_THAT(GetAndResetEvents(), ElementsAre(SELECTION_SHOWN));
545 EXPECT_EQ(start_rect.bottom_left(), GetLastEventAnchor()); 545 EXPECT_EQ(start_rect.bottom_left(), GetLastEventAnchor());
546 546
547 start_rect.Offset(1, 0); 547 start_rect.Offset(1, 0);
548 ChangeSelection(start_rect, visible, end_rect, visible); 548 EXPECT_TRUE(ChangeSelection(start_rect, visible, end_rect, visible));
549 // Selection movement does not currently trigger a separate event. 549 // Selection movement does not currently trigger a separate event.
550 EXPECT_THAT(GetAndResetEvents(), IsEmpty()); 550 EXPECT_THAT(GetAndResetEvents(), IsEmpty());
551 551
552 ClearSelection(); 552 EXPECT_TRUE(ClearSelection());
553 EXPECT_THAT(GetAndResetEvents(), ElementsAre(SELECTION_CLEARED)); 553 EXPECT_THAT(GetAndResetEvents(), ElementsAre(SELECTION_CLEARED));
554 EXPECT_EQ(gfx::PointF(), GetLastEventAnchor()); 554 EXPECT_EQ(gfx::PointF(), GetLastEventAnchor());
555 } 555 }
556 556
557 TEST_F(TouchSelectionControllerTest, SelectionRepeatedLongPress) { 557 TEST_F(TouchSelectionControllerTest, SelectionRepeatedLongPress) {
558 gfx::RectF start_rect(5, 5, 0, 10); 558 gfx::RectF start_rect(5, 5, 0, 10);
559 gfx::RectF end_rect(50, 5, 0, 10); 559 gfx::RectF end_rect(50, 5, 0, 10);
560 bool visible = true; 560 bool visible = true;
561 561
562 controller().OnLongPressEvent(); 562 controller().OnLongPressEvent();
563 ChangeSelection(start_rect, visible, end_rect, visible); 563 EXPECT_TRUE(ChangeSelection(start_rect, visible, end_rect, visible));
564 EXPECT_THAT(GetAndResetEvents(), ElementsAre(SELECTION_SHOWN)); 564 EXPECT_THAT(GetAndResetEvents(), ElementsAre(SELECTION_SHOWN));
565 EXPECT_EQ(start_rect.bottom_left(), GetLastEventAnchor()); 565 EXPECT_EQ(start_rect.bottom_left(), GetLastEventAnchor());
566 566
567 // A long press triggering a new selection should re-send the SELECTION_SHOWN 567 // A long press triggering a new selection should re-send the SELECTION_SHOWN
568 // event notification. 568 // event notification.
569 start_rect.Offset(10, 10); 569 start_rect.Offset(10, 10);
570 controller().OnLongPressEvent(); 570 controller().OnLongPressEvent();
571 ChangeSelection(start_rect, visible, end_rect, visible); 571 EXPECT_TRUE(ChangeSelection(start_rect, visible, end_rect, visible));
572 EXPECT_THAT(GetAndResetEvents(), ElementsAre(SELECTION_SHOWN)); 572 EXPECT_THAT(GetAndResetEvents(), ElementsAre(SELECTION_SHOWN));
573 EXPECT_EQ(start_rect.bottom_left(), GetLastEventAnchor()); 573 EXPECT_EQ(start_rect.bottom_left(), GetLastEventAnchor());
574 } 574 }
575 575
576 TEST_F(TouchSelectionControllerTest, SelectionDragged) { 576 TEST_F(TouchSelectionControllerTest, SelectionDragged) {
577 base::TimeTicks event_time = base::TimeTicks::Now(); 577 base::TimeTicks event_time = base::TimeTicks::Now();
578 controller().OnLongPressEvent(); 578 controller().OnLongPressEvent();
579 579
580 // The touch sequence should not be handled if selection is not active. 580 // The touch sequence should not be handled if selection is not active.
581 MockMotionEvent event(MockMotionEvent::ACTION_DOWN, event_time, 0, 0); 581 MockMotionEvent event(MockMotionEvent::ACTION_DOWN, event_time, 0, 0);
582 EXPECT_FALSE(controller().WillHandleTouchEvent(event)); 582 EXPECT_FALSE(controller().WillHandleTouchEvent(event));
583 583
584 float line_height = 10.f; 584 float line_height = 10.f;
585 gfx::RectF start_rect(0, 0, 0, line_height); 585 gfx::RectF start_rect(0, 0, 0, line_height);
586 gfx::RectF end_rect(50, 0, 0, line_height); 586 gfx::RectF end_rect(50, 0, 0, line_height);
587 bool visible = true; 587 bool visible = true;
588 ChangeSelection(start_rect, visible, end_rect, visible); 588 EXPECT_TRUE(ChangeSelection(start_rect, visible, end_rect, visible));
589 EXPECT_THAT(GetAndResetEvents(), ElementsAre(SELECTION_SHOWN)); 589 EXPECT_THAT(GetAndResetEvents(), ElementsAre(SELECTION_SHOWN));
590 EXPECT_EQ(start_rect.bottom_left(), GetLastEventAnchor()); 590 EXPECT_EQ(start_rect.bottom_left(), GetLastEventAnchor());
591 591
592 // The touch sequence should be handled only if the drawable reports a hit. 592 // The touch sequence should be handled only if the drawable reports a hit.
593 EXPECT_FALSE(controller().WillHandleTouchEvent(event)); 593 EXPECT_FALSE(controller().WillHandleTouchEvent(event));
594 SetDraggingEnabled(true); 594 SetDraggingEnabled(true);
595 EXPECT_TRUE(controller().WillHandleTouchEvent(event)); 595 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
596 EXPECT_FALSE(GetAndResetSelectionMoved()); 596 EXPECT_FALSE(GetAndResetSelectionMoved());
597 597
598 // The SelectBetweenCoordinates() result should reflect the movement. Note 598 // The SelectBetweenCoordinates() result should reflect the movement. Note
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
632 } 632 }
633 633
634 TEST_F(TouchSelectionControllerTest, SelectionDraggedWithOverlap) { 634 TEST_F(TouchSelectionControllerTest, SelectionDraggedWithOverlap) {
635 base::TimeTicks event_time = base::TimeTicks::Now(); 635 base::TimeTicks event_time = base::TimeTicks::Now();
636 controller().OnLongPressEvent(); 636 controller().OnLongPressEvent();
637 637
638 float line_height = 10.f; 638 float line_height = 10.f;
639 gfx::RectF start_rect(0, 0, 0, line_height); 639 gfx::RectF start_rect(0, 0, 0, line_height);
640 gfx::RectF end_rect(50, 0, 0, line_height); 640 gfx::RectF end_rect(50, 0, 0, line_height);
641 bool visible = true; 641 bool visible = true;
642 ChangeSelection(start_rect, visible, end_rect, visible); 642 EXPECT_TRUE(ChangeSelection(start_rect, visible, end_rect, visible));
643 EXPECT_THAT(GetAndResetEvents(), ElementsAre(SELECTION_SHOWN)); 643 EXPECT_THAT(GetAndResetEvents(), ElementsAre(SELECTION_SHOWN));
644 EXPECT_EQ(start_rect.bottom_left(), GetLastEventAnchor()); 644 EXPECT_EQ(start_rect.bottom_left(), GetLastEventAnchor());
645 645
646 // The ACTION_DOWN should lock to the closest handle. 646 // The ACTION_DOWN should lock to the closest handle.
647 gfx::PointF end_offset = end_rect.CenterPoint(); 647 gfx::PointF end_offset = end_rect.CenterPoint();
648 gfx::PointF fixed_offset = start_rect.CenterPoint(); 648 gfx::PointF fixed_offset = start_rect.CenterPoint();
649 float touch_down_x = (end_offset.x() + fixed_offset.x()) / 2 + 1.f; 649 float touch_down_x = (end_offset.x() + fixed_offset.x()) / 2 + 1.f;
650 MockMotionEvent event( 650 MockMotionEvent event(
651 MockMotionEvent::ACTION_DOWN, event_time, touch_down_x, 0); 651 MockMotionEvent::ACTION_DOWN, event_time, touch_down_x, 0);
652 SetDraggingEnabled(true); 652 SetDraggingEnabled(true);
(...skipping 17 matching lines...) Expand all
670 } 670 }
671 671
672 TEST_F(TouchSelectionControllerTest, SelectionDraggedToSwitchBaseAndExtent) { 672 TEST_F(TouchSelectionControllerTest, SelectionDraggedToSwitchBaseAndExtent) {
673 base::TimeTicks event_time = base::TimeTicks::Now(); 673 base::TimeTicks event_time = base::TimeTicks::Now();
674 controller().OnLongPressEvent(); 674 controller().OnLongPressEvent();
675 675
676 float line_height = 10.f; 676 float line_height = 10.f;
677 gfx::RectF start_rect(50, line_height, 0, line_height); 677 gfx::RectF start_rect(50, line_height, 0, line_height);
678 gfx::RectF end_rect(100, line_height, 0, line_height); 678 gfx::RectF end_rect(100, line_height, 0, line_height);
679 bool visible = true; 679 bool visible = true;
680 ChangeSelection(start_rect, visible, end_rect, visible); 680 EXPECT_TRUE(ChangeSelection(start_rect, visible, end_rect, visible));
681 EXPECT_THAT(GetAndResetEvents(), ElementsAre(SELECTION_SHOWN)); 681 EXPECT_THAT(GetAndResetEvents(), ElementsAre(SELECTION_SHOWN));
682 EXPECT_EQ(start_rect.bottom_left(), GetLastEventAnchor()); 682 EXPECT_EQ(start_rect.bottom_left(), GetLastEventAnchor());
683 683
684 SetDraggingEnabled(true); 684 SetDraggingEnabled(true);
685 685
686 // Move the extent, not triggering a swap of points. 686 // Move the extent, not triggering a swap of points.
687 MockMotionEvent event(MockMotionEvent::ACTION_DOWN, event_time, 687 MockMotionEvent event(MockMotionEvent::ACTION_DOWN, event_time,
688 end_rect.x(), end_rect.bottom()); 688 end_rect.x(), end_rect.bottom());
689 EXPECT_TRUE(controller().WillHandleTouchEvent(event)); 689 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
690 EXPECT_FALSE(GetAndResetSelectionMoved()); 690 EXPECT_FALSE(GetAndResetSelectionMoved());
691 EXPECT_FALSE(GetAndResetSelectionPointsSwapped()); 691 EXPECT_FALSE(GetAndResetSelectionPointsSwapped());
692 692
693 gfx::PointF base_offset = start_rect.CenterPoint(); 693 gfx::PointF base_offset = start_rect.CenterPoint();
694 gfx::PointF extent_offset = end_rect.CenterPoint(); 694 gfx::PointF extent_offset = end_rect.CenterPoint();
695 event = MockMotionEvent(MockMotionEvent::ACTION_MOVE, event_time, 695 event = MockMotionEvent(MockMotionEvent::ACTION_MOVE, event_time,
696 end_rect.x(), end_rect.bottom() + 5); 696 end_rect.x(), end_rect.bottom() + 5);
697 EXPECT_TRUE(controller().WillHandleTouchEvent(event)); 697 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
698 EXPECT_THAT(GetAndResetEvents(), ElementsAre(SELECTION_DRAG_STARTED)); 698 EXPECT_THAT(GetAndResetEvents(), ElementsAre(SELECTION_DRAG_STARTED));
699 EXPECT_TRUE(GetAndResetSelectionMoved()); 699 EXPECT_TRUE(GetAndResetSelectionMoved());
700 EXPECT_FALSE(GetAndResetSelectionPointsSwapped()); 700 EXPECT_FALSE(GetAndResetSelectionPointsSwapped());
701 EXPECT_EQ(base_offset, GetLastSelectionStart()); 701 EXPECT_EQ(base_offset, GetLastSelectionStart());
702 EXPECT_EQ(extent_offset + gfx::Vector2dF(0, 5), GetLastSelectionEnd()); 702 EXPECT_EQ(extent_offset + gfx::Vector2dF(0, 5), GetLastSelectionEnd());
703 703
704 event = MockMotionEvent(MockMotionEvent::ACTION_UP, event_time, 10, 5); 704 event = MockMotionEvent(MockMotionEvent::ACTION_UP, event_time, 10, 5);
705 EXPECT_TRUE(controller().WillHandleTouchEvent(event)); 705 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
706 EXPECT_THAT(GetAndResetEvents(), ElementsAre(SELECTION_DRAG_STOPPED)); 706 EXPECT_THAT(GetAndResetEvents(), ElementsAre(SELECTION_DRAG_STOPPED));
707 EXPECT_FALSE(GetAndResetSelectionMoved()); 707 EXPECT_FALSE(GetAndResetSelectionMoved());
708 708
709 end_rect += gfx::Vector2dF(0, 5); 709 end_rect += gfx::Vector2dF(0, 5);
710 ChangeSelection(start_rect, visible, end_rect, visible); 710 EXPECT_TRUE(ChangeSelection(start_rect, visible, end_rect, visible));
711 711
712 // Move the base, triggering a swap of points. 712 // Move the base, triggering a swap of points.
713 event = MockMotionEvent(MockMotionEvent::ACTION_DOWN, event_time, 713 event = MockMotionEvent(MockMotionEvent::ACTION_DOWN, event_time,
714 start_rect.x(), start_rect.bottom()); 714 start_rect.x(), start_rect.bottom());
715 EXPECT_TRUE(controller().WillHandleTouchEvent(event)); 715 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
716 EXPECT_FALSE(GetAndResetSelectionMoved()); 716 EXPECT_FALSE(GetAndResetSelectionMoved());
717 EXPECT_TRUE(GetAndResetSelectionPointsSwapped()); 717 EXPECT_TRUE(GetAndResetSelectionPointsSwapped());
718 718
719 base_offset = end_rect.CenterPoint(); 719 base_offset = end_rect.CenterPoint();
720 extent_offset = start_rect.CenterPoint(); 720 extent_offset = start_rect.CenterPoint();
721 event = MockMotionEvent(MockMotionEvent::ACTION_MOVE, event_time, 721 event = MockMotionEvent(MockMotionEvent::ACTION_MOVE, event_time,
722 start_rect.x(), start_rect.bottom() + 5); 722 start_rect.x(), start_rect.bottom() + 5);
723 EXPECT_TRUE(controller().WillHandleTouchEvent(event)); 723 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
724 EXPECT_THAT(GetAndResetEvents(), ElementsAre(SELECTION_DRAG_STARTED)); 724 EXPECT_THAT(GetAndResetEvents(), ElementsAre(SELECTION_DRAG_STARTED));
725 EXPECT_TRUE(GetAndResetSelectionMoved()); 725 EXPECT_TRUE(GetAndResetSelectionMoved());
726 EXPECT_FALSE(GetAndResetSelectionPointsSwapped()); 726 EXPECT_FALSE(GetAndResetSelectionPointsSwapped());
727 EXPECT_EQ(base_offset, GetLastSelectionStart()); 727 EXPECT_EQ(base_offset, GetLastSelectionStart());
728 EXPECT_EQ(extent_offset + gfx::Vector2dF(0, 5), GetLastSelectionEnd()); 728 EXPECT_EQ(extent_offset + gfx::Vector2dF(0, 5), GetLastSelectionEnd());
729 729
730 event = MockMotionEvent(MockMotionEvent::ACTION_UP, event_time, 10, 5); 730 event = MockMotionEvent(MockMotionEvent::ACTION_UP, event_time, 10, 5);
731 EXPECT_TRUE(controller().WillHandleTouchEvent(event)); 731 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
732 EXPECT_THAT(GetAndResetEvents(), ElementsAre(SELECTION_DRAG_STOPPED)); 732 EXPECT_THAT(GetAndResetEvents(), ElementsAre(SELECTION_DRAG_STOPPED));
733 EXPECT_FALSE(GetAndResetSelectionMoved()); 733 EXPECT_FALSE(GetAndResetSelectionMoved());
734 734
735 start_rect += gfx::Vector2dF(0, 5); 735 start_rect += gfx::Vector2dF(0, 5);
736 ChangeSelection(start_rect, visible, end_rect, visible); 736 EXPECT_TRUE(ChangeSelection(start_rect, visible, end_rect, visible));
737 737
738 // Move the same point again, not triggering a swap of points. 738 // Move the same point again, not triggering a swap of points.
739 event = MockMotionEvent(MockMotionEvent::ACTION_DOWN, event_time, 739 event = MockMotionEvent(MockMotionEvent::ACTION_DOWN, event_time,
740 start_rect.x(), start_rect.bottom()); 740 start_rect.x(), start_rect.bottom());
741 EXPECT_TRUE(controller().WillHandleTouchEvent(event)); 741 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
742 EXPECT_FALSE(GetAndResetSelectionMoved()); 742 EXPECT_FALSE(GetAndResetSelectionMoved());
743 EXPECT_FALSE(GetAndResetSelectionPointsSwapped()); 743 EXPECT_FALSE(GetAndResetSelectionPointsSwapped());
744 744
745 base_offset = end_rect.CenterPoint(); 745 base_offset = end_rect.CenterPoint();
746 extent_offset = start_rect.CenterPoint(); 746 extent_offset = start_rect.CenterPoint();
747 event = MockMotionEvent(MockMotionEvent::ACTION_MOVE, event_time, 747 event = MockMotionEvent(MockMotionEvent::ACTION_MOVE, event_time,
748 start_rect.x(), start_rect.bottom() + 5); 748 start_rect.x(), start_rect.bottom() + 5);
749 EXPECT_TRUE(controller().WillHandleTouchEvent(event)); 749 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
750 EXPECT_THAT(GetAndResetEvents(), ElementsAre(SELECTION_DRAG_STARTED)); 750 EXPECT_THAT(GetAndResetEvents(), ElementsAre(SELECTION_DRAG_STARTED));
751 EXPECT_TRUE(GetAndResetSelectionMoved()); 751 EXPECT_TRUE(GetAndResetSelectionMoved());
752 EXPECT_FALSE(GetAndResetSelectionPointsSwapped()); 752 EXPECT_FALSE(GetAndResetSelectionPointsSwapped());
753 EXPECT_EQ(base_offset, GetLastSelectionStart()); 753 EXPECT_EQ(base_offset, GetLastSelectionStart());
754 EXPECT_EQ(extent_offset + gfx::Vector2dF(0, 5), GetLastSelectionEnd()); 754 EXPECT_EQ(extent_offset + gfx::Vector2dF(0, 5), GetLastSelectionEnd());
755 755
756 event = MockMotionEvent(MockMotionEvent::ACTION_UP, event_time, 10, 5); 756 event = MockMotionEvent(MockMotionEvent::ACTION_UP, event_time, 10, 5);
757 EXPECT_TRUE(controller().WillHandleTouchEvent(event)); 757 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
758 EXPECT_THAT(GetAndResetEvents(), ElementsAre(SELECTION_DRAG_STOPPED)); 758 EXPECT_THAT(GetAndResetEvents(), ElementsAre(SELECTION_DRAG_STOPPED));
759 EXPECT_FALSE(GetAndResetSelectionMoved()); 759 EXPECT_FALSE(GetAndResetSelectionMoved());
760 760
761 start_rect += gfx::Vector2dF(0, 5); 761 start_rect += gfx::Vector2dF(0, 5);
762 ChangeSelection(start_rect, visible, end_rect, visible); 762 EXPECT_TRUE(ChangeSelection(start_rect, visible, end_rect, visible));
763 763
764 // Move the base, triggering a swap of points. 764 // Move the base, triggering a swap of points.
765 event = MockMotionEvent(MockMotionEvent::ACTION_DOWN, event_time, 765 event = MockMotionEvent(MockMotionEvent::ACTION_DOWN, event_time,
766 end_rect.x(), end_rect.bottom()); 766 end_rect.x(), end_rect.bottom());
767 EXPECT_TRUE(controller().WillHandleTouchEvent(event)); 767 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
768 EXPECT_FALSE(GetAndResetSelectionMoved()); 768 EXPECT_FALSE(GetAndResetSelectionMoved());
769 EXPECT_TRUE(GetAndResetSelectionPointsSwapped()); 769 EXPECT_TRUE(GetAndResetSelectionPointsSwapped());
770 770
771 base_offset = start_rect.CenterPoint(); 771 base_offset = start_rect.CenterPoint();
772 extent_offset = end_rect.CenterPoint(); 772 extent_offset = end_rect.CenterPoint();
(...skipping 14 matching lines...) Expand all
787 787
788 TEST_F(TouchSelectionControllerTest, SelectionDragExtremeLineSize) { 788 TEST_F(TouchSelectionControllerTest, SelectionDragExtremeLineSize) {
789 base::TimeTicks event_time = base::TimeTicks::Now(); 789 base::TimeTicks event_time = base::TimeTicks::Now();
790 controller().OnLongPressEvent(); 790 controller().OnLongPressEvent();
791 791
792 float small_line_height = 1.f; 792 float small_line_height = 1.f;
793 float large_line_height = 50.f; 793 float large_line_height = 50.f;
794 gfx::RectF small_line_rect(0, 0, 0, small_line_height); 794 gfx::RectF small_line_rect(0, 0, 0, small_line_height);
795 gfx::RectF large_line_rect(50, 50, 0, large_line_height); 795 gfx::RectF large_line_rect(50, 50, 0, large_line_height);
796 bool visible = true; 796 bool visible = true;
797 ChangeSelection(small_line_rect, visible, large_line_rect, visible); 797 EXPECT_TRUE(
798 ChangeSelection(small_line_rect, visible, large_line_rect, visible));
798 EXPECT_THAT(GetAndResetEvents(), ElementsAre(SELECTION_SHOWN)); 799 EXPECT_THAT(GetAndResetEvents(), ElementsAre(SELECTION_SHOWN));
799 EXPECT_EQ(small_line_rect.bottom_left(), GetLastEventAnchor()); 800 EXPECT_EQ(small_line_rect.bottom_left(), GetLastEventAnchor());
800 801
801 // Start dragging the handle on the small line. 802 // Start dragging the handle on the small line.
802 MockMotionEvent event(MockMotionEvent::ACTION_DOWN, event_time, 803 MockMotionEvent event(MockMotionEvent::ACTION_DOWN, event_time,
803 small_line_rect.x(), small_line_rect.y()); 804 small_line_rect.x(), small_line_rect.y());
804 SetDraggingEnabled(true); 805 SetDraggingEnabled(true);
805 EXPECT_TRUE(controller().WillHandleTouchEvent(event)); 806 EXPECT_TRUE(controller().WillHandleTouchEvent(event));
806 EXPECT_THAT(GetAndResetEvents(), ElementsAre(SELECTION_DRAG_STARTED)); 807 EXPECT_THAT(GetAndResetEvents(), ElementsAre(SELECTION_DRAG_STARTED));
807 // The drag coordinate for large lines should be capped to a reasonable 808 // The drag coordinate for large lines should be capped to a reasonable
(...skipping 12 matching lines...) Expand all
820 EXPECT_EQ(small_line_rect.CenterPoint(), GetLastSelectionEnd()); 821 EXPECT_EQ(small_line_rect.CenterPoint(), GetLastSelectionEnd());
821 } 822 }
822 823
823 TEST_F(TouchSelectionControllerTest, Animation) { 824 TEST_F(TouchSelectionControllerTest, Animation) {
824 controller().OnTapEvent(); 825 controller().OnTapEvent();
825 controller().OnSelectionEditable(true); 826 controller().OnSelectionEditable(true);
826 827
827 gfx::RectF insertion_rect(5, 5, 0, 10); 828 gfx::RectF insertion_rect(5, 5, 0, 10);
828 829
829 bool visible = true; 830 bool visible = true;
830 ChangeInsertion(insertion_rect, visible); 831 EXPECT_TRUE(ChangeInsertion(insertion_rect, visible));
831 EXPECT_FALSE(GetAndResetNeedsAnimate()); 832 EXPECT_FALSE(GetAndResetNeedsAnimate());
832 833
833 visible = false; 834 visible = false;
834 ChangeInsertion(insertion_rect, visible); 835 EXPECT_TRUE(ChangeInsertion(insertion_rect, visible));
835 EXPECT_TRUE(GetAndResetNeedsAnimate()); 836 EXPECT_TRUE(GetAndResetNeedsAnimate());
836 837
837 visible = true; 838 visible = true;
838 ChangeInsertion(insertion_rect, visible); 839 EXPECT_TRUE(ChangeInsertion(insertion_rect, visible));
839 EXPECT_TRUE(GetAndResetNeedsAnimate()); 840 EXPECT_TRUE(GetAndResetNeedsAnimate());
840 841
841 // If the handles are explicity hidden, no animation should be triggered. 842 // If the handles are explicity hidden, no animation should be triggered.
842 controller().HideAndDisallowShowingAutomatically(); 843 controller().HideAndDisallowShowingAutomatically();
843 EXPECT_FALSE(GetAndResetNeedsAnimate()); 844 EXPECT_FALSE(GetAndResetNeedsAnimate());
844 845
845 // If the client doesn't support animation, no animation should be triggered. 846 // If the client doesn't support animation, no animation should be triggered.
846 SetAnimationEnabled(false); 847 SetAnimationEnabled(false);
847 controller().OnTapEvent(); 848 controller().OnTapEvent();
848 visible = true; 849 visible = true;
849 ChangeInsertion(insertion_rect, visible); 850 EXPECT_TRUE(ChangeInsertion(insertion_rect, visible));
850 EXPECT_FALSE(GetAndResetNeedsAnimate()); 851 EXPECT_FALSE(GetAndResetNeedsAnimate());
851 } 852 }
852 853
853 TEST_F(TouchSelectionControllerTest, TemporarilyHidden) { 854 TEST_F(TouchSelectionControllerTest, TemporarilyHidden) {
854 controller().OnTapEvent(); 855 controller().OnTapEvent();
855 controller().OnSelectionEditable(true); 856 controller().OnSelectionEditable(true);
856 857
857 gfx::RectF insertion_rect(5, 5, 0, 10); 858 gfx::RectF insertion_rect(5, 5, 0, 10);
858 859
859 bool visible = true; 860 bool visible = true;
860 ChangeInsertion(insertion_rect, visible); 861 EXPECT_TRUE(ChangeInsertion(insertion_rect, visible));
861 EXPECT_FALSE(GetAndResetNeedsAnimate()); 862 EXPECT_FALSE(GetAndResetNeedsAnimate());
862 863
863 controller().SetTemporarilyHidden(true); 864 controller().SetTemporarilyHidden(true);
864 EXPECT_TRUE(GetAndResetNeedsAnimate()); 865 EXPECT_TRUE(GetAndResetNeedsAnimate());
865 866
866 visible = false; 867 visible = false;
867 ChangeInsertion(insertion_rect, visible); 868 EXPECT_TRUE(ChangeInsertion(insertion_rect, visible));
868 EXPECT_FALSE(GetAndResetNeedsAnimate()); 869 EXPECT_FALSE(GetAndResetNeedsAnimate());
869 870
870 visible = true; 871 visible = true;
871 ChangeInsertion(insertion_rect, visible); 872 EXPECT_TRUE(ChangeInsertion(insertion_rect, visible));
872 EXPECT_FALSE(GetAndResetNeedsAnimate()); 873 EXPECT_FALSE(GetAndResetNeedsAnimate());
873 874
874 controller().SetTemporarilyHidden(false); 875 controller().SetTemporarilyHidden(false);
875 EXPECT_TRUE(GetAndResetNeedsAnimate()); 876 EXPECT_TRUE(GetAndResetNeedsAnimate());
876 } 877 }
877 878
878 TEST_F(TouchSelectionControllerTest, SelectionClearOnTap) { 879 TEST_F(TouchSelectionControllerTest, SelectionClearOnTap) {
879 gfx::RectF start_rect(5, 5, 0, 10); 880 gfx::RectF start_rect(5, 5, 0, 10);
880 gfx::RectF end_rect(50, 5, 0, 10); 881 gfx::RectF end_rect(50, 5, 0, 10);
881 bool visible = true; 882 bool visible = true;
882 883
883 controller().OnLongPressEvent(); 884 controller().OnLongPressEvent();
884 ChangeSelection(start_rect, visible, end_rect, visible); 885 EXPECT_TRUE(ChangeSelection(start_rect, visible, end_rect, visible));
885 EXPECT_THAT(GetAndResetEvents(), ElementsAre(SELECTION_SHOWN)); 886 EXPECT_THAT(GetAndResetEvents(), ElementsAre(SELECTION_SHOWN));
886 887
887 // Selection should not be cleared if the selection bounds have not changed. 888 // Selection should not be cleared if the selection bounds have not changed.
888 controller().OnTapEvent(); 889 controller().OnTapEvent();
889 EXPECT_THAT(GetAndResetEvents(), IsEmpty()); 890 EXPECT_THAT(GetAndResetEvents(), IsEmpty());
890 EXPECT_EQ(start_rect.bottom_left(), GetLastEventAnchor()); 891 EXPECT_EQ(start_rect.bottom_left(), GetLastEventAnchor());
891 892
892 controller().OnTapEvent(); 893 controller().OnTapEvent();
893 ClearSelection(); 894 EXPECT_TRUE(ClearSelection());
894 EXPECT_THAT(GetAndResetEvents(), ElementsAre(SELECTION_CLEARED)); 895 EXPECT_THAT(GetAndResetEvents(), ElementsAre(SELECTION_CLEARED));
895 EXPECT_EQ(gfx::PointF(), GetLastEventAnchor()); 896 EXPECT_EQ(gfx::PointF(), GetLastEventAnchor());
896 } 897 }
897 898
898 TEST_F(TouchSelectionControllerTest, AllowShowingFromCurrentSelection) { 899 TEST_F(TouchSelectionControllerTest, AllowShowingFromCurrentSelection) {
899 gfx::RectF start_rect(5, 5, 0, 10); 900 gfx::RectF start_rect(5, 5, 0, 10);
900 gfx::RectF end_rect(50, 5, 0, 10); 901 gfx::RectF end_rect(50, 5, 0, 10);
901 bool visible = true; 902 bool visible = true;
902 903
903 // The selection should not be activated, as it wasn't yet allowed. 904 // The selection should not be activated, as it wasn't yet allowed.
904 ChangeSelection(start_rect, visible, end_rect, visible); 905 EXPECT_FALSE(ChangeSelection(start_rect, visible, end_rect, visible));
905 EXPECT_EQ(gfx::PointF(), GetLastEventAnchor()); 906 EXPECT_EQ(gfx::PointF(), GetLastEventAnchor());
906 907
907 // Now explicitly allow showing from the previously supplied bounds. 908 // Now explicitly allow showing from the previously supplied bounds.
908 controller().AllowShowingFromCurrentSelection(); 909 controller().AllowShowingFromCurrentSelection();
909 EXPECT_THAT(GetAndResetEvents(), ElementsAre(SELECTION_SHOWN)); 910 EXPECT_THAT(GetAndResetEvents(), ElementsAre(SELECTION_SHOWN));
910 EXPECT_EQ(start_rect.bottom_left(), GetLastEventAnchor()); 911 EXPECT_EQ(start_rect.bottom_left(), GetLastEventAnchor());
911 912
912 // Repeated calls to show from the current selection should be ignored. 913 // Repeated calls to show from the current selection should be ignored.
913 controller().AllowShowingFromCurrentSelection(); 914 controller().AllowShowingFromCurrentSelection();
914 EXPECT_THAT(GetAndResetEvents(), IsEmpty()); 915 EXPECT_THAT(GetAndResetEvents(), IsEmpty());
915 EXPECT_EQ(start_rect.bottom_left(), GetLastEventAnchor()); 916 EXPECT_EQ(start_rect.bottom_left(), GetLastEventAnchor());
916 917
917 // Trying to show from an empty selection will have no result. 918 // Trying to show from an empty selection will have no result.
918 ClearSelection(); 919 EXPECT_TRUE(ClearSelection());
919 EXPECT_THAT(GetAndResetEvents(), ElementsAre(SELECTION_CLEARED)); 920 EXPECT_THAT(GetAndResetEvents(), ElementsAre(SELECTION_CLEARED));
920 controller().AllowShowingFromCurrentSelection(); 921 controller().AllowShowingFromCurrentSelection();
921 EXPECT_THAT(GetAndResetEvents(), IsEmpty()); 922 EXPECT_THAT(GetAndResetEvents(), IsEmpty());
922 923
923 // Showing the insertion handle should also be supported. 924 // Showing the insertion handle should also be supported.
924 controller().OnSelectionEditable(true); 925 controller().OnSelectionEditable(true);
925 controller().OnSelectionEmpty(false); 926 controller().OnSelectionEmpty(false);
926 controller().HideAndDisallowShowingAutomatically(); 927 controller().HideAndDisallowShowingAutomatically();
927 gfx::RectF insertion_rect(5, 5, 0, 10); 928 gfx::RectF insertion_rect(5, 5, 0, 10);
928 ChangeInsertion(insertion_rect, visible); 929 EXPECT_FALSE(ChangeInsertion(insertion_rect, visible));
929 controller().AllowShowingFromCurrentSelection(); 930 controller().AllowShowingFromCurrentSelection();
930 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_SHOWN)); 931 EXPECT_THAT(GetAndResetEvents(), ElementsAre(INSERTION_SHOWN));
931 EXPECT_EQ(insertion_rect.bottom_left(), GetLastEventAnchor()); 932 EXPECT_EQ(insertion_rect.bottom_left(), GetLastEventAnchor());
932 } 933 }
933 934
934 } // namespace ui 935 } // namespace ui
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698