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

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

Powered by Google App Engine
This is Rietveld 408576698