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

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

Powered by Google App Engine
This is Rietveld 408576698