Home | History | Annotate | Download | only in input
      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 "content/browser/renderer_host/input/touch_selection_controller.h"
      6 
      7 #include "testing/gtest/include/gtest/gtest.h"
      8 #include "ui/events/test/mock_motion_event.h"
      9 
     10 using ui::test::MockMotionEvent;
     11 
     12 namespace content {
     13 namespace {
     14 
     15 const int kDefaultTapTimeoutMs = 200;
     16 const float kDefaulTapSlop = 10.f;
     17 
     18 class MockTouchHandleDrawable : public TouchHandleDrawable {
     19  public:
     20   explicit MockTouchHandleDrawable(bool* contains_point)
     21       : intersects_rect_(contains_point) {}
     22   virtual ~MockTouchHandleDrawable() {}
     23   virtual void SetEnabled(bool enabled) OVERRIDE {}
     24   virtual void SetOrientation(TouchHandleOrientation orientation) OVERRIDE {}
     25   virtual void SetAlpha(float alpha) OVERRIDE {}
     26   virtual void SetFocus(const gfx::PointF& position) OVERRIDE {}
     27   virtual void SetVisible(bool visible) OVERRIDE {}
     28   virtual bool IntersectsWith(const gfx::RectF& rect) const OVERRIDE {
     29     return *intersects_rect_;
     30   }
     31 
     32  private:
     33   bool* intersects_rect_;
     34 };
     35 
     36 }  // namespace
     37 
     38 class TouchSelectionControllerTest : public testing::Test,
     39                                      public TouchSelectionControllerClient {
     40  public:
     41   TouchSelectionControllerTest()
     42       : last_event_(SELECTION_CLEARED),
     43         caret_moved_(false),
     44         selection_moved_(false),
     45         needs_animate_(false),
     46         animation_enabled_(true),
     47         dragging_enabled_(false) {}
     48 
     49   virtual ~TouchSelectionControllerTest() {}
     50 
     51   // testing::Test implementation.
     52   virtual void SetUp() OVERRIDE {
     53     controller_.reset(new TouchSelectionController(
     54         this,
     55         base::TimeDelta::FromMilliseconds(kDefaultTapTimeoutMs),
     56         kDefaulTapSlop));
     57   }
     58 
     59   virtual void TearDown() OVERRIDE { controller_.reset(); }
     60 
     61   // TouchSelectionControllerClient implementation.
     62 
     63   virtual bool SupportsAnimation() const OVERRIDE { return animation_enabled_; }
     64 
     65   virtual void SetNeedsAnimate() OVERRIDE { needs_animate_ = true; }
     66 
     67   virtual void MoveCaret(const gfx::PointF& position) OVERRIDE {
     68     caret_moved_ = true;
     69     caret_position_ = position;
     70   }
     71 
     72   virtual void SelectBetweenCoordinates(const gfx::PointF& start,
     73                                         const gfx::PointF& end) OVERRIDE {
     74     selection_moved_ = true;
     75     selection_start_ = start;
     76     selection_end_ = end;
     77   }
     78 
     79   virtual void OnSelectionEvent(SelectionEventType event,
     80                                 const gfx::PointF& end_position) OVERRIDE {
     81     last_event_ = event;
     82     last_event_start_ = end_position;
     83   }
     84 
     85   virtual scoped_ptr<TouchHandleDrawable> CreateDrawable() OVERRIDE {
     86     return scoped_ptr<TouchHandleDrawable>(
     87         new MockTouchHandleDrawable(&dragging_enabled_));
     88   }
     89 
     90   void SetAnimationEnabled(bool enabled) { animation_enabled_ = enabled; }
     91   void SetDraggingEnabled(bool enabled) { dragging_enabled_ = enabled; }
     92 
     93   void ClearSelection() {
     94     controller_->OnSelectionBoundsChanged(cc::ViewportSelectionBound(),
     95                                           cc::ViewportSelectionBound());
     96   }
     97 
     98   void ClearInsertion() { ClearSelection(); }
     99 
    100   void ChangeInsertion(const gfx::RectF& rect, bool visible) {
    101     cc::ViewportSelectionBound bound;
    102     bound.type = cc::SELECTION_BOUND_CENTER;
    103     bound.edge_top = rect.origin();
    104     bound.edge_bottom = rect.bottom_left();
    105     bound.visible = visible;
    106     controller_->OnSelectionBoundsChanged(bound, bound);
    107   }
    108 
    109   void ChangeSelection(const gfx::RectF& start_rect,
    110                        bool start_visible,
    111                        const gfx::RectF& end_rect,
    112                        bool end_visible) {
    113     cc::ViewportSelectionBound start_bound, end_bound;
    114     start_bound.type = cc::SELECTION_BOUND_LEFT;
    115     end_bound.type = cc::SELECTION_BOUND_RIGHT;
    116     start_bound.edge_top = start_rect.origin();
    117     start_bound.edge_bottom = start_rect.bottom_left();
    118     end_bound.edge_top = end_rect.origin();
    119     end_bound.edge_bottom = end_rect.bottom_left();
    120     start_bound.visible = start_visible;
    121     end_bound.visible = end_visible;
    122     controller_->OnSelectionBoundsChanged(start_bound, end_bound);
    123   }
    124 
    125   void Animate() {
    126     base::TimeTicks now = base::TimeTicks::Now();
    127     while (needs_animate_) {
    128       needs_animate_ = controller_->Animate(now);
    129       now += base::TimeDelta::FromMilliseconds(16);
    130     }
    131   }
    132 
    133   bool GetAndResetNeedsAnimate() {
    134     bool needs_animate = needs_animate_;
    135     Animate();
    136     return needs_animate;
    137   }
    138 
    139   bool GetAndResetCaretMoved() {
    140     bool moved = caret_moved_;
    141     caret_moved_ = false;
    142     return moved;
    143   }
    144 
    145   bool GetAndResetSelectionMoved() {
    146     bool moved = selection_moved_;
    147     selection_moved_ = false;
    148     return moved;
    149   }
    150 
    151   const gfx::PointF& GetLastCaretPosition() const { return caret_position_; }
    152   const gfx::PointF& GetLastSelectionStart() const { return selection_start_; }
    153   const gfx::PointF& GetLastSelectionEnd() const { return selection_end_; }
    154   SelectionEventType GetLastEventType() const { return last_event_; }
    155   const gfx::PointF& GetLastEventAnchor() const { return last_event_start_; }
    156 
    157   TouchSelectionController& controller() { return *controller_; }
    158 
    159  private:
    160   gfx::PointF last_event_start_;
    161   gfx::PointF caret_position_;
    162   gfx::PointF selection_start_;
    163   gfx::PointF selection_end_;
    164   SelectionEventType last_event_;
    165   bool caret_moved_;
    166   bool selection_moved_;
    167   bool needs_animate_;
    168   bool animation_enabled_;
    169   bool dragging_enabled_;
    170   scoped_ptr<TouchSelectionController> controller_;
    171 };
    172 
    173 TEST_F(TouchSelectionControllerTest, InsertionBasic) {
    174   gfx::RectF insertion_rect(5, 5, 0, 10);
    175   bool visible = true;
    176 
    177   // Insertion events are ignored until automatic showing is enabled.
    178   ChangeInsertion(insertion_rect, visible);
    179   EXPECT_EQ(gfx::PointF(), GetLastEventAnchor());
    180   controller().OnTapEvent();
    181 
    182   // Insertion events are ignored until the selection region is marked editable.
    183   ChangeInsertion(insertion_rect, visible);
    184   EXPECT_EQ(gfx::PointF(), GetLastEventAnchor());
    185 
    186   controller().OnTapEvent();
    187   controller().OnSelectionEditable(true);
    188   ChangeInsertion(insertion_rect, visible);
    189   EXPECT_EQ(INSERTION_SHOWN, GetLastEventType());
    190   EXPECT_EQ(insertion_rect.bottom_left(), GetLastEventAnchor());
    191 
    192   insertion_rect.Offset(1, 0);
    193   ChangeInsertion(insertion_rect, visible);
    194   EXPECT_EQ(INSERTION_MOVED, GetLastEventType());
    195   EXPECT_EQ(insertion_rect.bottom_left(), GetLastEventAnchor());
    196 
    197   insertion_rect.Offset(0, 1);
    198   ChangeInsertion(insertion_rect, visible);
    199   EXPECT_EQ(INSERTION_MOVED, GetLastEventType());
    200   EXPECT_EQ(insertion_rect.bottom_left(), GetLastEventAnchor());
    201 
    202   ClearInsertion();
    203   EXPECT_EQ(INSERTION_CLEARED, GetLastEventType());
    204 }
    205 
    206 TEST_F(TouchSelectionControllerTest, InsertionClearedWhenNoLongerEditable) {
    207   gfx::RectF insertion_rect(5, 5, 0, 10);
    208   bool visible = true;
    209   controller().OnTapEvent();
    210   controller().OnSelectionEditable(true);
    211 
    212   ChangeInsertion(insertion_rect, visible);
    213   EXPECT_EQ(INSERTION_SHOWN, GetLastEventType());
    214   EXPECT_EQ(insertion_rect.bottom_left(), GetLastEventAnchor());
    215 
    216   controller().OnSelectionEditable(false);
    217   EXPECT_EQ(INSERTION_CLEARED, GetLastEventType());
    218 }
    219 
    220 TEST_F(TouchSelectionControllerTest, InsertionStaysHiddenIfEmptyRegionTapped) {
    221   gfx::RectF insertion_rect(5, 5, 0, 10);
    222   bool visible = true;
    223   controller().OnSelectionEditable(true);
    224 
    225   // Taps should be ignored if they're in an empty editable region.
    226   controller().OnTapEvent();
    227   controller().OnSelectionEmpty(true);
    228   ChangeInsertion(insertion_rect, visible);
    229   EXPECT_EQ(gfx::PointF(), GetLastEventAnchor());
    230 
    231   // Once the region becomes editable, taps should show the insertion handle.
    232   controller().OnTapEvent();
    233   controller().OnSelectionEmpty(false);
    234   ChangeInsertion(insertion_rect, visible);
    235   EXPECT_EQ(INSERTION_SHOWN, GetLastEventType());
    236   EXPECT_EQ(insertion_rect.bottom_left(), GetLastEventAnchor());
    237 
    238   // Reset the selection.
    239   controller().HideAndDisallowShowingAutomatically();
    240   EXPECT_EQ(INSERTION_CLEARED, GetLastEventType());
    241 
    242   // Long-pressing should show the handle even if the editable region is empty.
    243   insertion_rect.Offset(2, -2);
    244   controller().OnLongPressEvent();
    245   controller().OnSelectionEmpty(true);
    246   ChangeInsertion(insertion_rect, visible);
    247   EXPECT_EQ(INSERTION_SHOWN, GetLastEventType());
    248   EXPECT_EQ(insertion_rect.bottom_left(), GetLastEventAnchor());
    249 
    250   // Single Tap on an empty edit field should clear insertion handle.
    251   controller().OnTapEvent();
    252   EXPECT_EQ(INSERTION_CLEARED, GetLastEventType());
    253 }
    254 
    255 TEST_F(TouchSelectionControllerTest, InsertionAppearsAfterTapFollowingTyping) {
    256   gfx::RectF insertion_rect(5, 5, 0, 10);
    257   bool visible = true;
    258 
    259   // Simulate the user tapping an empty text field.
    260   controller().OnTapEvent();
    261   controller().OnSelectionEditable(true);
    262   controller().OnSelectionEmpty(true);
    263   ChangeInsertion(insertion_rect, visible);
    264   EXPECT_EQ(gfx::PointF(), GetLastEventAnchor());
    265 
    266   // Simulate the cursor moving while a user is typing.
    267   insertion_rect.Offset(10, 0);
    268   controller().OnSelectionEmpty(false);
    269   ChangeInsertion(insertion_rect, visible);
    270   EXPECT_EQ(gfx::PointF(), GetLastEventAnchor());
    271 
    272   // If the user taps the *same* position as the cursor at the end of the text
    273   // entry, the handle should appear.
    274   controller().OnTapEvent();
    275   ChangeInsertion(insertion_rect, visible);
    276   EXPECT_EQ(INSERTION_SHOWN, GetLastEventType());
    277   EXPECT_EQ(insertion_rect.bottom_left(), GetLastEventAnchor());
    278 }
    279 
    280 TEST_F(TouchSelectionControllerTest, InsertionToSelectionTransition) {
    281   controller().OnLongPressEvent();
    282   controller().OnSelectionEditable(true);
    283 
    284   gfx::RectF start_rect(5, 5, 0, 10);
    285   gfx::RectF end_rect(50, 5, 0, 10);
    286   bool visible = true;
    287 
    288   ChangeInsertion(start_rect, visible);
    289   EXPECT_EQ(INSERTION_SHOWN, GetLastEventType());
    290   EXPECT_EQ(start_rect.bottom_left(), GetLastEventAnchor());
    291 
    292   ChangeSelection(start_rect, visible, end_rect, visible);
    293   EXPECT_EQ(SELECTION_SHOWN, GetLastEventType());
    294   EXPECT_EQ(start_rect.bottom_left(), GetLastEventAnchor());
    295 
    296   ChangeInsertion(end_rect, visible);
    297   EXPECT_EQ(INSERTION_SHOWN, GetLastEventType());
    298   EXPECT_EQ(end_rect.bottom_left(), GetLastEventAnchor());
    299 
    300   controller().HideAndDisallowShowingAutomatically();
    301   EXPECT_EQ(INSERTION_CLEARED, GetLastEventType());
    302 
    303   controller().OnTapEvent();
    304   ChangeInsertion(end_rect, visible);
    305   EXPECT_EQ(INSERTION_SHOWN, GetLastEventType());
    306   EXPECT_EQ(end_rect.bottom_left(), GetLastEventAnchor());
    307 }
    308 
    309 TEST_F(TouchSelectionControllerTest, InsertionDragged) {
    310   base::TimeTicks event_time = base::TimeTicks::Now();
    311   controller().OnTapEvent();
    312   controller().OnSelectionEditable(true);
    313 
    314   // The touch sequence should not be handled if insertion is not active.
    315   MockMotionEvent event(MockMotionEvent::ACTION_DOWN, event_time, 0, 0);
    316   EXPECT_FALSE(controller().WillHandleTouchEvent(event));
    317 
    318   float line_height = 10.f;
    319   gfx::RectF start_rect(10, 0, 0, line_height);
    320   bool visible = true;
    321   ChangeInsertion(start_rect, visible);
    322   EXPECT_EQ(INSERTION_SHOWN, GetLastEventType());
    323   EXPECT_EQ(start_rect.bottom_left(), GetLastEventAnchor());
    324 
    325   // The touch sequence should be handled only if the drawable reports a hit.
    326   EXPECT_FALSE(controller().WillHandleTouchEvent(event));
    327   SetDraggingEnabled(true);
    328   EXPECT_TRUE(controller().WillHandleTouchEvent(event));
    329   EXPECT_FALSE(GetAndResetCaretMoved());
    330 
    331   // The MoveCaret() result should reflect the movement.
    332   // The reported position is offset from the center of |start_rect|.
    333   gfx::PointF start_offset = start_rect.CenterPoint();
    334   event = MockMotionEvent(MockMotionEvent::ACTION_MOVE, event_time, 0, 5);
    335   EXPECT_TRUE(controller().WillHandleTouchEvent(event));
    336   EXPECT_TRUE(GetAndResetCaretMoved());
    337   EXPECT_EQ(start_offset + gfx::Vector2dF(0, 5), GetLastCaretPosition());
    338 
    339   event = MockMotionEvent(MockMotionEvent::ACTION_MOVE, event_time, 5, 5);
    340   EXPECT_TRUE(controller().WillHandleTouchEvent(event));
    341   EXPECT_TRUE(GetAndResetCaretMoved());
    342   EXPECT_EQ(start_offset + gfx::Vector2dF(5, 5), GetLastCaretPosition());
    343 
    344   event = MockMotionEvent(MockMotionEvent::ACTION_MOVE, event_time, 10, 10);
    345   EXPECT_TRUE(controller().WillHandleTouchEvent(event));
    346   EXPECT_TRUE(GetAndResetCaretMoved());
    347   EXPECT_EQ(start_offset + gfx::Vector2dF(10, 10), GetLastCaretPosition());
    348 
    349   event = MockMotionEvent(MockMotionEvent::ACTION_UP, event_time, 10, 5);
    350   EXPECT_TRUE(controller().WillHandleTouchEvent(event));
    351   EXPECT_FALSE(GetAndResetCaretMoved());
    352 
    353   // Once the drag is complete, no more touch events should be consumed until
    354   // the next ACTION_DOWN.
    355   EXPECT_FALSE(controller().WillHandleTouchEvent(event));
    356 }
    357 
    358 TEST_F(TouchSelectionControllerTest, InsertionTapped) {
    359   base::TimeTicks event_time = base::TimeTicks::Now();
    360   controller().OnTapEvent();
    361   controller().OnSelectionEditable(true);
    362   SetDraggingEnabled(true);
    363 
    364   gfx::RectF start_rect(10, 0, 0, 10);
    365   bool visible = true;
    366   ChangeInsertion(start_rect, visible);
    367   EXPECT_EQ(INSERTION_SHOWN, GetLastEventType());
    368 
    369   MockMotionEvent event(MockMotionEvent::ACTION_DOWN, event_time, 0, 0);
    370   EXPECT_TRUE(controller().WillHandleTouchEvent(event));
    371   //TODO(AKV): this test case has to be modified once crbug.com/394093 is fixed.
    372   EXPECT_EQ(INSERTION_DRAG_STARTED, GetLastEventType());
    373 
    374   event = MockMotionEvent(MockMotionEvent::ACTION_UP, event_time, 0, 0);
    375   EXPECT_TRUE(controller().WillHandleTouchEvent(event));
    376   EXPECT_EQ(INSERTION_TAPPED, GetLastEventType());
    377 
    378   // Reset the insertion.
    379   ClearInsertion();
    380   controller().OnTapEvent();
    381   ChangeInsertion(start_rect, visible);
    382   ASSERT_EQ(INSERTION_SHOWN, GetLastEventType());
    383 
    384   // No tap should be signalled if the time between DOWN and UP was too long.
    385   event = MockMotionEvent(MockMotionEvent::ACTION_DOWN, event_time, 0, 0);
    386   EXPECT_TRUE(controller().WillHandleTouchEvent(event));
    387   event = MockMotionEvent(MockMotionEvent::ACTION_UP,
    388                           event_time + base::TimeDelta::FromSeconds(1),
    389                           0,
    390                           0);
    391   EXPECT_TRUE(controller().WillHandleTouchEvent(event));
    392   EXPECT_EQ(INSERTION_DRAG_STARTED, GetLastEventType());
    393 
    394   // Reset the insertion.
    395   ClearInsertion();
    396   controller().OnTapEvent();
    397   ChangeInsertion(start_rect, visible);
    398   ASSERT_EQ(INSERTION_SHOWN, GetLastEventType());
    399 
    400   // No tap should be signalled if the drag was too long.
    401   event = MockMotionEvent(MockMotionEvent::ACTION_DOWN, event_time, 0, 0);
    402   EXPECT_TRUE(controller().WillHandleTouchEvent(event));
    403   event = MockMotionEvent(MockMotionEvent::ACTION_MOVE, event_time, 100, 0);
    404   EXPECT_TRUE(controller().WillHandleTouchEvent(event));
    405   event = MockMotionEvent(MockMotionEvent::ACTION_UP, event_time, 100, 0);
    406   EXPECT_TRUE(controller().WillHandleTouchEvent(event));
    407   EXPECT_EQ(INSERTION_DRAG_STARTED, GetLastEventType());
    408 
    409   // Reset the insertion.
    410   ClearInsertion();
    411   controller().OnTapEvent();
    412   ChangeInsertion(start_rect, visible);
    413   ASSERT_EQ(INSERTION_SHOWN, GetLastEventType());
    414 
    415   // No tap should be signalled if the touch sequence is cancelled.
    416   event = MockMotionEvent(MockMotionEvent::ACTION_DOWN, event_time, 0, 0);
    417   EXPECT_TRUE(controller().WillHandleTouchEvent(event));
    418   event = MockMotionEvent(MockMotionEvent::ACTION_CANCEL, event_time, 0, 0);
    419   EXPECT_TRUE(controller().WillHandleTouchEvent(event));
    420   EXPECT_EQ(INSERTION_DRAG_STARTED, GetLastEventType());
    421 }
    422 
    423 TEST_F(TouchSelectionControllerTest, InsertionNotResetByRepeatedTapOrPress) {
    424   base::TimeTicks event_time = base::TimeTicks::Now();
    425   controller().OnTapEvent();
    426   controller().OnSelectionEditable(true);
    427   SetDraggingEnabled(true);
    428 
    429   gfx::RectF anchor_rect(10, 0, 0, 10);
    430   bool visible = true;
    431   ChangeInsertion(anchor_rect, visible);
    432   EXPECT_EQ(INSERTION_SHOWN, GetLastEventType());
    433   EXPECT_EQ(anchor_rect.bottom_left(), GetLastEventAnchor());
    434 
    435   // Tapping again shouldn't reset the active insertion point.
    436   controller().OnTapEvent();
    437   MockMotionEvent event(MockMotionEvent::ACTION_DOWN, event_time, 0, 0);
    438   EXPECT_TRUE(controller().WillHandleTouchEvent(event));
    439   EXPECT_EQ(INSERTION_DRAG_STARTED, GetLastEventType());
    440   EXPECT_EQ(anchor_rect.bottom_left(), GetLastEventAnchor());
    441 
    442   event = MockMotionEvent(MockMotionEvent::ACTION_UP, event_time, 0, 0);
    443   EXPECT_TRUE(controller().WillHandleTouchEvent(event));
    444   EXPECT_EQ(INSERTION_TAPPED, GetLastEventType());
    445   EXPECT_EQ(anchor_rect.bottom_left(), GetLastEventAnchor());
    446 
    447   anchor_rect.Offset(5, 15);
    448   ChangeInsertion(anchor_rect, visible);
    449   EXPECT_EQ(INSERTION_MOVED, GetLastEventType());
    450   EXPECT_EQ(anchor_rect.bottom_left(), GetLastEventAnchor());
    451 
    452   // Pressing shouldn't reset the active insertion point.
    453   controller().OnLongPressEvent();
    454   controller().OnSelectionEmpty(true);
    455   event = MockMotionEvent(MockMotionEvent::ACTION_DOWN, event_time, 0, 0);
    456   EXPECT_TRUE(controller().WillHandleTouchEvent(event));
    457   EXPECT_EQ(INSERTION_DRAG_STARTED, GetLastEventType());
    458   EXPECT_EQ(anchor_rect.bottom_left(), GetLastEventAnchor());
    459 
    460   event = MockMotionEvent(MockMotionEvent::ACTION_UP, event_time, 0, 0);
    461   EXPECT_TRUE(controller().WillHandleTouchEvent(event));
    462   EXPECT_EQ(INSERTION_TAPPED, GetLastEventType());
    463   EXPECT_EQ(anchor_rect.bottom_left(), GetLastEventAnchor());
    464 }
    465 
    466 TEST_F(TouchSelectionControllerTest, SelectionBasic) {
    467   gfx::RectF start_rect(5, 5, 0, 10);
    468   gfx::RectF end_rect(50, 5, 0, 10);
    469   bool visible = true;
    470 
    471   // Selection events are ignored until automatic showing is enabled.
    472   ChangeSelection(start_rect, visible, end_rect, visible);
    473   EXPECT_EQ(gfx::PointF(), GetLastEventAnchor());
    474 
    475   controller().OnLongPressEvent();
    476   ChangeSelection(start_rect, visible, end_rect, visible);
    477   EXPECT_EQ(SELECTION_SHOWN, GetLastEventType());
    478   EXPECT_EQ(start_rect.bottom_left(), GetLastEventAnchor());
    479 
    480   start_rect.Offset(1, 0);
    481   ChangeSelection(start_rect, visible, end_rect, visible);
    482   // Selection movement does not currently trigger a separate event.
    483   EXPECT_EQ(SELECTION_SHOWN, GetLastEventType());
    484 
    485   ClearSelection();
    486   EXPECT_EQ(SELECTION_CLEARED, GetLastEventType());
    487   EXPECT_EQ(gfx::PointF(), GetLastEventAnchor());
    488 }
    489 
    490 TEST_F(TouchSelectionControllerTest, SelectionRepeatedLongPress) {
    491   gfx::RectF start_rect(5, 5, 0, 10);
    492   gfx::RectF end_rect(50, 5, 0, 10);
    493   bool visible = true;
    494 
    495   controller().OnLongPressEvent();
    496   ChangeSelection(start_rect, visible, end_rect, visible);
    497   EXPECT_EQ(SELECTION_SHOWN, GetLastEventType());
    498   EXPECT_EQ(start_rect.bottom_left(), GetLastEventAnchor());
    499 
    500   // A long press triggering a new selection should re-send the SELECTION_SHOWN
    501   // event notification.
    502   start_rect.Offset(10, 10);
    503   controller().OnLongPressEvent();
    504   ChangeSelection(start_rect, visible, end_rect, visible);
    505   EXPECT_EQ(SELECTION_SHOWN, GetLastEventType());
    506   EXPECT_EQ(start_rect.bottom_left(), GetLastEventAnchor());
    507 }
    508 
    509 TEST_F(TouchSelectionControllerTest, SelectionDragged) {
    510   base::TimeTicks event_time = base::TimeTicks::Now();
    511   controller().OnLongPressEvent();
    512 
    513   // The touch sequence should not be handled if selection is not active.
    514   MockMotionEvent event(MockMotionEvent::ACTION_DOWN, event_time, 0, 0);
    515   EXPECT_FALSE(controller().WillHandleTouchEvent(event));
    516 
    517   float line_height = 10.f;
    518   gfx::RectF start_rect(0, 0, 0, line_height);
    519   gfx::RectF end_rect(50, 0, 0, line_height);
    520   bool visible = true;
    521   ChangeSelection(start_rect, visible, end_rect, visible);
    522   EXPECT_EQ(SELECTION_SHOWN, GetLastEventType());
    523   EXPECT_EQ(start_rect.bottom_left(), GetLastEventAnchor());
    524 
    525   // The touch sequence should be handled only if the drawable reports a hit.
    526   EXPECT_FALSE(controller().WillHandleTouchEvent(event));
    527   SetDraggingEnabled(true);
    528   EXPECT_TRUE(controller().WillHandleTouchEvent(event));
    529   EXPECT_FALSE(GetAndResetSelectionMoved());
    530 
    531   // The SelectBetweenCoordinates() result should reflect the movement. Note
    532   // that the start coordinate will always reflect the "fixed" handle's
    533   // position, in this case the position from |end_rect|.
    534   // Note that the reported position is offset from the center of the
    535   // input rects (i.e., the middle of the corresponding text line).
    536   gfx::PointF fixed_offset = end_rect.CenterPoint();
    537   gfx::PointF start_offset = start_rect.CenterPoint();
    538   event = MockMotionEvent(MockMotionEvent::ACTION_MOVE, event_time, 0, 5);
    539   EXPECT_TRUE(controller().WillHandleTouchEvent(event));
    540   EXPECT_EQ(SELECTION_DRAG_STARTED, GetLastEventType());
    541   EXPECT_TRUE(GetAndResetSelectionMoved());
    542   EXPECT_EQ(fixed_offset, GetLastSelectionStart());
    543   EXPECT_EQ(start_offset + gfx::Vector2dF(0, 5), GetLastSelectionEnd());
    544 
    545   event = MockMotionEvent(MockMotionEvent::ACTION_MOVE, event_time, 5, 5);
    546   EXPECT_TRUE(controller().WillHandleTouchEvent(event));
    547   EXPECT_TRUE(GetAndResetSelectionMoved());
    548   EXPECT_EQ(fixed_offset, GetLastSelectionStart());
    549   EXPECT_EQ(start_offset + gfx::Vector2dF(5, 5), GetLastSelectionEnd());
    550 
    551   event = MockMotionEvent(MockMotionEvent::ACTION_MOVE, event_time, 10, 5);
    552   EXPECT_TRUE(controller().WillHandleTouchEvent(event));
    553   EXPECT_TRUE(GetAndResetSelectionMoved());
    554   EXPECT_EQ(fixed_offset, GetLastSelectionStart());
    555   EXPECT_EQ(start_offset + gfx::Vector2dF(10, 5), GetLastSelectionEnd());
    556 
    557   event = MockMotionEvent(MockMotionEvent::ACTION_UP, event_time, 10, 5);
    558   EXPECT_TRUE(controller().WillHandleTouchEvent(event));
    559   EXPECT_EQ(SELECTION_DRAG_STOPPED, GetLastEventType());
    560   EXPECT_FALSE(GetAndResetSelectionMoved());
    561 
    562   // Once the drag is complete, no more touch events should be consumed until
    563   // the next ACTION_DOWN.
    564   EXPECT_FALSE(controller().WillHandleTouchEvent(event));
    565 }
    566 
    567 TEST_F(TouchSelectionControllerTest, SelectionDraggedWithOverlap) {
    568   base::TimeTicks event_time = base::TimeTicks::Now();
    569   controller().OnLongPressEvent();
    570 
    571   float line_height = 10.f;
    572   gfx::RectF start_rect(0, 0, 0, line_height);
    573   gfx::RectF end_rect(50, 0, 0, line_height);
    574   bool visible = true;
    575   ChangeSelection(start_rect, visible, end_rect, visible);
    576   EXPECT_EQ(SELECTION_SHOWN, GetLastEventType());
    577   EXPECT_EQ(start_rect.bottom_left(), GetLastEventAnchor());
    578 
    579   // The ACTION_DOWN should lock to the closest handle.
    580   gfx::PointF end_offset = end_rect.CenterPoint();
    581   gfx::PointF fixed_offset = start_rect.CenterPoint();
    582   float touch_down_x = (end_offset.x() + fixed_offset.x()) / 2 + 1.f;
    583   MockMotionEvent event(
    584       MockMotionEvent::ACTION_DOWN, event_time, touch_down_x, 0);
    585   SetDraggingEnabled(true);
    586   EXPECT_TRUE(controller().WillHandleTouchEvent(event));
    587   EXPECT_EQ(SELECTION_DRAG_STARTED, GetLastEventType());
    588   EXPECT_FALSE(GetAndResetSelectionMoved());
    589 
    590   // Even though the ACTION_MOVE is over the start handle, it should continue
    591   // targetting the end handle that consumed the ACTION_DOWN.
    592   event = MockMotionEvent(MockMotionEvent::ACTION_MOVE, event_time, 0, 0);
    593   EXPECT_TRUE(controller().WillHandleTouchEvent(event));
    594   EXPECT_TRUE(GetAndResetSelectionMoved());
    595   EXPECT_EQ(fixed_offset, GetLastSelectionStart());
    596   EXPECT_EQ(end_offset - gfx::Vector2dF(touch_down_x, 0),
    597             GetLastSelectionEnd());
    598 
    599   event = MockMotionEvent(MockMotionEvent::ACTION_UP, event_time, 0, 0);
    600   EXPECT_TRUE(controller().WillHandleTouchEvent(event));
    601   EXPECT_EQ(SELECTION_DRAG_STOPPED, GetLastEventType());
    602   EXPECT_FALSE(GetAndResetSelectionMoved());
    603 }
    604 
    605 TEST_F(TouchSelectionControllerTest, Animation) {
    606   controller().OnTapEvent();
    607   controller().OnSelectionEditable(true);
    608 
    609   gfx::RectF insertion_rect(5, 5, 0, 10);
    610 
    611   bool visible = true;
    612   ChangeInsertion(insertion_rect, visible);
    613   EXPECT_FALSE(GetAndResetNeedsAnimate());
    614 
    615   visible = false;
    616   ChangeInsertion(insertion_rect, visible);
    617   EXPECT_TRUE(GetAndResetNeedsAnimate());
    618 
    619   visible = true;
    620   ChangeInsertion(insertion_rect, visible);
    621   EXPECT_TRUE(GetAndResetNeedsAnimate());
    622 
    623   // If the handles are explicity hidden, no animation should be triggered.
    624   controller().HideAndDisallowShowingAutomatically();
    625   EXPECT_FALSE(GetAndResetNeedsAnimate());
    626 
    627   // If the client doesn't support animation, no animation should be triggered.
    628   SetAnimationEnabled(false);
    629   controller().OnTapEvent();
    630   visible = true;
    631   ChangeInsertion(insertion_rect, visible);
    632   EXPECT_FALSE(GetAndResetNeedsAnimate());
    633 }
    634 
    635 TEST_F(TouchSelectionControllerTest, TemporarilyHidden) {
    636   controller().OnTapEvent();
    637   controller().OnSelectionEditable(true);
    638 
    639   gfx::RectF insertion_rect(5, 5, 0, 10);
    640 
    641   bool visible = true;
    642   ChangeInsertion(insertion_rect, visible);
    643   EXPECT_FALSE(GetAndResetNeedsAnimate());
    644 
    645   controller().SetTemporarilyHidden(true);
    646   EXPECT_TRUE(GetAndResetNeedsAnimate());
    647 
    648   visible = false;
    649   ChangeInsertion(insertion_rect, visible);
    650   EXPECT_FALSE(GetAndResetNeedsAnimate());
    651 
    652   visible = true;
    653   ChangeInsertion(insertion_rect, visible);
    654   EXPECT_FALSE(GetAndResetNeedsAnimate());
    655 
    656   controller().SetTemporarilyHidden(false);
    657   EXPECT_TRUE(GetAndResetNeedsAnimate());
    658 }
    659 
    660 TEST_F(TouchSelectionControllerTest, SelectionClearOnTap) {
    661   gfx::RectF start_rect(5, 5, 0, 10);
    662   gfx::RectF end_rect(50, 5, 0, 10);
    663   bool visible = true;
    664 
    665   controller().OnLongPressEvent();
    666   ChangeSelection(start_rect, visible, end_rect, visible);
    667 
    668   // Selection should not be cleared if the selection bounds have not changed.
    669   controller().OnTapEvent();
    670   EXPECT_EQ(SELECTION_SHOWN, GetLastEventType());
    671   EXPECT_EQ(start_rect.bottom_left(), GetLastEventAnchor());
    672 
    673   controller().OnTapEvent();
    674   ClearSelection();
    675   EXPECT_EQ(SELECTION_CLEARED, GetLastEventType());
    676   EXPECT_EQ(gfx::PointF(), GetLastEventAnchor());
    677 }
    678 
    679 }  // namespace content
    680