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

Side by Side Diff: third_party/WebKit/Source/core/input/EventHandlerTest.cpp

Issue 2201853002: Blink handle selection handle visibility (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fixed line length Created 4 years, 1 month 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 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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 "core/input/EventHandler.h" 5 #include "core/input/EventHandler.h"
6 6
7 #include "core/dom/Document.h" 7 #include "core/dom/Document.h"
8 #include "core/dom/Range.h" 8 #include "core/dom/Range.h"
9 #include "core/editing/Editor.h" 9 #include "core/editing/Editor.h"
10 #include "core/editing/FrameSelection.h" 10 #include "core/editing/FrameSelection.h"
11 #include "core/frame/FrameView.h" 11 #include "core/frame/FrameView.h"
12 #include "core/frame/LocalFrame.h" 12 #include "core/frame/LocalFrame.h"
13 #include "core/frame/Settings.h" 13 #include "core/frame/Settings.h"
14 #include "core/page/AutoscrollController.h" 14 #include "core/page/AutoscrollController.h"
15 #include "core/page/Page.h" 15 #include "core/page/Page.h"
16 #include "core/testing/DummyPageHolder.h" 16 #include "core/testing/DummyPageHolder.h"
17 #include "platform/PlatformMouseEvent.h" 17 #include "platform/PlatformMouseEvent.h"
18 #include "testing/gtest/include/gtest/gtest.h" 18 #include "testing/gtest/include/gtest/gtest.h"
19 #include <memory> 19 #include <memory>
20 20
21 namespace blink { 21 namespace blink {
22 22
23 class EventHandlerTest : public ::testing::Test { 23 class EventHandlerTest : public ::testing::Test {
24 protected: 24 protected:
25 void SetUp() override; 25 void SetUp() override;
26 26
27 Page& page() const { return m_dummyPageHolder->page(); } 27 Page& page() const { return m_dummyPageHolder->page(); }
28 Document& document() const { return m_dummyPageHolder->document(); } 28 Document& document() const { return m_dummyPageHolder->document(); }
29 FrameSelection& selection() const { return document().frame()->selection(); }
29 30
30 void setHtmlInnerHTML(const char* htmlContent); 31 void setHtmlInnerHTML(const char* htmlContent);
31 32
32 private: 33 private:
33 std::unique_ptr<DummyPageHolder> m_dummyPageHolder; 34 std::unique_ptr<DummyPageHolder> m_dummyPageHolder;
34 }; 35 };
35 36
36 class TapEventBuilder : public PlatformGestureEvent { 37 class TapEventBuilder : public PlatformGestureEvent {
37 public: 38 public:
38 TapEventBuilder(IntPoint position, int tapCount) 39 TapEventBuilder(IntPoint position, int tapCount)
39 : PlatformGestureEvent(PlatformEvent::GestureTap, 40 : PlatformGestureEvent(PlatformEvent::GestureTap,
40 position, 41 position,
41 position, 42 position,
42 IntSize(5, 5), 43 IntSize(5, 5),
43 WTF::monotonicallyIncreasingTime(), 44 WTF::monotonicallyIncreasingTime(),
44 static_cast<PlatformEvent::Modifiers>(0), 45 static_cast<PlatformEvent::Modifiers>(0),
45 PlatformGestureSourceTouchscreen) { 46 PlatformGestureSourceTouchscreen) {
46 m_data.m_tap.m_tapCount = tapCount; 47 m_data.m_tap.m_tapCount = tapCount;
47 } 48 }
48 }; 49 };
49 50
51 class LongPressEventBuilder : public PlatformGestureEvent {
52 public:
53 LongPressEventBuilder(IntPoint position)
54 : PlatformGestureEvent(PlatformEvent::GestureLongPress,
55 position,
56 position,
57 IntSize(5, 5),
58 WTF::monotonicallyIncreasingTime(),
59 static_cast<PlatformEvent::Modifiers>(0),
60 PlatformGestureSourceTouchscreen) {}
61 };
62
63 class MousePressEventBuilder : public PlatformMouseEvent {
64 public:
65 MousePressEventBuilder(IntPoint position,
66 int clickCount,
67 WebMouseEvent::Button button)
68 : PlatformMouseEvent(position,
69 position,
70 button,
71 PlatformEvent::MousePressed,
72 clickCount,
73 static_cast<PlatformEvent::Modifiers>(0),
74 WTF::monotonicallyIncreasingTime()) {}
75 };
76
50 void EventHandlerTest::SetUp() { 77 void EventHandlerTest::SetUp() {
51 m_dummyPageHolder = DummyPageHolder::create(IntSize(300, 400)); 78 m_dummyPageHolder = DummyPageHolder::create(IntSize(300, 400));
52 } 79 }
53 80
54 void EventHandlerTest::setHtmlInnerHTML(const char* htmlContent) { 81 void EventHandlerTest::setHtmlInnerHTML(const char* htmlContent) {
55 document().documentElement()->setInnerHTML(String::fromUTF8(htmlContent)); 82 document().documentElement()->setInnerHTML(String::fromUTF8(htmlContent));
56 document().view()->updateAllLifecyclePhases(); 83 document().view()->updateAllLifecyclePhases();
57 } 84 }
58 85
59 TEST_F(EventHandlerTest, dragSelectionAfterScroll) { 86 TEST_F(EventHandlerTest, dragSelectionAfterScroll) {
(...skipping 30 matching lines...) Expand all
90 page().autoscrollController().animate(WTF::monotonicallyIncreasingTime()); 117 page().autoscrollController().animate(WTF::monotonicallyIncreasingTime());
91 page().animator().serviceScriptedAnimations( 118 page().animator().serviceScriptedAnimations(
92 WTF::monotonicallyIncreasingTime()); 119 WTF::monotonicallyIncreasingTime());
93 120
94 PlatformMouseEvent mouseUpEvent( 121 PlatformMouseEvent mouseUpEvent(
95 IntPoint(100, 50), IntPoint(200, 250), WebPointerProperties::Button::Left, 122 IntPoint(100, 50), IntPoint(200, 250), WebPointerProperties::Button::Left,
96 PlatformEvent::MouseReleased, 1, static_cast<PlatformEvent::Modifiers>(0), 123 PlatformEvent::MouseReleased, 1, static_cast<PlatformEvent::Modifiers>(0),
97 WTF::monotonicallyIncreasingTime()); 124 WTF::monotonicallyIncreasingTime());
98 document().frame()->eventHandler().handleMouseReleaseEvent(mouseUpEvent); 125 document().frame()->eventHandler().handleMouseReleaseEvent(mouseUpEvent);
99 126
100 FrameSelection& selection = document().frame()->selection(); 127 ASSERT_TRUE(selection().isRange());
101 ASSERT_TRUE(selection.isRange());
102 Range* range = 128 Range* range =
103 createRange(selection.selection().toNormalizedEphemeralRange()); 129 createRange(selection().selection().toNormalizedEphemeralRange());
104 ASSERT_TRUE(range); 130 ASSERT_TRUE(range);
105 EXPECT_EQ("Line 1\nLine 2", range->text()); 131 EXPECT_EQ("Line 1\nLine 2", range->text());
106 } 132 }
107 133
108 TEST_F(EventHandlerTest, multiClickSelectionFromTap) { 134 TEST_F(EventHandlerTest, multiClickSelectionFromTap) {
109 setHtmlInnerHTML( 135 setHtmlInnerHTML(
110 "<style> body { margin: 0px; } .line { display: block; width: 300px; " 136 "<style> body { margin: 0px; } .line { display: block; width: 300px; "
111 "height: 30px; } </style>" 137 "height: 30px; } </style>"
112 "<body contenteditable='true'><span class='line' id='line'>One Two " 138 "<body contenteditable='true'><span class='line' id='line'>One Two "
113 "Three</span></body>"); 139 "Three</span></body>");
114 140
115 FrameSelection& selection = document().frame()->selection();
116 Node* line = document().getElementById("line")->firstChild(); 141 Node* line = document().getElementById("line")->firstChild();
117 142
118 TapEventBuilder singleTapEvent(IntPoint(0, 0), 1); 143 TapEventBuilder singleTapEvent(IntPoint(0, 0), 1);
119 document().frame()->eventHandler().handleGestureEvent(singleTapEvent); 144 document().frame()->eventHandler().handleGestureEvent(singleTapEvent);
120 ASSERT_TRUE(selection.isCaret()); 145 ASSERT_TRUE(selection().isCaret());
121 EXPECT_EQ(Position(line, 0), selection.start()); 146 EXPECT_EQ(Position(line, 0), selection().start());
122 147
123 // Multi-tap events on editable elements should trigger selection, just 148 // Multi-tap events on editable elements should trigger selection, just
124 // like multi-click events. 149 // like multi-click events.
125 TapEventBuilder doubleTapEvent(IntPoint(0, 0), 2); 150 TapEventBuilder doubleTapEvent(IntPoint(0, 0), 2);
126 document().frame()->eventHandler().handleGestureEvent(doubleTapEvent); 151 document().frame()->eventHandler().handleGestureEvent(doubleTapEvent);
127 ASSERT_TRUE(selection.isRange()); 152 ASSERT_TRUE(selection().isRange());
128 EXPECT_EQ(Position(line, 0), selection.start()); 153 EXPECT_EQ(Position(line, 0), selection().start());
129 if (document().frame()->editor().isSelectTrailingWhitespaceEnabled()) { 154 if (document().frame()->editor().isSelectTrailingWhitespaceEnabled()) {
130 EXPECT_EQ(Position(line, 4), selection.end()); 155 EXPECT_EQ(Position(line, 4), selection().end());
131 EXPECT_EQ("One ", WebString(selection.selectedText()).utf8()); 156 EXPECT_EQ("One ", WebString(selection().selectedText()).utf8());
132 } else { 157 } else {
133 EXPECT_EQ(Position(line, 3), selection.end()); 158 EXPECT_EQ(Position(line, 3), selection().end());
134 EXPECT_EQ("One", WebString(selection.selectedText()).utf8()); 159 EXPECT_EQ("One", WebString(selection().selectedText()).utf8());
135 } 160 }
136 161
137 TapEventBuilder tripleTapEvent(IntPoint(0, 0), 3); 162 TapEventBuilder tripleTapEvent(IntPoint(0, 0), 3);
138 document().frame()->eventHandler().handleGestureEvent(tripleTapEvent); 163 document().frame()->eventHandler().handleGestureEvent(tripleTapEvent);
139 ASSERT_TRUE(selection.isRange()); 164 ASSERT_TRUE(selection().isRange());
140 EXPECT_EQ(Position(line, 0), selection.start()); 165 EXPECT_EQ(Position(line, 0), selection().start());
141 EXPECT_EQ(Position(line, 13), selection.end()); 166 EXPECT_EQ(Position(line, 13), selection().end());
142 EXPECT_EQ("One Two Three", WebString(selection.selectedText()).utf8()); 167 EXPECT_EQ("One Two Three", WebString(selection().selectedText()).utf8());
143 } 168 }
144 169
145 TEST_F(EventHandlerTest, multiClickSelectionFromTapDisabledIfNotEditable) { 170 TEST_F(EventHandlerTest, multiClickSelectionFromTapDisabledIfNotEditable) {
146 setHtmlInnerHTML( 171 setHtmlInnerHTML(
147 "<style> body { margin: 0px; } .line { display: block; width: 300px; " 172 "<style> body { margin: 0px; } .line { display: block; width: 300px; "
148 "height: 30px; } </style>" 173 "height: 30px; } </style>"
149 "<span class='line' id='line'>One Two Three</span>"); 174 "<span class='line' id='line'>One Two Three</span>");
150 175
151 FrameSelection& selection = document().frame()->selection();
152 Node* line = document().getElementById("line")->firstChild(); 176 Node* line = document().getElementById("line")->firstChild();
153 177
154 TapEventBuilder singleTapEvent(IntPoint(0, 0), 1); 178 TapEventBuilder singleTapEvent(IntPoint(0, 0), 1);
155 document().frame()->eventHandler().handleGestureEvent(singleTapEvent); 179 document().frame()->eventHandler().handleGestureEvent(singleTapEvent);
156 ASSERT_TRUE(selection.isCaret()); 180 ASSERT_TRUE(selection().isCaret());
157 EXPECT_EQ(Position(line, 0), selection.start()); 181 EXPECT_EQ(Position(line, 0), selection().start());
158 182
159 // As the text is readonly, multi-tap events should not trigger selection. 183 // As the text is readonly, multi-tap events should not trigger selection.
160 TapEventBuilder doubleTapEvent(IntPoint(0, 0), 2); 184 TapEventBuilder doubleTapEvent(IntPoint(0, 0), 2);
161 document().frame()->eventHandler().handleGestureEvent(doubleTapEvent); 185 document().frame()->eventHandler().handleGestureEvent(doubleTapEvent);
162 ASSERT_TRUE(selection.isCaret()); 186 ASSERT_TRUE(selection().isCaret());
163 EXPECT_EQ(Position(line, 0), selection.start()); 187 EXPECT_EQ(Position(line, 0), selection().start());
164 188
165 TapEventBuilder tripleTapEvent(IntPoint(0, 0), 3); 189 TapEventBuilder tripleTapEvent(IntPoint(0, 0), 3);
166 document().frame()->eventHandler().handleGestureEvent(tripleTapEvent); 190 document().frame()->eventHandler().handleGestureEvent(tripleTapEvent);
167 ASSERT_TRUE(selection.isCaret()); 191 ASSERT_TRUE(selection().isCaret());
168 EXPECT_EQ(Position(line, 0), selection.start()); 192 EXPECT_EQ(Position(line, 0), selection().start());
169 } 193 }
170 194
171 TEST_F(EventHandlerTest, draggedInlinePositionTest) { 195 TEST_F(EventHandlerTest, draggedInlinePositionTest) {
172 setHtmlInnerHTML( 196 setHtmlInnerHTML(
173 "<style>" 197 "<style>"
174 "body { margin: 0px; }" 198 "body { margin: 0px; }"
175 ".line { font-family: sans-serif; background: blue; width: 300px; " 199 ".line { font-family: sans-serif; background: blue; width: 300px; "
176 "height: 30px; font-size: 40px; margin-left: 250px; }" 200 "height: 30px; font-size: 40px; margin-left: 250px; }"
177 "</style>" 201 "</style>"
178 "<div style='width: 300px; height: 100px;'>" 202 "<div style='width: 300px; height: 100px;'>"
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
248 .build()); 272 .build());
249 PlatformMouseEvent mouseDownEvent( 273 PlatformMouseEvent mouseDownEvent(
250 IntPoint(0, 0), IntPoint(100, 200), WebPointerProperties::Button::Right, 274 IntPoint(0, 0), IntPoint(100, 200), WebPointerProperties::Button::Right,
251 PlatformEvent::MousePressed, 1, PlatformEvent::Modifiers::RightButtonDown, 275 PlatformEvent::MousePressed, 1, PlatformEvent::Modifiers::RightButtonDown,
252 WTF::monotonicallyIncreasingTime()); 276 WTF::monotonicallyIncreasingTime());
253 EXPECT_EQ( 277 EXPECT_EQ(
254 WebInputEventResult::HandledApplication, 278 WebInputEventResult::HandledApplication,
255 document().frame()->eventHandler().sendContextMenuEvent(mouseDownEvent)); 279 document().frame()->eventHandler().sendContextMenuEvent(mouseDownEvent));
256 } 280 }
257 281
282 TEST_F(EventHandlerTest, EmptyTextfieldInsertionOnTap) {
283 setHtmlInnerHTML("<textarea cols=50 rows=50></textarea>");
284
285 TapEventBuilder singleTapEvent(IntPoint(200, 200), 1);
286 document().frame()->eventHandler().handleGestureEvent(singleTapEvent);
287
288 ASSERT_TRUE(selection().isCaret());
289 ASSERT_FALSE(selection().isHandleVisible());
290 }
291
292 TEST_F(EventHandlerTest, NonEmptyTextfieldInsertionOnTap) {
293 setHtmlInnerHTML("<textarea cols=50 rows=50>Enter text</textarea>");
294
295 TapEventBuilder singleTapEvent(IntPoint(200, 200), 1);
296 document().frame()->eventHandler().handleGestureEvent(singleTapEvent);
297
298 ASSERT_TRUE(selection().isCaret());
299 ASSERT_TRUE(selection().isHandleVisible());
300 }
301
302 TEST_F(EventHandlerTest, EmptyTextfieldInsertionOnLongPress) {
303 setHtmlInnerHTML("<textarea cols=50 rows=50></textarea>");
304
305 LongPressEventBuilder longPressEvent(IntPoint(200, 200));
306 document().frame()->eventHandler().handleGestureEvent(longPressEvent);
307
308 ASSERT_TRUE(selection().isCaret());
309 ASSERT_TRUE(selection().isHandleVisible());
310
311 // Single Tap on an empty edit field should clear insertion handle
312 TapEventBuilder singleTapEvent(IntPoint(200, 200), 1);
313 document().frame()->eventHandler().handleGestureEvent(singleTapEvent);
314
315 ASSERT_TRUE(selection().isCaret());
316 ASSERT_FALSE(selection().isHandleVisible());
317 }
318
319 TEST_F(EventHandlerTest, NonEmptyTextfieldInsertionOnLongPress) {
320 setHtmlInnerHTML("<textarea cols=50 rows=50>Enter text</textarea>");
321
322 LongPressEventBuilder longPressEvent(IntPoint(200, 200));
323 document().frame()->eventHandler().handleGestureEvent(longPressEvent);
324
325 ASSERT_TRUE(selection().isCaret());
326 ASSERT_TRUE(selection().isHandleVisible());
327 }
328
329 TEST_F(EventHandlerTest, ClearHandleAfterTap) {
330 setHtmlInnerHTML("<textarea cols=50 rows=50>Enter text</textarea>");
331
332 // Show handle
333 LongPressEventBuilder longPressEvent(IntPoint(200, 200));
334 document().frame()->eventHandler().handleGestureEvent(longPressEvent);
335
336 ASSERT_TRUE(selection().isCaret());
337 ASSERT_TRUE(selection().isHandleVisible());
338
339 // Tap away from text area should clear handle
340 TapEventBuilder singleTapEvent(IntPoint(700, 700), 1);
341 document().frame()->eventHandler().handleGestureEvent(singleTapEvent);
342
343 ASSERT_TRUE(selection().isNone());
344 ASSERT_FALSE(selection().isHandleVisible());
345 }
346
347 TEST_F(EventHandlerTest, HandleNotShownOnMouseEvents) {
348 setHtmlInnerHTML("<textarea cols=50 rows=50>Enter text</textarea>");
349
350 MousePressEventBuilder leftMousePressEvent(
351 IntPoint(200, 200), 1, WebPointerProperties::Button::Left);
352 document().frame()->eventHandler().handleMousePressEvent(leftMousePressEvent);
353
354 ASSERT_TRUE(selection().isCaret());
355 ASSERT_FALSE(selection().isHandleVisible());
356
357 MousePressEventBuilder rightMousePressEvent(
358 IntPoint(200, 200), 1, WebPointerProperties::Button::Right);
359 document().frame()->eventHandler().handleMousePressEvent(
360 rightMousePressEvent);
361
362 ASSERT_TRUE(selection().isCaret());
363 ASSERT_FALSE(selection().isHandleVisible());
364
365 MousePressEventBuilder doubleClickMousePressEvent(
366 IntPoint(200, 200), 2, WebPointerProperties::Button::Left);
367 document().frame()->eventHandler().handleMousePressEvent(
368 doubleClickMousePressEvent);
369
370 ASSERT_TRUE(selection().isRange());
371 ASSERT_FALSE(selection().isHandleVisible());
372
373 MousePressEventBuilder tripleClickMousePressEvent(
374 IntPoint(200, 200), 3, WebPointerProperties::Button::Left);
375 document().frame()->eventHandler().handleMousePressEvent(
376 tripleClickMousePressEvent);
377
378 ASSERT_TRUE(selection().isRange());
379 ASSERT_FALSE(selection().isHandleVisible());
380 }
381
258 } // namespace blink 382 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698