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

Side by Side Diff: content/shell/renderer/test_runner/EventSender.cpp

Issue 110533009: Import TestRunner library into chromium. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: updates Created 7 years 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 | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright 2013 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 // This file contains the definition for EventSender.
6 //
7 // Some notes about drag and drop handling:
8 // Windows drag and drop goes through a system call to doDragDrop. At that
9 // point, program control is given to Windows which then periodically makes
10 // callbacks into the webview. This won't work for layout tests, so instead,
11 // we queue up all the mouse move and mouse up events. When the test tries to
12 // start a drag (by calling EvenSendingController::doDragDrop), we take the
13 // events in the queue and replay them.
14 // The behavior of queuing events and replaying them can be disabled by a
15 // layout test by setting eventSender.dragMode to false.
16
17 #include "content/shell/renderer/test_runner/EventSender.h"
18
19 #include <deque>
20
21 #include "content/shell/renderer/test_runner/KeyCodeMapping.h"
22 #include "content/shell/renderer/test_runner/MockSpellCheck.h"
23 #include "content/shell/renderer/test_runner/TestCommon.h"
24 #include "content/shell/renderer/test_runner/TestInterfaces.h"
25 #include "content/shell/renderer/test_runner/WebTestDelegate.h"
26 #include "content/shell/renderer/test_runner/WebTestProxy.h"
27 #include "third_party/WebKit/public/platform/WebDragData.h"
28 #include "third_party/WebKit/public/platform/WebString.h"
29 #include "third_party/WebKit/public/platform/WebVector.h"
30 #include "third_party/WebKit/public/web/WebContextMenuData.h"
31 #include "third_party/WebKit/public/web/WebTouchPoint.h"
32 #include "third_party/WebKit/public/web/WebView.h"
33
34 #ifdef WIN32
35 #include "third_party/WebKit/public/web/win/WebInputEventFactory.h"
36 #elif __APPLE__
37 #include "third_party/WebKit/public/web/mac/WebInputEventFactory.h"
38 #elif defined(ANDROID)
39 #include "third_party/WebKit/public/web/android/WebInputEventFactory.h"
40 #elif defined(TOOLKIT_GTK)
41 #include "third_party/WebKit/public/web/gtk/WebInputEventFactory.h"
42 #endif
43
44 // FIXME: layout before each event?
45
46 using namespace std;
47 using namespace blink;
48
49 namespace WebTestRunner {
50
51 WebPoint EventSender::lastMousePos;
52 WebMouseEvent::Button EventSender::pressedButton = WebMouseEvent::ButtonNone;
53 WebMouseEvent::Button EventSender::lastButtonType = WebMouseEvent::ButtonNone;
54
55 namespace {
56
57 struct SavedEvent {
58 enum SavedEventType {
59 Unspecified,
60 MouseUp,
61 MouseMove,
62 LeapForward
63 };
64
65 SavedEventType type;
66 WebMouseEvent::Button buttonType; // For MouseUp.
67 WebPoint pos; // For MouseMove.
68 int milliseconds; // For LeapForward.
69
70 SavedEvent()
71 : type(Unspecified)
72 , buttonType(WebMouseEvent::ButtonNone)
73 , milliseconds(0) { }
74 };
75
76 WebDragData currentDragData;
77 WebDragOperation currentDragEffect;
78 WebDragOperationsMask currentDragEffectsAllowed;
79 bool replayingSavedEvents = false;
80 deque<SavedEvent> mouseEventQueue;
81 int touchModifiers;
82 vector<WebTouchPoint> touchPoints;
83
84 // Time and place of the last mouse up event.
85 double lastClickTimeSec = 0;
86 WebPoint lastClickPos;
87 int clickCount = 0;
88
89 // maximum distance (in space and time) for a mouse click
90 // to register as a double or triple click
91 const double multipleClickTimeSec = 1;
92 const int multipleClickRadiusPixels = 5;
93
94 // How much we should scroll per event - the value here is chosen to
95 // match the WebKit impl and layout test results.
96 const float scrollbarPixelsPerTick = 40.0f;
97
98 inline bool outsideMultiClickRadius(const WebPoint& a, const WebPoint& b)
99 {
100 return ((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)) >
101 multipleClickRadiusPixels * multipleClickRadiusPixels;
102 }
103
104 // Used to offset the time the event hander things an event happened. This is
105 // done so tests can run without a delay, but bypass checks that are time
106 // dependent (e.g., dragging has a timeout vs selection).
107 uint32 timeOffsetMs = 0;
108
109 double getCurrentEventTimeSec(WebTestDelegate* delegate)
110 {
111 return (delegate->getCurrentTimeInMillisecond() + timeOffsetMs) / 1000.0;
112 }
113
114 void advanceEventTime(int32_t deltaMs)
115 {
116 timeOffsetMs += deltaMs;
117 }
118
119 void initMouseEvent(WebInputEvent::Type t, WebMouseEvent::Button b, const WebPoi nt& pos, WebMouseEvent* e, double ts)
120 {
121 e->type = t;
122 e->button = b;
123 e->modifiers = 0;
124 e->x = pos.x;
125 e->y = pos.y;
126 e->globalX = pos.x;
127 e->globalY = pos.y;
128 e->timeStampSeconds = ts;
129 e->clickCount = clickCount;
130 }
131
132 void applyKeyModifier(const string& modifierName, WebInputEvent* event)
133 {
134 const char* characters = modifierName.c_str();
135 if (!strcmp(characters, "ctrlKey")
136 #ifndef __APPLE__
137 || !strcmp(characters, "addSelectionKey")
138 #endif
139 ) {
140 event->modifiers |= WebInputEvent::ControlKey;
141 } else if (!strcmp(characters, "shiftKey") || !strcmp(characters, "rangeSele ctionKey"))
142 event->modifiers |= WebInputEvent::ShiftKey;
143 else if (!strcmp(characters, "altKey")) {
144 event->modifiers |= WebInputEvent::AltKey;
145 #ifdef __APPLE__
146 } else if (!strcmp(characters, "metaKey") || !strcmp(characters, "addSelecti onKey")) {
147 event->modifiers |= WebInputEvent::MetaKey;
148 #else
149 } else if (!strcmp(characters, "metaKey")) {
150 event->modifiers |= WebInputEvent::MetaKey;
151 #endif
152 } else if (!strcmp(characters, "autoRepeat")) {
153 event->modifiers |= WebInputEvent::IsAutoRepeat;
154 }
155 }
156
157 void applyKeyModifiers(const CppVariant* argument, WebInputEvent* event)
158 {
159 if (argument->isObject()) {
160 vector<string> modifiers = argument->toStringVector();
161 for (vector<string>::const_iterator i = modifiers.begin(); i != modifier s.end(); ++i)
162 applyKeyModifier(*i, event);
163 } else if (argument->isString()) {
164 applyKeyModifier(argument->toString(), event);
165 }
166 }
167
168 // Get the edit command corresponding to a keyboard event.
169 // Returns true if the specified event corresponds to an edit command, the name
170 // of the edit command will be stored in |*name|.
171 bool getEditCommand(const WebKeyboardEvent& event, string* name)
172 {
173 #ifdef __APPLE__
174 // We only cares about Left,Right,Up,Down keys with Command or Command+Shift
175 // modifiers. These key events correspond to some special movement and
176 // selection editor commands, and was supposed to be handled in
177 // WebKit/chromium/src/EditorClientImpl.cpp. But these keys will be marked
178 // as system key, which prevents them from being handled. Thus they must be
179 // handled specially.
180 if ((event.modifiers & ~WebKeyboardEvent::ShiftKey) != WebKeyboardEvent::Met aKey)
181 return false;
182
183 switch (event.windowsKeyCode) {
184 case VKEY_LEFT:
185 *name = "MoveToBeginningOfLine";
186 break;
187 case VKEY_RIGHT:
188 *name = "MoveToEndOfLine";
189 break;
190 case VKEY_UP:
191 *name = "MoveToBeginningOfDocument";
192 break;
193 case VKEY_DOWN:
194 *name = "MoveToEndOfDocument";
195 break;
196 default:
197 return false;
198 }
199
200 if (event.modifiers & WebKeyboardEvent::ShiftKey)
201 name->append("AndModifySelection");
202
203 return true;
204 #else
205 return false;
206 #endif
207 }
208
209 // Key event location code introduced in DOM Level 3.
210 // See also: http://www.w3.org/TR/DOM-Level-3-Events/#events-keyboardevents
211 enum KeyLocationCode {
212 DOMKeyLocationStandard = 0x00,
213 DOMKeyLocationLeft = 0x01,
214 DOMKeyLocationRight = 0x02,
215 DOMKeyLocationNumpad = 0x03
216 };
217
218 }
219
220 EventSender::EventSender(TestInterfaces* interfaces)
221 : m_testInterfaces(interfaces)
222 , m_delegate(0)
223 {
224 // Initialize the map that associates methods of this class with the names
225 // they will use when called by JavaScript. The actual binding of those
226 // names to their methods will be done by calling bindToJavaScript() (define d
227 // by CppBoundClass, the parent to EventSender).
228 bindMethod("addTouchPoint", &EventSender::addTouchPoint);
229 bindMethod("beginDragWithFiles", &EventSender::beginDragWithFiles);
230 bindMethod("cancelTouchPoint", &EventSender::cancelTouchPoint);
231 bindMethod("clearKillRing", &EventSender::clearKillRing);
232 bindMethod("clearTouchPoints", &EventSender::clearTouchPoints);
233 bindMethod("contextClick", &EventSender::contextClick);
234 bindMethod("continuousMouseScrollBy", &EventSender::continuousMouseScrollBy) ;
235 bindMethod("dispatchMessage", &EventSender::dispatchMessage);
236 bindMethod("dumpFilenameBeingDragged", &EventSender::dumpFilenameBeingDragge d);
237 bindMethod("enableDOMUIEventLogging", &EventSender::enableDOMUIEventLogging) ;
238 bindMethod("fireKeyboardEventsToElement", &EventSender::fireKeyboardEventsTo Element);
239 bindMethod("keyDown", &EventSender::keyDown);
240 bindMethod("leapForward", &EventSender::leapForward);
241 bindMethod("mouseDown", &EventSender::mouseDown);
242 bindMethod("mouseMoveTo", &EventSender::mouseMoveTo);
243 bindMethod("mouseScrollBy", &EventSender::mouseScrollBy);
244 bindMethod("mouseUp", &EventSender::mouseUp);
245 bindMethod("mouseDragBegin", &EventSender::mouseDragBegin);
246 bindMethod("mouseDragEnd", &EventSender::mouseDragEnd);
247 bindMethod("mouseMomentumBegin", &EventSender::mouseMomentumBegin);
248 bindMethod("mouseMomentumScrollBy", &EventSender::mouseMomentumScrollBy);
249 bindMethod("mouseMomentumEnd", &EventSender::mouseMomentumEnd);
250 bindMethod("releaseTouchPoint", &EventSender::releaseTouchPoint);
251 bindMethod("scheduleAsynchronousClick", &EventSender::scheduleAsynchronousCl ick);
252 bindMethod("scheduleAsynchronousKeyDown", &EventSender::scheduleAsynchronous KeyDown);
253 bindMethod("setTouchModifier", &EventSender::setTouchModifier);
254 bindMethod("textZoomIn", &EventSender::textZoomIn);
255 bindMethod("textZoomOut", &EventSender::textZoomOut);
256 bindMethod("touchCancel", &EventSender::touchCancel);
257 bindMethod("touchEnd", &EventSender::touchEnd);
258 bindMethod("touchMove", &EventSender::touchMove);
259 bindMethod("touchStart", &EventSender::touchStart);
260 bindMethod("updateTouchPoint", &EventSender::updateTouchPoint);
261 bindMethod("gestureFlingCancel", &EventSender::gestureFlingCancel);
262 bindMethod("gestureFlingStart", &EventSender::gestureFlingStart);
263 bindMethod("gestureScrollBegin", &EventSender::gestureScrollBegin);
264 bindMethod("gestureScrollEnd", &EventSender::gestureScrollEnd);
265 bindMethod("gestureScrollFirstPoint", &EventSender::gestureScrollFirstPoint) ;
266 bindMethod("gestureScrollUpdate", &EventSender::gestureScrollUpdate);
267 bindMethod("gestureScrollUpdateWithoutPropagation", &EventSender::gestureScr ollUpdateWithoutPropagation);
268 bindMethod("gestureTap", &EventSender::gestureTap);
269 bindMethod("gestureTapDown", &EventSender::gestureTapDown);
270 bindMethod("gestureShowPress", &EventSender::gestureShowPress);
271 bindMethod("gestureTapCancel", &EventSender::gestureTapCancel);
272 bindMethod("gestureLongPress", &EventSender::gestureLongPress);
273 bindMethod("gestureLongTap", &EventSender::gestureLongTap);
274 bindMethod("gestureTwoFingerTap", &EventSender::gestureTwoFingerTap);
275 bindMethod("zoomPageIn", &EventSender::zoomPageIn);
276 bindMethod("zoomPageOut", &EventSender::zoomPageOut);
277 bindMethod("setPageScaleFactor", &EventSender::setPageScaleFactor);
278
279 bindProperty("forceLayoutOnEvents", &forceLayoutOnEvents);
280
281 // When set to true (the default value), we batch mouse move and mouse up
282 // events so we can simulate drag & drop.
283 bindProperty("dragMode", &dragMode);
284 #ifdef WIN32
285 bindProperty("WM_KEYDOWN", &wmKeyDown);
286 bindProperty("WM_KEYUP", &wmKeyUp);
287 bindProperty("WM_CHAR", &wmChar);
288 bindProperty("WM_DEADCHAR", &wmDeadChar);
289 bindProperty("WM_SYSKEYDOWN", &wmSysKeyDown);
290 bindProperty("WM_SYSKEYUP", &wmSysKeyUp);
291 bindProperty("WM_SYSCHAR", &wmSysChar);
292 bindProperty("WM_SYSDEADCHAR", &wmSysDeadChar);
293 #endif
294 }
295
296 EventSender::~EventSender()
297 {
298 }
299
300 void EventSender::setContextMenuData(const WebContextMenuData& contextMenuData)
301 {
302 m_lastContextMenuData = WebScopedPtr<WebContextMenuData>(new WebContextMenuD ata(contextMenuData));
303 }
304
305 void EventSender::reset()
306 {
307 // The test should have finished a drag and the mouse button state.
308 BLINK_ASSERT(currentDragData.isNull());
309 currentDragData.reset();
310 currentDragEffect = blink::WebDragOperationNone;
311 currentDragEffectsAllowed = blink::WebDragOperationNone;
312 if (webview() && pressedButton != WebMouseEvent::ButtonNone)
313 webview()->mouseCaptureLost();
314 pressedButton = WebMouseEvent::ButtonNone;
315 dragMode.set(true);
316 forceLayoutOnEvents.set(true);
317 #ifdef WIN32
318 wmKeyDown.set(WM_KEYDOWN);
319 wmKeyUp.set(WM_KEYUP);
320 wmChar.set(WM_CHAR);
321 wmDeadChar.set(WM_DEADCHAR);
322 wmSysKeyDown.set(WM_SYSKEYDOWN);
323 wmSysKeyUp.set(WM_SYSKEYUP);
324 wmSysChar.set(WM_SYSCHAR);
325 wmSysDeadChar.set(WM_SYSDEADCHAR);
326 #endif
327 lastMousePos = WebPoint(0, 0);
328 lastClickTimeSec = 0;
329 lastClickPos = WebPoint(0, 0);
330 clickCount = 0;
331 lastButtonType = WebMouseEvent::ButtonNone;
332 timeOffsetMs = 0;
333 touchModifiers = 0;
334 touchPoints.clear();
335 m_taskList.revokeAll();
336 m_currentGestureLocation = WebPoint(0, 0);
337 mouseEventQueue.clear();
338 }
339
340 void EventSender::doDragDrop(const WebDragData& dragData, WebDragOperationsMask mask)
341 {
342 WebMouseEvent event;
343 initMouseEvent(WebInputEvent::MouseDown, pressedButton, lastMousePos, &event , getCurrentEventTimeSec(m_delegate));
344 WebPoint clientPoint(event.x, event.y);
345 WebPoint screenPoint(event.globalX, event.globalY);
346 currentDragData = dragData;
347 currentDragEffectsAllowed = mask;
348 currentDragEffect = webview()->dragTargetDragEnter(dragData, clientPoint, sc reenPoint, currentDragEffectsAllowed, 0);
349
350 // Finish processing events.
351 replaySavedEvents();
352 }
353
354 void EventSender::dumpFilenameBeingDragged(const CppArgumentList&, CppVariant*)
355 {
356 WebString filename;
357 WebVector<WebDragData::Item> items = currentDragData.items();
358 for (size_t i = 0; i < items.size(); ++i) {
359 if (items[i].storageType == WebDragData::Item::StorageTypeBinaryData) {
360 filename = items[i].title;
361 break;
362 }
363 }
364 m_delegate->printMessage(std::string("Filename being dragged: ") + filename. utf8().data() + "\n");
365 }
366
367 WebMouseEvent::Button EventSender::getButtonTypeFromButtonNumber(int buttonCode)
368 {
369 if (!buttonCode)
370 return WebMouseEvent::ButtonLeft;
371 if (buttonCode == 2)
372 return WebMouseEvent::ButtonRight;
373 return WebMouseEvent::ButtonMiddle;
374 }
375
376 int EventSender::getButtonNumberFromSingleArg(const CppArgumentList& arguments)
377 {
378 int buttonCode = 0;
379 if (arguments.size() > 0 && arguments[0].isNumber())
380 buttonCode = arguments[0].toInt32();
381 return buttonCode;
382 }
383
384 void EventSender::updateClickCountForButton(WebMouseEvent::Button buttonType)
385 {
386 if ((getCurrentEventTimeSec(m_delegate) - lastClickTimeSec < multipleClickTi meSec)
387 && (!outsideMultiClickRadius(lastMousePos, lastClickPos))
388 && (buttonType == lastButtonType))
389 ++clickCount;
390 else {
391 clickCount = 1;
392 lastButtonType = buttonType;
393 }
394 }
395
396 //
397 // Implemented javascript methods.
398 //
399
400 void EventSender::mouseDown(const CppArgumentList& arguments, CppVariant* result )
401 {
402 if (result) // Could be 0 if invoked asynchronously.
403 result->setNull();
404
405 if (shouldForceLayoutOnEvents())
406 webview()->layout();
407
408 int buttonNumber = getButtonNumberFromSingleArg(arguments);
409 BLINK_ASSERT(buttonNumber != -1);
410
411 WebMouseEvent::Button buttonType = getButtonTypeFromButtonNumber(buttonNumbe r);
412
413 updateClickCountForButton(buttonType);
414
415 WebMouseEvent event;
416 pressedButton = buttonType;
417 initMouseEvent(WebInputEvent::MouseDown, buttonType, lastMousePos, &event, g etCurrentEventTimeSec(m_delegate));
418 if (arguments.size() >= 2 && (arguments[1].isObject() || arguments[1].isStri ng()))
419 applyKeyModifiers(&(arguments[1]), &event);
420 webview()->handleInputEvent(event);
421 }
422
423 void EventSender::mouseUp(const CppArgumentList& arguments, CppVariant* result)
424 {
425 if (result) // Could be 0 if invoked asynchronously.
426 result->setNull();
427
428 if (shouldForceLayoutOnEvents())
429 webview()->layout();
430
431 int buttonNumber = getButtonNumberFromSingleArg(arguments);
432 BLINK_ASSERT(buttonNumber != -1);
433
434 WebMouseEvent::Button buttonType = getButtonTypeFromButtonNumber(buttonNumbe r);
435
436 if (isDragMode() && !replayingSavedEvents) {
437 SavedEvent savedEvent;
438 savedEvent.type = SavedEvent::MouseUp;
439 savedEvent.buttonType = buttonType;
440 mouseEventQueue.push_back(savedEvent);
441 replaySavedEvents();
442 } else {
443 WebMouseEvent event;
444 initMouseEvent(WebInputEvent::MouseUp, buttonType, lastMousePos, &event, getCurrentEventTimeSec(m_delegate));
445 if (arguments.size() >= 2 && (arguments[1].isObject() || arguments[1].is String()))
446 applyKeyModifiers(&(arguments[1]), &event);
447 doMouseUp(event);
448 }
449 }
450
451 void EventSender::doMouseUp(const WebMouseEvent& e)
452 {
453 webview()->handleInputEvent(e);
454
455 pressedButton = WebMouseEvent::ButtonNone;
456 lastClickTimeSec = e.timeStampSeconds;
457 lastClickPos = lastMousePos;
458
459 // If we're in a drag operation, complete it.
460 if (currentDragData.isNull())
461 return;
462
463 WebPoint clientPoint(e.x, e.y);
464 WebPoint screenPoint(e.globalX, e.globalY);
465 finishDragAndDrop(e, webview()->dragTargetDragOver(clientPoint, screenPoint, currentDragEffectsAllowed, 0));
466 }
467
468 void EventSender::finishDragAndDrop(const WebMouseEvent& e, blink::WebDragOperat ion dragEffect)
469 {
470 WebPoint clientPoint(e.x, e.y);
471 WebPoint screenPoint(e.globalX, e.globalY);
472 currentDragEffect = dragEffect;
473 if (currentDragEffect)
474 webview()->dragTargetDrop(clientPoint, screenPoint, 0);
475 else
476 webview()->dragTargetDragLeave();
477 webview()->dragSourceEndedAt(clientPoint, screenPoint, currentDragEffect);
478 webview()->dragSourceSystemDragEnded();
479
480 currentDragData.reset();
481 }
482
483 void EventSender::mouseMoveTo(const CppArgumentList& arguments, CppVariant* resu lt)
484 {
485 result->setNull();
486
487 if (arguments.size() < 2 || !arguments[0].isNumber() || !arguments[1].isNumb er())
488 return;
489 if (shouldForceLayoutOnEvents())
490 webview()->layout();
491
492 WebPoint mousePos(arguments[0].toInt32(), arguments[1].toInt32());
493
494 if (isDragMode() && pressedButton == WebMouseEvent::ButtonLeft && !replaying SavedEvents) {
495 SavedEvent savedEvent;
496 savedEvent.type = SavedEvent::MouseMove;
497 savedEvent.pos = mousePos;
498 mouseEventQueue.push_back(savedEvent);
499 } else {
500 WebMouseEvent event;
501 initMouseEvent(WebInputEvent::MouseMove, pressedButton, mousePos, &event , getCurrentEventTimeSec(m_delegate));
502 if (arguments.size() >= 3 && (arguments[2].isObject() || arguments[2].is String()))
503 applyKeyModifiers(&(arguments[2]), &event);
504 doMouseMove(event);
505 }
506 }
507
508 void EventSender::doMouseMove(const WebMouseEvent& e)
509 {
510 lastMousePos = WebPoint(e.x, e.y);
511
512 webview()->handleInputEvent(e);
513
514 if (pressedButton == WebMouseEvent::ButtonNone || currentDragData.isNull())
515 return;
516 WebPoint clientPoint(e.x, e.y);
517 WebPoint screenPoint(e.globalX, e.globalY);
518 currentDragEffect = webview()->dragTargetDragOver(clientPoint, screenPoint, currentDragEffectsAllowed, 0);
519 }
520
521 void EventSender::keyDown(const CppArgumentList& arguments, CppVariant* result)
522 {
523 if (result)
524 result->setNull();
525 if (arguments.size() < 1 || !arguments[0].isString())
526 return;
527 bool generateChar = false;
528
529 // FIXME: I'm not exactly sure how we should convert the string to a key
530 // event. This seems to work in the cases I tested.
531 // FIXME: Should we also generate a KEY_UP?
532 string codeStr = arguments[0].toString();
533
534 // Convert \n -> VK_RETURN. Some layout tests use \n to mean "Enter", when
535 // Windows uses \r for "Enter".
536 int code = 0;
537 int text = 0;
538 bool needsShiftKeyModifier = false;
539 if ("\n" == codeStr) {
540 generateChar = true;
541 text = code = VKEY_RETURN;
542 } else if ("rightArrow" == codeStr)
543 code = VKEY_RIGHT;
544 else if ("downArrow" == codeStr)
545 code = VKEY_DOWN;
546 else if ("leftArrow" == codeStr)
547 code = VKEY_LEFT;
548 else if ("upArrow" == codeStr)
549 code = VKEY_UP;
550 else if ("insert" == codeStr)
551 code = VKEY_INSERT;
552 else if ("delete" == codeStr)
553 code = VKEY_DELETE;
554 else if ("pageUp" == codeStr)
555 code = VKEY_PRIOR;
556 else if ("pageDown" == codeStr)
557 code = VKEY_NEXT;
558 else if ("home" == codeStr)
559 code = VKEY_HOME;
560 else if ("end" == codeStr)
561 code = VKEY_END;
562 else if ("printScreen" == codeStr)
563 code = VKEY_SNAPSHOT;
564 else if ("menu" == codeStr)
565 code = VKEY_APPS;
566 else if ("leftControl" == codeStr)
567 code = VKEY_LCONTROL;
568 else if ("rightControl" == codeStr)
569 code = VKEY_RCONTROL;
570 else if ("leftShift" == codeStr)
571 code = VKEY_LSHIFT;
572 else if ("rightShift" == codeStr)
573 code = VKEY_RSHIFT;
574 else if ("leftAlt" == codeStr)
575 code = VKEY_LMENU;
576 else if ("rightAlt" == codeStr)
577 code = VKEY_RMENU;
578 else if ("numLock" == codeStr)
579 code = VKEY_NUMLOCK;
580 else {
581 // Compare the input string with the function-key names defined by the
582 // DOM spec (i.e. "F1",...,"F24"). If the input string is a function-key
583 // name, set its key code.
584 for (int i = 1; i <= 24; ++i) {
585 char functionChars[10];
586 snprintf(functionChars, 10, "F%d", i);
587 string functionKeyName(functionChars);
588 if (functionKeyName == codeStr) {
589 code = VKEY_F1 + (i - 1);
590 break;
591 }
592 }
593 if (!code) {
594 WebString webCodeStr = WebString::fromUTF8(codeStr.data(), codeStr.s ize());
595 BLINK_ASSERT(webCodeStr.length() == 1);
596 text = code = webCodeStr.at(0);
597 needsShiftKeyModifier = needsShiftModifier(code);
598 if ((code & 0xFF) >= 'a' && (code & 0xFF) <= 'z')
599 code -= 'a' - 'A';
600 generateChar = true;
601 }
602
603 if ("(" == codeStr) {
604 code = '9';
605 needsShiftKeyModifier = true;
606 }
607 }
608
609 // For one generated keyboard event, we need to generate a keyDown/keyUp
610 // pair; refer to EventSender.cpp in Tools/DumpRenderTree/win.
611 // On Windows, we might also need to generate a char event to mimic the
612 // Windows event flow; on other platforms we create a merged event and test
613 // the event flow that that platform provides.
614 WebKeyboardEvent eventDown, eventChar, eventUp;
615 eventDown.type = WebInputEvent::RawKeyDown;
616 eventDown.modifiers = 0;
617 eventDown.windowsKeyCode = code;
618 #if defined(__linux__) && defined(TOOLKIT_GTK)
619 eventDown.nativeKeyCode = NativeKeyCodeForWindowsKeyCode(code);
620 #endif
621
622 if (generateChar) {
623 eventDown.text[0] = text;
624 eventDown.unmodifiedText[0] = text;
625 }
626 eventDown.setKeyIdentifierFromWindowsKeyCode();
627
628 if (arguments.size() >= 2 && (arguments[1].isObject() || arguments[1].isStri ng())) {
629 applyKeyModifiers(&(arguments[1]), &eventDown);
630 #if WIN32 || __APPLE__ || defined(ANDROID) || defined(TOOLKIT_GTK)
631 eventDown.isSystemKey = WebInputEventFactory::isSystemKeyEvent(eventDown );
632 #endif
633 }
634
635 if (needsShiftKeyModifier)
636 eventDown.modifiers |= WebInputEvent::ShiftKey;
637
638 // See if KeyLocation argument is given.
639 if (arguments.size() >= 3 && arguments[2].isNumber()) {
640 int location = arguments[2].toInt32();
641 if (location == DOMKeyLocationNumpad)
642 eventDown.modifiers |= WebInputEvent::IsKeyPad;
643 }
644
645 eventChar = eventUp = eventDown;
646 eventUp.type = WebInputEvent::KeyUp;
647 // EventSender.m forces a layout here, with at least one
648 // test (fast/forms/focus-control-to-page.html) relying on this.
649 if (shouldForceLayoutOnEvents())
650 webview()->layout();
651
652 // In the browser, if a keyboard event corresponds to an editor command,
653 // the command will be dispatched to the renderer just before dispatching
654 // the keyboard event, and then it will be executed in the
655 // RenderView::handleCurrentKeyboardEvent() method, which is called from
656 // third_party/WebKit/Source/WebKit/chromium/src/EditorClientImpl.cpp.
657 // We just simulate the same behavior here.
658 string editCommand;
659 if (getEditCommand(eventDown, &editCommand))
660 m_delegate->setEditCommand(editCommand, "");
661
662 webview()->handleInputEvent(eventDown);
663
664 if (code == VKEY_ESCAPE && !currentDragData.isNull()) {
665 WebMouseEvent event;
666 initMouseEvent(WebInputEvent::MouseDown, pressedButton, lastMousePos, &e vent, getCurrentEventTimeSec(m_delegate));
667 finishDragAndDrop(event, blink::WebDragOperationNone);
668 }
669
670 m_delegate->clearEditCommand();
671
672 if (generateChar) {
673 eventChar.type = WebInputEvent::Char;
674 eventChar.keyIdentifier[0] = '\0';
675 webview()->handleInputEvent(eventChar);
676 }
677
678 webview()->handleInputEvent(eventUp);
679 }
680
681 void EventSender::dispatchMessage(const CppArgumentList& arguments, CppVariant* result)
682 {
683 result->setNull();
684
685 #ifdef WIN32
686 if (arguments.size() == 3) {
687 // Grab the message id to see if we need to dispatch it.
688 int msg = arguments[0].toInt32();
689
690 // WebKit's version of this function stuffs a MSG struct and uses
691 // TranslateMessage and DispatchMessage. We use a WebKeyboardEvent, whic h
692 // doesn't need to receive the DeadChar and SysDeadChar messages.
693 if (msg == WM_DEADCHAR || msg == WM_SYSDEADCHAR)
694 return;
695
696 if (shouldForceLayoutOnEvents())
697 webview()->layout();
698
699 unsigned long lparam = static_cast<unsigned long>(arguments[2].toDouble( ));
700 webview()->handleInputEvent(WebInputEventFactory::keyboardEvent(0, msg, arguments[1].toInt32(), lparam));
701 } else
702 BLINK_ASSERT_NOT_REACHED();
703 #endif
704 }
705
706 bool EventSender::needsShiftModifier(int keyCode)
707 {
708 // If code is an uppercase letter, assign a SHIFT key to
709 // eventDown.modifier, this logic comes from
710 // Tools/DumpRenderTree/win/EventSender.cpp
711 return (keyCode & 0xFF) >= 'A' && (keyCode & 0xFF) <= 'Z';
712 }
713
714 void EventSender::leapForward(const CppArgumentList& arguments, CppVariant* resu lt)
715 {
716 result->setNull();
717
718 if (arguments.size() < 1 || !arguments[0].isNumber())
719 return;
720
721 int milliseconds = arguments[0].toInt32();
722 if (isDragMode() && pressedButton == WebMouseEvent::ButtonLeft && !replaying SavedEvents) {
723 SavedEvent savedEvent;
724 savedEvent.type = SavedEvent::LeapForward;
725 savedEvent.milliseconds = milliseconds;
726 mouseEventQueue.push_back(savedEvent);
727 } else
728 doLeapForward(milliseconds);
729 }
730
731 void EventSender::doLeapForward(int milliseconds)
732 {
733 advanceEventTime(milliseconds);
734 }
735
736 // Apple's port of WebKit zooms by a factor of 1.2 (see
737 // WebKit/WebView/WebView.mm)
738 void EventSender::textZoomIn(const CppArgumentList&, CppVariant* result)
739 {
740 webview()->setTextZoomFactor(webview()->textZoomFactor() * 1.2f);
741 result->setNull();
742 }
743
744 void EventSender::textZoomOut(const CppArgumentList&, CppVariant* result)
745 {
746 webview()->setTextZoomFactor(webview()->textZoomFactor() / 1.2f);
747 result->setNull();
748 }
749
750 void EventSender::zoomPageIn(const CppArgumentList&, CppVariant* result)
751 {
752 const vector<WebTestProxyBase*>& windowList = m_testInterfaces->windowList() ;
753
754 for (size_t i = 0; i < windowList.size(); ++i)
755 windowList.at(i)->webView()->setZoomLevel(windowList.at(i)->webView()->z oomLevel() + 1);
756 result->setNull();
757 }
758
759 void EventSender::zoomPageOut(const CppArgumentList&, CppVariant* result)
760 {
761 const vector<WebTestProxyBase*>& windowList = m_testInterfaces->windowList() ;
762
763 for (size_t i = 0; i < windowList.size(); ++i)
764 windowList.at(i)->webView()->setZoomLevel(windowList.at(i)->webView()->z oomLevel() - 1);
765 result->setNull();
766 }
767
768 void EventSender::setPageScaleFactor(const CppArgumentList& arguments, CppVarian t* result)
769 {
770 if (arguments.size() < 3 || !arguments[0].isNumber() || !arguments[1].isNumb er() || !arguments[2].isNumber())
771 return;
772
773 float scaleFactor = static_cast<float>(arguments[0].toDouble());
774 int x = arguments[1].toInt32();
775 int y = arguments[2].toInt32();
776 webview()->setPageScaleFactorLimits(scaleFactor, scaleFactor);
777 webview()->setPageScaleFactor(scaleFactor, WebPoint(x, y));
778 result->setNull();
779 }
780
781 void EventSender::mouseScrollBy(const CppArgumentList& arguments, CppVariant* re sult)
782 {
783 WebMouseWheelEvent event;
784 initMouseWheelEvent(arguments, result, false, &event);
785 webview()->handleInputEvent(event);
786 }
787
788 void EventSender::continuousMouseScrollBy(const CppArgumentList& arguments, CppV ariant* result)
789 {
790 WebMouseWheelEvent event;
791 initMouseWheelEvent(arguments, result, true, &event);
792 webview()->handleInputEvent(event);
793 }
794
795 void EventSender::replaySavedEvents()
796 {
797 replayingSavedEvents = true;
798 while (!mouseEventQueue.empty()) {
799 SavedEvent e = mouseEventQueue.front();
800 mouseEventQueue.pop_front();
801
802 switch (e.type) {
803 case SavedEvent::MouseMove: {
804 WebMouseEvent event;
805 initMouseEvent(WebInputEvent::MouseMove, pressedButton, e.pos, &even t, getCurrentEventTimeSec(m_delegate));
806 doMouseMove(event);
807 break;
808 }
809 case SavedEvent::LeapForward:
810 doLeapForward(e.milliseconds);
811 break;
812 case SavedEvent::MouseUp: {
813 WebMouseEvent event;
814 initMouseEvent(WebInputEvent::MouseUp, e.buttonType, lastMousePos, & event, getCurrentEventTimeSec(m_delegate));
815 doMouseUp(event);
816 break;
817 }
818 default:
819 BLINK_ASSERT_NOT_REACHED();
820 }
821 }
822
823 replayingSavedEvents = false;
824 }
825
826 // Because actual context menu is implemented by the browser side,
827 // this function does only what LayoutTests are expecting:
828 // - Many test checks the count of items. So returning non-zero value makes sens e.
829 // - Some test compares the count before and after some action. So changing the count based on flags
830 // also makes sense. This function is doing such for some flags.
831 // - Some test even checks actual string content. So providing it would be also helpful.
832 //
833 static vector<WebString> makeMenuItemStringsFor(WebContextMenuData* contextMenu, WebTestDelegate* delegate)
834 {
835 // These constants are based on Safari's context menu because tests are made for it.
836 static const char* nonEditableMenuStrings[] = { "Back", "Reload Page", "Open in Dashbaord", "<separator>", "View Source", "Save Page As", "Print Page", "Ins pect Element", 0 };
837 static const char* editableMenuStrings[] = { "Cut", "Copy", "<separator>", " Paste", "Spelling and Grammar", "Substitutions, Transformations", "Font", "Speec h", "Paragraph Direction", "<separator>", 0 };
838
839 // This is possible because mouse events are cancelleable.
840 if (!contextMenu)
841 return vector<WebString>();
842
843 vector<WebString> strings;
844
845 if (contextMenu->isEditable) {
846 for (const char** item = editableMenuStrings; *item; ++item)
847 strings.push_back(WebString::fromUTF8(*item));
848 WebVector<WebString> suggestions;
849 MockSpellCheck::fillSuggestionList(contextMenu->misspelledWord, &suggest ions);
850 for (size_t i = 0; i < suggestions.size(); ++i)
851 strings.push_back(suggestions[i]);
852 } else {
853 for (const char** item = nonEditableMenuStrings; *item; ++item)
854 strings.push_back(WebString::fromUTF8(*item));
855 }
856
857 return strings;
858 }
859
860 void EventSender::contextClick(const CppArgumentList& arguments, CppVariant* res ult)
861 {
862 if (shouldForceLayoutOnEvents())
863 webview()->layout();
864
865 updateClickCountForButton(WebMouseEvent::ButtonRight);
866
867 // Clears last context menu data because we need to know if the context menu be requested
868 // after following mouse events.
869 m_lastContextMenuData.reset();
870
871 // Generate right mouse down and up.
872 WebMouseEvent event;
873 // This is a hack to work around only allowing a single pressed button since we want to
874 // test the case where both the left and right mouse buttons are pressed.
875 if (pressedButton == WebMouseEvent::ButtonNone)
876 pressedButton = WebMouseEvent::ButtonRight;
877 initMouseEvent(WebInputEvent::MouseDown, WebMouseEvent::ButtonRight, lastMou sePos, &event, getCurrentEventTimeSec(m_delegate));
878 webview()->handleInputEvent(event);
879
880 #ifdef WIN32
881 initMouseEvent(WebInputEvent::MouseUp, WebMouseEvent::ButtonRight, lastMouse Pos, &event, getCurrentEventTimeSec(m_delegate));
882 webview()->handleInputEvent(event);
883
884 pressedButton = WebMouseEvent::ButtonNone;
885 #endif
886
887 NPObject* resultArray = WebBindings::makeStringArray(makeMenuItemStringsFor( m_lastContextMenuData.get(), m_delegate));
888 result->set(resultArray);
889 WebBindings::releaseObject(resultArray);
890
891 m_lastContextMenuData.reset();
892 }
893
894 class MouseDownTask: public WebMethodTask<EventSender> {
895 public:
896 MouseDownTask(EventSender* obj, const CppArgumentList& arg)
897 : WebMethodTask<EventSender>(obj), m_arguments(arg) { }
898 virtual void runIfValid() { m_object->mouseDown(m_arguments, 0); }
899
900 private:
901 CppArgumentList m_arguments;
902 };
903
904 class MouseUpTask: public WebMethodTask<EventSender> {
905 public:
906 MouseUpTask(EventSender* obj, const CppArgumentList& arg)
907 : WebMethodTask<EventSender>(obj), m_arguments(arg) { }
908 virtual void runIfValid() { m_object->mouseUp(m_arguments, 0); }
909
910 private:
911 CppArgumentList m_arguments;
912 };
913
914 void EventSender::scheduleAsynchronousClick(const CppArgumentList& arguments, Cp pVariant* result)
915 {
916 result->setNull();
917 m_delegate->postTask(new MouseDownTask(this, arguments));
918 m_delegate->postTask(new MouseUpTask(this, arguments));
919 }
920
921 class KeyDownTask : public WebMethodTask<EventSender> {
922 public:
923 KeyDownTask(EventSender* obj, const CppArgumentList& arg)
924 : WebMethodTask<EventSender>(obj), m_arguments(arg) { }
925 virtual void runIfValid() { m_object->keyDown(m_arguments, 0); }
926
927 private:
928 CppArgumentList m_arguments;
929 };
930
931 void EventSender::scheduleAsynchronousKeyDown(const CppArgumentList& arguments, CppVariant* result)
932 {
933 result->setNull();
934 m_delegate->postTask(new KeyDownTask(this, arguments));
935 }
936
937 void EventSender::beginDragWithFiles(const CppArgumentList& arguments, CppVarian t* result)
938 {
939 currentDragData.initialize();
940 vector<string> files = arguments[0].toStringVector();
941 WebVector<WebString> absoluteFilenames(files.size());
942 for (size_t i = 0; i < files.size(); ++i) {
943 WebDragData::Item item;
944 item.storageType = WebDragData::Item::StorageTypeFilename;
945 item.filenameData = m_delegate->getAbsoluteWebStringFromUTF8Path(files[i ]);
946 currentDragData.addItem(item);
947 absoluteFilenames[i] = item.filenameData;
948 }
949 currentDragData.setFilesystemId(m_delegate->registerIsolatedFileSystem(absol uteFilenames));
950 currentDragEffectsAllowed = blink::WebDragOperationCopy;
951
952 // Provide a drag source.
953 webview()->dragTargetDragEnter(currentDragData, lastMousePos, lastMousePos, currentDragEffectsAllowed, 0);
954
955 // dragMode saves events and then replays them later. We don't need/want tha t.
956 dragMode.set(false);
957
958 // Make the rest of eventSender think a drag is in progress.
959 pressedButton = WebMouseEvent::ButtonLeft;
960
961 result->setNull();
962 }
963
964 void EventSender::addTouchPoint(const CppArgumentList& arguments, CppVariant* re sult)
965 {
966 result->setNull();
967
968 WebTouchPoint touchPoint;
969 touchPoint.state = WebTouchPoint::StatePressed;
970 touchPoint.position = WebPoint(arguments[0].toInt32(), arguments[1].toInt32( ));
971 touchPoint.screenPosition = touchPoint.position;
972
973 if (arguments.size() > 2) {
974 int radiusX = arguments[2].toInt32();
975 int radiusY = radiusX;
976 if (arguments.size() > 3)
977 radiusY = arguments[3].toInt32();
978
979 touchPoint.radiusX = radiusX;
980 touchPoint.radiusY = radiusY;
981 }
982
983 int lowestId = 0;
984 for (size_t i = 0; i < touchPoints.size(); i++) {
985 if (touchPoints[i].id == lowestId)
986 lowestId++;
987 }
988 touchPoint.id = lowestId;
989 touchPoints.push_back(touchPoint);
990 }
991
992 void EventSender::clearTouchPoints(const CppArgumentList&, CppVariant* result)
993 {
994 result->setNull();
995 touchPoints.clear();
996 }
997
998 void EventSender::releaseTouchPoint(const CppArgumentList& arguments, CppVariant * result)
999 {
1000 result->setNull();
1001
1002 const unsigned index = arguments[0].toInt32();
1003 BLINK_ASSERT(index < touchPoints.size());
1004
1005 WebTouchPoint* touchPoint = &touchPoints[index];
1006 touchPoint->state = WebTouchPoint::StateReleased;
1007 }
1008
1009 void EventSender::setTouchModifier(const CppArgumentList& arguments, CppVariant* result)
1010 {
1011 result->setNull();
1012
1013 int mask = 0;
1014 const string keyName = arguments[0].toString();
1015 if (keyName == "shift")
1016 mask = WebInputEvent::ShiftKey;
1017 else if (keyName == "alt")
1018 mask = WebInputEvent::AltKey;
1019 else if (keyName == "ctrl")
1020 mask = WebInputEvent::ControlKey;
1021 else if (keyName == "meta")
1022 mask = WebInputEvent::MetaKey;
1023
1024 if (arguments[1].toBoolean())
1025 touchModifiers |= mask;
1026 else
1027 touchModifiers &= ~mask;
1028 }
1029
1030 void EventSender::updateTouchPoint(const CppArgumentList& arguments, CppVariant* result)
1031 {
1032 result->setNull();
1033
1034 const unsigned index = arguments[0].toInt32();
1035 BLINK_ASSERT(index < touchPoints.size());
1036
1037 WebPoint position(arguments[1].toInt32(), arguments[2].toInt32());
1038 WebTouchPoint* touchPoint = &touchPoints[index];
1039 touchPoint->state = WebTouchPoint::StateMoved;
1040 touchPoint->position = position;
1041 touchPoint->screenPosition = position;
1042 }
1043
1044 void EventSender::cancelTouchPoint(const CppArgumentList& arguments, CppVariant* result)
1045 {
1046 result->setNull();
1047
1048 const unsigned index = arguments[0].toInt32();
1049 BLINK_ASSERT(index < touchPoints.size());
1050
1051 WebTouchPoint* touchPoint = &touchPoints[index];
1052 touchPoint->state = WebTouchPoint::StateCancelled;
1053 }
1054
1055 void EventSender::sendCurrentTouchEvent(const WebInputEvent::Type type)
1056 {
1057 BLINK_ASSERT(static_cast<unsigned>(WebTouchEvent::touchesLengthCap) > touchP oints.size());
1058 if (shouldForceLayoutOnEvents())
1059 webview()->layout();
1060
1061 WebTouchEvent touchEvent;
1062 touchEvent.type = type;
1063 touchEvent.modifiers = touchModifiers;
1064 touchEvent.timeStampSeconds = getCurrentEventTimeSec(m_delegate);
1065 touchEvent.touchesLength = touchPoints.size();
1066 for (unsigned i = 0; i < touchPoints.size(); ++i)
1067 touchEvent.touches[i] = touchPoints[i];
1068 webview()->handleInputEvent(touchEvent);
1069
1070 for (unsigned i = 0; i < touchPoints.size(); ++i) {
1071 WebTouchPoint* touchPoint = &touchPoints[i];
1072 if (touchPoint->state == WebTouchPoint::StateReleased) {
1073 touchPoints.erase(touchPoints.begin() + i);
1074 --i;
1075 } else
1076 touchPoint->state = WebTouchPoint::StateStationary;
1077 }
1078 }
1079
1080 void EventSender::mouseDragBegin(const CppArgumentList& arguments, CppVariant* r esult)
1081 {
1082 WebMouseWheelEvent event;
1083 initMouseEvent(WebInputEvent::MouseWheel, WebMouseEvent::ButtonNone, lastMou sePos, &event, getCurrentEventTimeSec(m_delegate));
1084 event.phase = WebMouseWheelEvent::PhaseBegan;
1085 event.hasPreciseScrollingDeltas = true;
1086 webview()->handleInputEvent(event);
1087 }
1088
1089 void EventSender::mouseDragEnd(const CppArgumentList& arguments, CppVariant* res ult)
1090 {
1091 WebMouseWheelEvent event;
1092 initMouseEvent(WebInputEvent::MouseWheel, WebMouseEvent::ButtonNone, lastMou sePos, &event, getCurrentEventTimeSec(m_delegate));
1093 event.phase = WebMouseWheelEvent::PhaseEnded;
1094 event.hasPreciseScrollingDeltas = true;
1095 webview()->handleInputEvent(event);
1096 }
1097
1098 void EventSender::mouseMomentumBegin(const CppArgumentList& arguments, CppVarian t* result)
1099 {
1100 WebMouseWheelEvent event;
1101 initMouseEvent(WebInputEvent::MouseWheel, WebMouseEvent::ButtonNone, lastMou sePos, &event, getCurrentEventTimeSec(m_delegate));
1102 event.momentumPhase = WebMouseWheelEvent::PhaseBegan;
1103 event.hasPreciseScrollingDeltas = true;
1104 webview()->handleInputEvent(event);
1105 }
1106
1107 void EventSender::mouseMomentumScrollBy(const CppArgumentList& arguments, CppVar iant* result)
1108 {
1109 WebMouseWheelEvent event;
1110 initMouseWheelEvent(arguments, result, true, &event);
1111 event.momentumPhase = WebMouseWheelEvent::PhaseChanged;
1112 event.hasPreciseScrollingDeltas = true;
1113 webview()->handleInputEvent(event);
1114 }
1115
1116 void EventSender::mouseMomentumEnd(const CppArgumentList& arguments, CppVariant* result)
1117 {
1118 WebMouseWheelEvent event;
1119 initMouseEvent(WebInputEvent::MouseWheel, WebMouseEvent::ButtonNone, lastMou sePos, &event, getCurrentEventTimeSec(m_delegate));
1120 event.momentumPhase = WebMouseWheelEvent::PhaseEnded;
1121 event.hasPreciseScrollingDeltas = true;
1122 webview()->handleInputEvent(event);
1123 }
1124
1125 void EventSender::initMouseWheelEvent(const CppArgumentList& arguments, CppVaria nt* result, bool continuous, WebMouseWheelEvent* event)
1126 {
1127 result->setNull();
1128
1129 if (arguments.size() < 2 || !arguments[0].isNumber() || !arguments[1].isNumb er())
1130 return;
1131
1132 // Force a layout here just to make sure every position has been
1133 // determined before we send events (as well as all the other methods
1134 // that send an event do).
1135 if (shouldForceLayoutOnEvents())
1136 webview()->layout();
1137
1138 int horizontal = arguments[0].toInt32();
1139 int vertical = arguments[1].toInt32();
1140 int paged = false;
1141 int hasPreciseScrollingDeltas = false;
1142
1143 if (arguments.size() > 2 && arguments[2].isBool())
1144 paged = arguments[2].toBoolean();
1145
1146 if (arguments.size() > 3 && arguments[3].isBool())
1147 hasPreciseScrollingDeltas = arguments[3].toBoolean();
1148
1149 initMouseEvent(WebInputEvent::MouseWheel, pressedButton, lastMousePos, event , getCurrentEventTimeSec(m_delegate));
1150 event->wheelTicksX = static_cast<float>(horizontal);
1151 event->wheelTicksY = static_cast<float>(vertical);
1152 event->deltaX = event->wheelTicksX;
1153 event->deltaY = event->wheelTicksY;
1154 event->scrollByPage = paged;
1155 event->hasPreciseScrollingDeltas = hasPreciseScrollingDeltas;
1156
1157 if (continuous) {
1158 event->wheelTicksX /= scrollbarPixelsPerTick;
1159 event->wheelTicksY /= scrollbarPixelsPerTick;
1160 } else {
1161 event->deltaX *= scrollbarPixelsPerTick;
1162 event->deltaY *= scrollbarPixelsPerTick;
1163 }
1164 }
1165
1166 void EventSender::touchEnd(const CppArgumentList&, CppVariant* result)
1167 {
1168 result->setNull();
1169 sendCurrentTouchEvent(WebInputEvent::TouchEnd);
1170 }
1171
1172 void EventSender::touchMove(const CppArgumentList&, CppVariant* result)
1173 {
1174 result->setNull();
1175 sendCurrentTouchEvent(WebInputEvent::TouchMove);
1176 }
1177
1178 void EventSender::touchStart(const CppArgumentList&, CppVariant* result)
1179 {
1180 result->setNull();
1181 sendCurrentTouchEvent(WebInputEvent::TouchStart);
1182 }
1183
1184 void EventSender::touchCancel(const CppArgumentList&, CppVariant* result)
1185 {
1186 result->setNull();
1187 sendCurrentTouchEvent(WebInputEvent::TouchCancel);
1188 }
1189
1190 void EventSender::gestureScrollBegin(const CppArgumentList& arguments, CppVarian t* result)
1191 {
1192 result->setNull();
1193 gestureEvent(WebInputEvent::GestureScrollBegin, arguments);
1194 }
1195
1196 void EventSender::gestureScrollEnd(const CppArgumentList& arguments, CppVariant* result)
1197 {
1198 result->setNull();
1199 gestureEvent(WebInputEvent::GestureScrollEnd, arguments);
1200 }
1201
1202 void EventSender::gestureScrollUpdate(const CppArgumentList& arguments, CppVaria nt* result)
1203 {
1204 result->setNull();
1205 gestureEvent(WebInputEvent::GestureScrollUpdate, arguments);
1206 }
1207
1208 void EventSender::gestureScrollUpdateWithoutPropagation(const CppArgumentList& a rguments, CppVariant* result)
1209 {
1210 result->setNull();
1211 gestureEvent(WebInputEvent::GestureScrollUpdateWithoutPropagation, arguments );
1212 }
1213
1214 void EventSender::gestureTap(const CppArgumentList& arguments, CppVariant* resul t)
1215 {
1216 result->setNull();
1217 gestureEvent(WebInputEvent::GestureTap, arguments);
1218 }
1219
1220 void EventSender::gestureTapDown(const CppArgumentList& arguments, CppVariant* r esult)
1221 {
1222 result->setNull();
1223 gestureEvent(WebInputEvent::GestureTapDown, arguments);
1224 }
1225
1226 void EventSender::gestureShowPress(const CppArgumentList& arguments, CppVariant* result)
1227 {
1228 result->setNull();
1229 gestureEvent(WebInputEvent::GestureShowPress, arguments);
1230 }
1231
1232 void EventSender::gestureTapCancel(const CppArgumentList& arguments, CppVariant* result)
1233 {
1234 result->setNull();
1235 gestureEvent(WebInputEvent::GestureTapCancel, arguments);
1236 }
1237
1238 void EventSender::gestureLongPress(const CppArgumentList& arguments, CppVariant* result)
1239 {
1240 result->setNull();
1241 gestureEvent(WebInputEvent::GestureLongPress, arguments);
1242 }
1243
1244 void EventSender::gestureLongTap(const CppArgumentList& arguments, CppVariant* r esult)
1245 {
1246 result->setNull();
1247 gestureEvent(WebInputEvent::GestureLongTap, arguments);
1248 }
1249
1250 void EventSender::gestureTwoFingerTap(const CppArgumentList& arguments, CppVaria nt* result)
1251 {
1252 result->setNull();
1253 gestureEvent(WebInputEvent::GestureTwoFingerTap, arguments);
1254 }
1255
1256 void EventSender::gestureScrollFirstPoint(const CppArgumentList& arguments, CppV ariant* result)
1257 {
1258 result->setNull();
1259 if (arguments.size() < 2 || !arguments[0].isNumber() || !arguments[1].isNumb er())
1260 return;
1261
1262 WebPoint point(arguments[0].toInt32(), arguments[1].toInt32());
1263 m_currentGestureLocation = point;
1264 }
1265
1266 void EventSender::gestureEvent(WebInputEvent::Type type, const CppArgumentList& arguments)
1267 {
1268 if (arguments.size() < 2 || !arguments[0].isNumber() || !arguments[1].isNumb er())
1269 return;
1270
1271 WebPoint point(arguments[0].toInt32(), arguments[1].toInt32());
1272
1273 WebGestureEvent event;
1274 event.type = type;
1275
1276 switch (type) {
1277 case WebInputEvent::GestureScrollUpdate:
1278 case WebInputEvent::GestureScrollUpdateWithoutPropagation:
1279 event.data.scrollUpdate.deltaX = static_cast<float>(arguments[0].toDoubl e());
1280 event.data.scrollUpdate.deltaY = static_cast<float>(arguments[1].toDoubl e());
1281 event.x = m_currentGestureLocation.x;
1282 event.y = m_currentGestureLocation.y;
1283 m_currentGestureLocation.x = m_currentGestureLocation.x + event.data.scr ollUpdate.deltaX;
1284 m_currentGestureLocation.y = m_currentGestureLocation.y + event.data.scr ollUpdate.deltaY;
1285 break;
1286
1287 case WebInputEvent::GestureScrollBegin:
1288 m_currentGestureLocation = WebPoint(point.x, point.y);
1289 event.x = m_currentGestureLocation.x;
1290 event.y = m_currentGestureLocation.y;
1291 break;
1292 case WebInputEvent::GestureScrollEnd:
1293 case WebInputEvent::GestureFlingStart:
1294 event.x = m_currentGestureLocation.x;
1295 event.y = m_currentGestureLocation.y;
1296 break;
1297 case WebInputEvent::GestureTap:
1298 if (arguments.size() >= 3)
1299 event.data.tap.tapCount = static_cast<float>(arguments[2].toDouble() );
1300 else
1301 event.data.tap.tapCount = 1;
1302 event.x = point.x;
1303 event.y = point.y;
1304 break;
1305 case WebInputEvent::GestureTapUnconfirmed:
1306 if (arguments.size() >= 3)
1307 event.data.tap.tapCount = static_cast<float>(arguments[2].toDouble() );
1308 else
1309 event.data.tap.tapCount = 1;
1310 event.x = point.x;
1311 event.y = point.y;
1312 break;
1313 case WebInputEvent::GestureTapDown:
1314 event.x = point.x;
1315 event.y = point.y;
1316 if (arguments.size() >= 4) {
1317 event.data.tapDown.width = static_cast<float>(arguments[2].toDouble( ));
1318 event.data.tapDown.height = static_cast<float>(arguments[3].toDouble ());
1319 }
1320 break;
1321 case WebInputEvent::GestureShowPress:
1322 event.x = point.x;
1323 event.y = point.y;
1324 if (arguments.size() >= 4) {
1325 event.data.showPress.width = static_cast<float>(arguments[2].toDoubl e());
1326 event.data.showPress.height = static_cast<float>(arguments[3].toDoub le());
1327 }
1328 break;
1329 case WebInputEvent::GestureTapCancel:
1330 event.x = point.x;
1331 event.y = point.y;
1332 break;
1333 case WebInputEvent::GestureLongPress:
1334 event.x = point.x;
1335 event.y = point.y;
1336 if (arguments.size() >= 4) {
1337 event.data.longPress.width = static_cast<float>(arguments[2].toDoubl e());
1338 event.data.longPress.height = static_cast<float>(arguments[3].toDoub le());
1339 }
1340 break;
1341 case WebInputEvent::GestureLongTap:
1342 event.x = point.x;
1343 event.y = point.y;
1344 if (arguments.size() >= 4) {
1345 event.data.longPress.width = static_cast<float>(arguments[2].toDoubl e());
1346 event.data.longPress.height = static_cast<float>(arguments[3].toDoub le());
1347 }
1348 break;
1349 case WebInputEvent::GestureTwoFingerTap:
1350 event.x = point.x;
1351 event.y = point.y;
1352 if (arguments.size() >= 4) {
1353 event.data.twoFingerTap.firstFingerWidth = static_cast<float>(argume nts[2].toDouble());
1354 event.data.twoFingerTap.firstFingerHeight = static_cast<float>(argum ents[3].toDouble());
1355 }
1356 break;
1357 default:
1358 BLINK_ASSERT_NOT_REACHED();
1359 }
1360
1361 event.globalX = event.x;
1362 event.globalY = event.y;
1363 event.timeStampSeconds = getCurrentEventTimeSec(m_delegate);
1364
1365 if (shouldForceLayoutOnEvents())
1366 webview()->layout();
1367
1368 webview()->handleInputEvent(event);
1369
1370 // Long press might start a drag drop session. Complete it if so.
1371 if (type == WebInputEvent::GestureLongPress && !currentDragData.isNull()) {
1372 WebMouseEvent mouseEvent;
1373 initMouseEvent(WebInputEvent::MouseDown, pressedButton, point, &mouseEve nt, getCurrentEventTimeSec(m_delegate));
1374 finishDragAndDrop(mouseEvent, blink::WebDragOperationNone);
1375 }
1376 }
1377
1378 void EventSender::gestureFlingCancel(const CppArgumentList&, CppVariant* result)
1379 {
1380 result->setNull();
1381
1382 WebGestureEvent event;
1383 event.type = WebInputEvent::GestureFlingCancel;
1384 event.timeStampSeconds = getCurrentEventTimeSec(m_delegate);
1385
1386 if (shouldForceLayoutOnEvents())
1387 webview()->layout();
1388
1389 webview()->handleInputEvent(event);
1390 }
1391
1392 void EventSender::gestureFlingStart(const CppArgumentList& arguments, CppVariant * result)
1393 {
1394 result->setNull();
1395 if (arguments.size() < 4)
1396 return;
1397
1398 for (int i = 0; i < 4; i++)
1399 if (!arguments[i].isNumber())
1400 return;
1401
1402 WebGestureEvent event;
1403 event.type = WebInputEvent::GestureFlingStart;
1404
1405 event.x = static_cast<float>(arguments[0].toDouble());
1406 event.y = static_cast<float>(arguments[1].toDouble());
1407 event.globalX = event.x;
1408 event.globalY = event.y;
1409
1410 event.data.flingStart.velocityX = static_cast<float>(arguments[2].toDouble() );
1411 event.data.flingStart.velocityY = static_cast<float>(arguments[3].toDouble() );
1412 event.timeStampSeconds = getCurrentEventTimeSec(m_delegate);
1413
1414 if (shouldForceLayoutOnEvents())
1415 webview()->layout();
1416
1417 webview()->handleInputEvent(event);
1418 }
1419
1420 //
1421 // Unimplemented stubs
1422 //
1423
1424 void EventSender::enableDOMUIEventLogging(const CppArgumentList&, CppVariant* re sult)
1425 {
1426 result->setNull();
1427 }
1428
1429 void EventSender::fireKeyboardEventsToElement(const CppArgumentList&, CppVariant * result)
1430 {
1431 result->setNull();
1432 }
1433
1434 void EventSender::clearKillRing(const CppArgumentList&, CppVariant* result)
1435 {
1436 result->setNull();
1437 }
1438
1439 }
OLDNEW
« no previous file with comments | « content/shell/renderer/test_runner/EventSender.h ('k') | content/shell/renderer/test_runner/GamepadController.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698