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.
5 // This file contains the definition for EventSender.
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.
17 #include "content/shell/renderer/test_runner/EventSender.h"
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"
35 #include "third_party/WebKit/public/web/win/WebInputEventFactory.h"
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"
44 // FIXME: layout before each event?
47 using namespace blink;
49 namespace WebTestRunner {
51 WebPoint EventSender::lastMousePos;
52 WebMouseEvent::Button EventSender::pressedButton = WebMouseEvent::ButtonNone;
53 WebMouseEvent::Button EventSender::lastButtonType = WebMouseEvent::ButtonNone;
66 WebMouseEvent::Button buttonType; // For MouseUp.
67 WebPoint pos; // For MouseMove.
68 int milliseconds; // For LeapForward.
72 , buttonType(WebMouseEvent::ButtonNone)
76 WebDragData currentDragData;
77 WebDragOperation currentDragEffect;
78 WebDragOperationsMask currentDragEffectsAllowed;
79 bool replayingSavedEvents = false;
80 deque<SavedEvent> mouseEventQueue;
82 vector<WebTouchPoint> touchPoints;
84 // Time and place of the last mouse up event.
85 double lastClickTimeSec = 0;
86 WebPoint lastClickPos;
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;
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;
98 inline bool outsideMultiClickRadius(const WebPoint& a, const WebPoint& b)
100 return ((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)) >
101 multipleClickRadiusPixels * multipleClickRadiusPixels;
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;
109 double getCurrentEventTimeSec(WebTestDelegate* delegate)
111 return (delegate->getCurrentTimeInMillisecond() + timeOffsetMs) / 1000.0;
114 void advanceEventTime(int32_t deltaMs)
116 timeOffsetMs += deltaMs;
119 void initMouseEvent(WebInputEvent::Type t, WebMouseEvent::Button b, const WebPoint& pos, WebMouseEvent* e, double ts)
128 e->timeStampSeconds = ts;
129 e->clickCount = clickCount;
132 void applyKeyModifier(const string& modifierName, WebInputEvent* event)
134 const char* characters = modifierName.c_str();
135 if (!strcmp(characters, "ctrlKey")
137 || !strcmp(characters, "addSelectionKey")
140 event->modifiers |= WebInputEvent::ControlKey;
141 } else if (!strcmp(characters, "shiftKey") || !strcmp(characters, "rangeSelectionKey"))
142 event->modifiers |= WebInputEvent::ShiftKey;
143 else if (!strcmp(characters, "altKey")) {
144 event->modifiers |= WebInputEvent::AltKey;
146 } else if (!strcmp(characters, "metaKey") || !strcmp(characters, "addSelectionKey")) {
147 event->modifiers |= WebInputEvent::MetaKey;
149 } else if (!strcmp(characters, "metaKey")) {
150 event->modifiers |= WebInputEvent::MetaKey;
152 } else if (!strcmp(characters, "autoRepeat")) {
153 event->modifiers |= WebInputEvent::IsAutoRepeat;
157 void applyKeyModifiers(const CppVariant* argument, WebInputEvent* event)
159 if (argument->isObject()) {
160 vector<string> modifiers = argument->toStringVector();
161 for (vector<string>::const_iterator i = modifiers.begin(); i != modifiers.end(); ++i)
162 applyKeyModifier(*i, event);
163 } else if (argument->isString()) {
164 applyKeyModifier(argument->toString(), event);
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)
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::MetaKey)
183 switch (event.windowsKeyCode) {
185 *name = "MoveToBeginningOfLine";
188 *name = "MoveToEndOfLine";
191 *name = "MoveToBeginningOfDocument";
194 *name = "MoveToEndOfDocument";
200 if (event.modifiers & WebKeyboardEvent::ShiftKey)
201 name->append("AndModifySelection");
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
220 EventSender::EventSender(TestInterfaces* interfaces)
221 : m_testInterfaces(interfaces)
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() (defined
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::dumpFilenameBeingDragged);
237 bindMethod("enableDOMUIEventLogging", &EventSender::enableDOMUIEventLogging);
238 bindMethod("fireKeyboardEventsToElement", &EventSender::fireKeyboardEventsToElement);
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::scheduleAsynchronousClick);
252 bindMethod("scheduleAsynchronousKeyDown", &EventSender::scheduleAsynchronousKeyDown);
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::gestureScrollUpdateWithoutPropagation);
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);
279 bindProperty("forceLayoutOnEvents", &forceLayoutOnEvents);
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);
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);
296 EventSender::~EventSender()
300 void EventSender::setContextMenuData(const WebContextMenuData& contextMenuData)
302 m_lastContextMenuData = scoped_ptr<WebContextMenuData>(new WebContextMenuData(contextMenuData));
305 void EventSender::reset()
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;
316 forceLayoutOnEvents.set(true);
318 wmKeyDown.set(WM_KEYDOWN);
319 wmKeyUp.set(WM_KEYUP);
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);
327 lastMousePos = WebPoint(0, 0);
328 lastClickTimeSec = 0;
329 lastClickPos = WebPoint(0, 0);
331 lastButtonType = WebMouseEvent::ButtonNone;
335 m_taskList.revokeAll();
336 m_currentGestureLocation = WebPoint(0, 0);
337 mouseEventQueue.clear();
340 void EventSender::doDragDrop(const WebDragData& dragData, WebDragOperationsMask mask)
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, screenPoint, currentDragEffectsAllowed, 0);
350 // Finish processing events.
354 void EventSender::dumpFilenameBeingDragged(const CppArgumentList&, CppVariant*)
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;
364 m_delegate->printMessage(std::string("Filename being dragged: ") + filename.utf8().data() + "\n");
367 WebMouseEvent::Button EventSender::getButtonTypeFromButtonNumber(int buttonCode)
370 return WebMouseEvent::ButtonLeft;
372 return WebMouseEvent::ButtonRight;
373 return WebMouseEvent::ButtonMiddle;
376 int EventSender::getButtonNumberFromSingleArg(const CppArgumentList& arguments)
379 if (arguments.size() > 0 && arguments[0].isNumber())
380 buttonCode = arguments[0].toInt32();
384 void EventSender::updateClickCountForButton(WebMouseEvent::Button buttonType)
386 if ((getCurrentEventTimeSec(m_delegate) - lastClickTimeSec < multipleClickTimeSec)
387 && (!outsideMultiClickRadius(lastMousePos, lastClickPos))
388 && (buttonType == lastButtonType))
392 lastButtonType = buttonType;
397 // Implemented javascript methods.
400 void EventSender::mouseDown(const CppArgumentList& arguments, CppVariant* result)
402 if (result) // Could be 0 if invoked asynchronously.
405 if (shouldForceLayoutOnEvents())
408 int buttonNumber = getButtonNumberFromSingleArg(arguments);
409 BLINK_ASSERT(buttonNumber != -1);
411 WebMouseEvent::Button buttonType = getButtonTypeFromButtonNumber(buttonNumber);
413 updateClickCountForButton(buttonType);
416 pressedButton = buttonType;
417 initMouseEvent(WebInputEvent::MouseDown, buttonType, lastMousePos, &event, getCurrentEventTimeSec(m_delegate));
418 if (arguments.size() >= 2 && (arguments[1].isObject() || arguments[1].isString()))
419 applyKeyModifiers(&(arguments[1]), &event);
420 webview()->handleInputEvent(event);
423 void EventSender::mouseUp(const CppArgumentList& arguments, CppVariant* result)
425 if (result) // Could be 0 if invoked asynchronously.
428 if (shouldForceLayoutOnEvents())
431 int buttonNumber = getButtonNumberFromSingleArg(arguments);
432 BLINK_ASSERT(buttonNumber != -1);
434 WebMouseEvent::Button buttonType = getButtonTypeFromButtonNumber(buttonNumber);
436 if (isDragMode() && !replayingSavedEvents) {
437 SavedEvent savedEvent;
438 savedEvent.type = SavedEvent::MouseUp;
439 savedEvent.buttonType = buttonType;
440 mouseEventQueue.push_back(savedEvent);
444 initMouseEvent(WebInputEvent::MouseUp, buttonType, lastMousePos, &event, getCurrentEventTimeSec(m_delegate));
445 if (arguments.size() >= 2 && (arguments[1].isObject() || arguments[1].isString()))
446 applyKeyModifiers(&(arguments[1]), &event);
451 void EventSender::doMouseUp(const WebMouseEvent& e)
453 webview()->handleInputEvent(e);
455 pressedButton = WebMouseEvent::ButtonNone;
456 lastClickTimeSec = e.timeStampSeconds;
457 lastClickPos = lastMousePos;
459 // If we're in a drag operation, complete it.
460 if (currentDragData.isNull())
463 WebPoint clientPoint(e.x, e.y);
464 WebPoint screenPoint(e.globalX, e.globalY);
465 finishDragAndDrop(e, webview()->dragTargetDragOver(clientPoint, screenPoint, currentDragEffectsAllowed, 0));
468 void EventSender::finishDragAndDrop(const WebMouseEvent& e, blink::WebDragOperation dragEffect)
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);
476 webview()->dragTargetDragLeave();
477 webview()->dragSourceEndedAt(clientPoint, screenPoint, currentDragEffect);
478 webview()->dragSourceSystemDragEnded();
480 currentDragData.reset();
483 void EventSender::mouseMoveTo(const CppArgumentList& arguments, CppVariant* result)
487 if (arguments.size() < 2 || !arguments[0].isNumber() || !arguments[1].isNumber())
489 if (shouldForceLayoutOnEvents())
492 WebPoint mousePos(arguments[0].toInt32(), arguments[1].toInt32());
494 if (isDragMode() && pressedButton == WebMouseEvent::ButtonLeft && !replayingSavedEvents) {
495 SavedEvent savedEvent;
496 savedEvent.type = SavedEvent::MouseMove;
497 savedEvent.pos = mousePos;
498 mouseEventQueue.push_back(savedEvent);
501 initMouseEvent(WebInputEvent::MouseMove, pressedButton, mousePos, &event, getCurrentEventTimeSec(m_delegate));
502 if (arguments.size() >= 3 && (arguments[2].isObject() || arguments[2].isString()))
503 applyKeyModifiers(&(arguments[2]), &event);
508 void EventSender::doMouseMove(const WebMouseEvent& e)
510 lastMousePos = WebPoint(e.x, e.y);
512 webview()->handleInputEvent(e);
514 if (pressedButton == WebMouseEvent::ButtonNone || currentDragData.isNull())
516 WebPoint clientPoint(e.x, e.y);
517 WebPoint screenPoint(e.globalX, e.globalY);
518 currentDragEffect = webview()->dragTargetDragOver(clientPoint, screenPoint, currentDragEffectsAllowed, 0);
521 void EventSender::keyDown(const CppArgumentList& arguments, CppVariant* result)
525 if (arguments.size() < 1 || !arguments[0].isString())
527 bool generateChar = false;
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();
534 // Convert \n -> VK_RETURN. Some layout tests use \n to mean "Enter", when
535 // Windows uses \r for "Enter".
538 bool needsShiftKeyModifier = false;
539 if ("\n" == codeStr) {
541 text = code = VKEY_RETURN;
542 } else if ("rightArrow" == codeStr)
544 else if ("downArrow" == codeStr)
546 else if ("leftArrow" == codeStr)
548 else if ("upArrow" == codeStr)
550 else if ("insert" == codeStr)
552 else if ("delete" == codeStr)
554 else if ("pageUp" == codeStr)
556 else if ("pageDown" == codeStr)
558 else if ("home" == codeStr)
560 else if ("end" == codeStr)
562 else if ("printScreen" == codeStr)
563 code = VKEY_SNAPSHOT;
564 else if ("menu" == codeStr)
566 else if ("leftControl" == codeStr)
567 code = VKEY_LCONTROL;
568 else if ("rightControl" == codeStr)
569 code = VKEY_RCONTROL;
570 else if ("leftShift" == codeStr)
572 else if ("rightShift" == codeStr)
574 else if ("leftAlt" == codeStr)
576 else if ("rightAlt" == codeStr)
578 else if ("numLock" == codeStr)
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);
594 WebString webCodeStr = WebString::fromUTF8(codeStr.data(), codeStr.size());
595 BLINK_ASSERT(webCodeStr.length() == 1);
596 text = code = webCodeStr.at(0);
597 needsShiftKeyModifier = needsShiftModifier(code);
598 if ((code & 0xFF) >= 'a' && (code & 0xFF) <= 'z')
603 if ("(" == codeStr) {
605 needsShiftKeyModifier = true;
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);
623 eventDown.text[0] = text;
624 eventDown.unmodifiedText[0] = text;
626 eventDown.setKeyIdentifierFromWindowsKeyCode();
628 if (arguments.size() >= 2 && (arguments[1].isObject() || arguments[1].isString())) {
629 applyKeyModifiers(&(arguments[1]), &eventDown);
630 #if WIN32 || __APPLE__ || defined(ANDROID) || defined(TOOLKIT_GTK)
631 eventDown.isSystemKey = WebInputEventFactory::isSystemKeyEvent(eventDown);
635 if (needsShiftKeyModifier)
636 eventDown.modifiers |= WebInputEvent::ShiftKey;
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;
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())
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.
659 if (getEditCommand(eventDown, &editCommand))
660 m_delegate->setEditCommand(editCommand, "");
662 webview()->handleInputEvent(eventDown);
664 if (code == VKEY_ESCAPE && !currentDragData.isNull()) {
666 initMouseEvent(WebInputEvent::MouseDown, pressedButton, lastMousePos, &event, getCurrentEventTimeSec(m_delegate));
667 finishDragAndDrop(event, blink::WebDragOperationNone);
670 m_delegate->clearEditCommand();
673 eventChar.type = WebInputEvent::Char;
674 eventChar.keyIdentifier[0] = '\0';
675 webview()->handleInputEvent(eventChar);
678 webview()->handleInputEvent(eventUp);
681 void EventSender::dispatchMessage(const CppArgumentList& arguments, CppVariant* result)
686 if (arguments.size() == 3) {
687 // Grab the message id to see if we need to dispatch it.
688 int msg = arguments[0].toInt32();
690 // WebKit's version of this function stuffs a MSG struct and uses
691 // TranslateMessage and DispatchMessage. We use a WebKeyboardEvent, which
692 // doesn't need to receive the DeadChar and SysDeadChar messages.
693 if (msg == WM_DEADCHAR || msg == WM_SYSDEADCHAR)
696 if (shouldForceLayoutOnEvents())
699 unsigned long lparam = static_cast<unsigned long>(arguments[2].toDouble());
700 webview()->handleInputEvent(WebInputEventFactory::keyboardEvent(0, msg, arguments[1].toInt32(), lparam));
702 BLINK_ASSERT_NOT_REACHED();
706 bool EventSender::needsShiftModifier(int keyCode)
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';
714 void EventSender::leapForward(const CppArgumentList& arguments, CppVariant* result)
718 if (arguments.size() < 1 || !arguments[0].isNumber())
721 int milliseconds = arguments[0].toInt32();
722 if (isDragMode() && pressedButton == WebMouseEvent::ButtonLeft && !replayingSavedEvents) {
723 SavedEvent savedEvent;
724 savedEvent.type = SavedEvent::LeapForward;
725 savedEvent.milliseconds = milliseconds;
726 mouseEventQueue.push_back(savedEvent);
728 doLeapForward(milliseconds);
731 void EventSender::doLeapForward(int milliseconds)
733 advanceEventTime(milliseconds);
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)
740 webview()->setTextZoomFactor(webview()->textZoomFactor() * 1.2f);
744 void EventSender::textZoomOut(const CppArgumentList&, CppVariant* result)
746 webview()->setTextZoomFactor(webview()->textZoomFactor() / 1.2f);
750 void EventSender::zoomPageIn(const CppArgumentList&, CppVariant* result)
752 const vector<WebTestProxyBase*>& windowList = m_testInterfaces->windowList();
754 for (size_t i = 0; i < windowList.size(); ++i)
755 windowList.at(i)->webView()->setZoomLevel(windowList.at(i)->webView()->zoomLevel() + 1);
759 void EventSender::zoomPageOut(const CppArgumentList&, CppVariant* result)
761 const vector<WebTestProxyBase*>& windowList = m_testInterfaces->windowList();
763 for (size_t i = 0; i < windowList.size(); ++i)
764 windowList.at(i)->webView()->setZoomLevel(windowList.at(i)->webView()->zoomLevel() - 1);
768 void EventSender::setPageScaleFactor(const CppArgumentList& arguments, CppVariant* result)
770 if (arguments.size() < 3 || !arguments[0].isNumber() || !arguments[1].isNumber() || !arguments[2].isNumber())
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));
781 void EventSender::mouseScrollBy(const CppArgumentList& arguments, CppVariant* result)
783 WebMouseWheelEvent event;
784 initMouseWheelEvent(arguments, result, false, &event);
785 webview()->handleInputEvent(event);
788 void EventSender::continuousMouseScrollBy(const CppArgumentList& arguments, CppVariant* result)
790 WebMouseWheelEvent event;
791 initMouseWheelEvent(arguments, result, true, &event);
792 webview()->handleInputEvent(event);
795 void EventSender::replaySavedEvents()
797 replayingSavedEvents = true;
798 while (!mouseEventQueue.empty()) {
799 SavedEvent e = mouseEventQueue.front();
800 mouseEventQueue.pop_front();
803 case SavedEvent::MouseMove: {
805 initMouseEvent(WebInputEvent::MouseMove, pressedButton, e.pos, &event, getCurrentEventTimeSec(m_delegate));
809 case SavedEvent::LeapForward:
810 doLeapForward(e.milliseconds);
812 case SavedEvent::MouseUp: {
814 initMouseEvent(WebInputEvent::MouseUp, e.buttonType, lastMousePos, &event, getCurrentEventTimeSec(m_delegate));
819 BLINK_ASSERT_NOT_REACHED();
823 replayingSavedEvents = false;
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 sense.
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.
833 static vector<WebString> makeMenuItemStringsFor(WebContextMenuData* contextMenu, WebTestDelegate* delegate)
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", "Inspect Element", 0 };
837 static const char* editableMenuStrings[] = { "Cut", "Copy", "<separator>", "Paste", "Spelling and Grammar", "Substitutions, Transformations", "Font", "Speech", "Paragraph Direction", "<separator>", 0 };
839 // This is possible because mouse events are cancelleable.
841 return vector<WebString>();
843 vector<WebString> strings;
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, &suggestions);
850 for (size_t i = 0; i < suggestions.size(); ++i)
851 strings.push_back(suggestions[i]);
853 for (const char** item = nonEditableMenuStrings; *item; ++item)
854 strings.push_back(WebString::fromUTF8(*item));
860 void EventSender::contextClick(const CppArgumentList& arguments, CppVariant* result)
862 if (shouldForceLayoutOnEvents())
865 updateClickCountForButton(WebMouseEvent::ButtonRight);
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();
871 // Generate right mouse down and up.
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, lastMousePos, &event, getCurrentEventTimeSec(m_delegate));
878 webview()->handleInputEvent(event);
881 initMouseEvent(WebInputEvent::MouseUp, WebMouseEvent::ButtonRight, lastMousePos, &event, getCurrentEventTimeSec(m_delegate));
882 webview()->handleInputEvent(event);
884 pressedButton = WebMouseEvent::ButtonNone;
887 NPObject* resultArray = WebBindings::makeStringArray(makeMenuItemStringsFor(m_lastContextMenuData.get(), m_delegate));
888 result->set(resultArray);
889 WebBindings::releaseObject(resultArray);
891 m_lastContextMenuData.reset();
894 class MouseDownTask: public WebMethodTask<EventSender> {
896 MouseDownTask(EventSender* obj, const CppArgumentList& arg)
897 : WebMethodTask<EventSender>(obj), m_arguments(arg) { }
898 virtual void runIfValid() OVERRIDE { m_object->mouseDown(m_arguments, 0); }
901 CppArgumentList m_arguments;
904 class MouseUpTask: public WebMethodTask<EventSender> {
906 MouseUpTask(EventSender* obj, const CppArgumentList& arg)
907 : WebMethodTask<EventSender>(obj), m_arguments(arg) { }
908 virtual void runIfValid() OVERRIDE { m_object->mouseUp(m_arguments, 0); }
911 CppArgumentList m_arguments;
914 void EventSender::scheduleAsynchronousClick(const CppArgumentList& arguments, CppVariant* result)
917 m_delegate->postTask(new MouseDownTask(this, arguments));
918 m_delegate->postTask(new MouseUpTask(this, arguments));
921 class KeyDownTask : public WebMethodTask<EventSender> {
923 KeyDownTask(EventSender* obj, const CppArgumentList& arg)
924 : WebMethodTask<EventSender>(obj), m_arguments(arg) { }
925 virtual void runIfValid() OVERRIDE { m_object->keyDown(m_arguments, 0); }
928 CppArgumentList m_arguments;
931 void EventSender::scheduleAsynchronousKeyDown(const CppArgumentList& arguments, CppVariant* result)
934 m_delegate->postTask(new KeyDownTask(this, arguments));
937 void EventSender::beginDragWithFiles(const CppArgumentList& arguments, CppVariant* result)
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;
949 currentDragData.setFilesystemId(m_delegate->registerIsolatedFileSystem(absoluteFilenames));
950 currentDragEffectsAllowed = blink::WebDragOperationCopy;
952 // Provide a drag source.
953 webview()->dragTargetDragEnter(currentDragData, lastMousePos, lastMousePos, currentDragEffectsAllowed, 0);
955 // dragMode saves events and then replays them later. We don't need/want that.
958 // Make the rest of eventSender think a drag is in progress.
959 pressedButton = WebMouseEvent::ButtonLeft;
964 void EventSender::addTouchPoint(const CppArgumentList& arguments, CppVariant* result)
968 WebTouchPoint touchPoint;
969 touchPoint.state = WebTouchPoint::StatePressed;
970 touchPoint.position.x = arguments[0].toInt32();
971 touchPoint.position.y = arguments[1].toInt32();
972 touchPoint.screenPosition = touchPoint.position;
974 if (arguments.size() > 2) {
975 int radiusX = arguments[2].toInt32();
976 int radiusY = radiusX;
977 if (arguments.size() > 3)
978 radiusY = arguments[3].toInt32();
980 touchPoint.radiusX = radiusX;
981 touchPoint.radiusY = radiusY;
985 for (size_t i = 0; i < touchPoints.size(); i++) {
986 if (touchPoints[i].id == lowestId)
989 touchPoint.id = lowestId;
990 touchPoints.push_back(touchPoint);
993 void EventSender::clearTouchPoints(const CppArgumentList&, CppVariant* result)
999 void EventSender::releaseTouchPoint(const CppArgumentList& arguments, CppVariant* result)
1003 const unsigned index = arguments[0].toInt32();
1004 BLINK_ASSERT(index < touchPoints.size());
1006 WebTouchPoint* touchPoint = &touchPoints[index];
1007 touchPoint->state = WebTouchPoint::StateReleased;
1010 void EventSender::setTouchModifier(const CppArgumentList& arguments, CppVariant* result)
1015 const string keyName = arguments[0].toString();
1016 if (keyName == "shift")
1017 mask = WebInputEvent::ShiftKey;
1018 else if (keyName == "alt")
1019 mask = WebInputEvent::AltKey;
1020 else if (keyName == "ctrl")
1021 mask = WebInputEvent::ControlKey;
1022 else if (keyName == "meta")
1023 mask = WebInputEvent::MetaKey;
1025 if (arguments[1].toBoolean())
1026 touchModifiers |= mask;
1028 touchModifiers &= ~mask;
1031 void EventSender::updateTouchPoint(const CppArgumentList& arguments, CppVariant* result)
1035 const unsigned index = arguments[0].toInt32();
1036 BLINK_ASSERT(index < touchPoints.size());
1038 WebTouchPoint* touchPoint = &touchPoints[index];
1039 touchPoint->state = WebTouchPoint::StateMoved;
1040 touchPoint->position.x = arguments[1].toInt32();
1041 touchPoint->position.y = arguments[2].toInt32();
1042 touchPoint->screenPosition = touchPoint->position;
1045 void EventSender::cancelTouchPoint(const CppArgumentList& arguments, CppVariant* result)
1049 const unsigned index = arguments[0].toInt32();
1050 BLINK_ASSERT(index < touchPoints.size());
1052 WebTouchPoint* touchPoint = &touchPoints[index];
1053 touchPoint->state = WebTouchPoint::StateCancelled;
1056 void EventSender::sendCurrentTouchEvent(const WebInputEvent::Type type)
1058 BLINK_ASSERT(static_cast<unsigned>(WebTouchEvent::touchesLengthCap) > touchPoints.size());
1059 if (shouldForceLayoutOnEvents())
1060 webview()->layout();
1062 WebTouchEvent touchEvent;
1063 touchEvent.type = type;
1064 touchEvent.modifiers = touchModifiers;
1065 touchEvent.timeStampSeconds = getCurrentEventTimeSec(m_delegate);
1066 touchEvent.touchesLength = touchPoints.size();
1067 for (unsigned i = 0; i < touchPoints.size(); ++i)
1068 touchEvent.touches[i] = touchPoints[i];
1069 webview()->handleInputEvent(touchEvent);
1071 for (unsigned i = 0; i < touchPoints.size(); ++i) {
1072 WebTouchPoint* touchPoint = &touchPoints[i];
1073 if (touchPoint->state == WebTouchPoint::StateReleased) {
1074 touchPoints.erase(touchPoints.begin() + i);
1077 touchPoint->state = WebTouchPoint::StateStationary;
1081 void EventSender::mouseDragBegin(const CppArgumentList& arguments, CppVariant* result)
1083 WebMouseWheelEvent event;
1084 initMouseEvent(WebInputEvent::MouseWheel, WebMouseEvent::ButtonNone, lastMousePos, &event, getCurrentEventTimeSec(m_delegate));
1085 event.phase = WebMouseWheelEvent::PhaseBegan;
1086 event.hasPreciseScrollingDeltas = true;
1087 webview()->handleInputEvent(event);
1090 void EventSender::mouseDragEnd(const CppArgumentList& arguments, CppVariant* result)
1092 WebMouseWheelEvent event;
1093 initMouseEvent(WebInputEvent::MouseWheel, WebMouseEvent::ButtonNone, lastMousePos, &event, getCurrentEventTimeSec(m_delegate));
1094 event.phase = WebMouseWheelEvent::PhaseEnded;
1095 event.hasPreciseScrollingDeltas = true;
1096 webview()->handleInputEvent(event);
1099 void EventSender::mouseMomentumBegin(const CppArgumentList& arguments, CppVariant* result)
1101 WebMouseWheelEvent event;
1102 initMouseEvent(WebInputEvent::MouseWheel, WebMouseEvent::ButtonNone, lastMousePos, &event, getCurrentEventTimeSec(m_delegate));
1103 event.momentumPhase = WebMouseWheelEvent::PhaseBegan;
1104 event.hasPreciseScrollingDeltas = true;
1105 webview()->handleInputEvent(event);
1108 void EventSender::mouseMomentumScrollBy(const CppArgumentList& arguments, CppVariant* result)
1110 WebMouseWheelEvent event;
1111 initMouseWheelEvent(arguments, result, true, &event);
1112 event.momentumPhase = WebMouseWheelEvent::PhaseChanged;
1113 event.hasPreciseScrollingDeltas = true;
1114 webview()->handleInputEvent(event);
1117 void EventSender::mouseMomentumEnd(const CppArgumentList& arguments, CppVariant* result)
1119 WebMouseWheelEvent event;
1120 initMouseEvent(WebInputEvent::MouseWheel, WebMouseEvent::ButtonNone, lastMousePos, &event, getCurrentEventTimeSec(m_delegate));
1121 event.momentumPhase = WebMouseWheelEvent::PhaseEnded;
1122 event.hasPreciseScrollingDeltas = true;
1123 webview()->handleInputEvent(event);
1126 void EventSender::initMouseWheelEvent(const CppArgumentList& arguments, CppVariant* result, bool continuous, WebMouseWheelEvent* event)
1130 if (arguments.size() < 2 || !arguments[0].isNumber() || !arguments[1].isNumber())
1133 // Force a layout here just to make sure every position has been
1134 // determined before we send events (as well as all the other methods
1135 // that send an event do).
1136 if (shouldForceLayoutOnEvents())
1137 webview()->layout();
1139 int horizontal = arguments[0].toInt32();
1140 int vertical = arguments[1].toInt32();
1142 int hasPreciseScrollingDeltas = false;
1144 if (arguments.size() > 2 && arguments[2].isBool())
1145 paged = arguments[2].toBoolean();
1147 if (arguments.size() > 3 && arguments[3].isBool())
1148 hasPreciseScrollingDeltas = arguments[3].toBoolean();
1150 initMouseEvent(WebInputEvent::MouseWheel, pressedButton, lastMousePos, event, getCurrentEventTimeSec(m_delegate));
1151 event->wheelTicksX = static_cast<float>(horizontal);
1152 event->wheelTicksY = static_cast<float>(vertical);
1153 event->deltaX = event->wheelTicksX;
1154 event->deltaY = event->wheelTicksY;
1155 event->scrollByPage = paged;
1156 event->hasPreciseScrollingDeltas = hasPreciseScrollingDeltas;
1159 event->wheelTicksX /= scrollbarPixelsPerTick;
1160 event->wheelTicksY /= scrollbarPixelsPerTick;
1162 event->deltaX *= scrollbarPixelsPerTick;
1163 event->deltaY *= scrollbarPixelsPerTick;
1167 void EventSender::touchEnd(const CppArgumentList&, CppVariant* result)
1170 sendCurrentTouchEvent(WebInputEvent::TouchEnd);
1173 void EventSender::touchMove(const CppArgumentList&, CppVariant* result)
1176 sendCurrentTouchEvent(WebInputEvent::TouchMove);
1179 void EventSender::touchStart(const CppArgumentList&, CppVariant* result)
1182 sendCurrentTouchEvent(WebInputEvent::TouchStart);
1185 void EventSender::touchCancel(const CppArgumentList&, CppVariant* result)
1188 sendCurrentTouchEvent(WebInputEvent::TouchCancel);
1191 void EventSender::gestureScrollBegin(const CppArgumentList& arguments, CppVariant* result)
1194 gestureEvent(WebInputEvent::GestureScrollBegin, arguments);
1197 void EventSender::gestureScrollEnd(const CppArgumentList& arguments, CppVariant* result)
1200 gestureEvent(WebInputEvent::GestureScrollEnd, arguments);
1203 void EventSender::gestureScrollUpdate(const CppArgumentList& arguments, CppVariant* result)
1206 gestureEvent(WebInputEvent::GestureScrollUpdate, arguments);
1209 void EventSender::gestureScrollUpdateWithoutPropagation(const CppArgumentList& arguments, CppVariant* result)
1212 gestureEvent(WebInputEvent::GestureScrollUpdateWithoutPropagation, arguments);
1215 void EventSender::gestureTap(const CppArgumentList& arguments, CppVariant* result)
1218 gestureEvent(WebInputEvent::GestureTap, arguments);
1221 void EventSender::gestureTapDown(const CppArgumentList& arguments, CppVariant* result)
1224 gestureEvent(WebInputEvent::GestureTapDown, arguments);
1227 void EventSender::gestureShowPress(const CppArgumentList& arguments, CppVariant* result)
1230 gestureEvent(WebInputEvent::GestureShowPress, arguments);
1233 void EventSender::gestureTapCancel(const CppArgumentList& arguments, CppVariant* result)
1236 gestureEvent(WebInputEvent::GestureTapCancel, arguments);
1239 void EventSender::gestureLongPress(const CppArgumentList& arguments, CppVariant* result)
1242 gestureEvent(WebInputEvent::GestureLongPress, arguments);
1245 void EventSender::gestureLongTap(const CppArgumentList& arguments, CppVariant* result)
1248 gestureEvent(WebInputEvent::GestureLongTap, arguments);
1251 void EventSender::gestureTwoFingerTap(const CppArgumentList& arguments, CppVariant* result)
1254 gestureEvent(WebInputEvent::GestureTwoFingerTap, arguments);
1257 void EventSender::gestureScrollFirstPoint(const CppArgumentList& arguments, CppVariant* result)
1260 if (arguments.size() < 2 || !arguments[0].isNumber() || !arguments[1].isNumber())
1263 WebPoint point(arguments[0].toInt32(), arguments[1].toInt32());
1264 m_currentGestureLocation = point;
1267 void EventSender::gestureEvent(WebInputEvent::Type type, const CppArgumentList& arguments)
1269 if (arguments.size() < 2 || !arguments[0].isNumber() || !arguments[1].isNumber())
1272 WebPoint point(arguments[0].toInt32(), arguments[1].toInt32());
1274 WebGestureEvent event;
1278 case WebInputEvent::GestureScrollUpdate:
1279 case WebInputEvent::GestureScrollUpdateWithoutPropagation:
1280 event.data.scrollUpdate.deltaX = static_cast<float>(arguments[0].toDouble());
1281 event.data.scrollUpdate.deltaY = static_cast<float>(arguments[1].toDouble());
1282 event.x = m_currentGestureLocation.x;
1283 event.y = m_currentGestureLocation.y;
1284 m_currentGestureLocation.x = m_currentGestureLocation.x + event.data.scrollUpdate.deltaX;
1285 m_currentGestureLocation.y = m_currentGestureLocation.y + event.data.scrollUpdate.deltaY;
1288 case WebInputEvent::GestureScrollBegin:
1289 m_currentGestureLocation = WebPoint(point.x, point.y);
1290 event.x = m_currentGestureLocation.x;
1291 event.y = m_currentGestureLocation.y;
1293 case WebInputEvent::GestureScrollEnd:
1294 case WebInputEvent::GestureFlingStart:
1295 event.x = m_currentGestureLocation.x;
1296 event.y = m_currentGestureLocation.y;
1298 case WebInputEvent::GestureTap:
1299 if (arguments.size() >= 3)
1300 event.data.tap.tapCount = static_cast<float>(arguments[2].toDouble());
1302 event.data.tap.tapCount = 1;
1306 case WebInputEvent::GestureTapUnconfirmed:
1307 if (arguments.size() >= 3)
1308 event.data.tap.tapCount = static_cast<float>(arguments[2].toDouble());
1310 event.data.tap.tapCount = 1;
1314 case WebInputEvent::GestureTapDown:
1317 if (arguments.size() >= 4) {
1318 event.data.tapDown.width = static_cast<float>(arguments[2].toDouble());
1319 event.data.tapDown.height = static_cast<float>(arguments[3].toDouble());
1322 case WebInputEvent::GestureShowPress:
1325 if (arguments.size() >= 4) {
1326 event.data.showPress.width = static_cast<float>(arguments[2].toDouble());
1327 event.data.showPress.height = static_cast<float>(arguments[3].toDouble());
1330 case WebInputEvent::GestureTapCancel:
1334 case WebInputEvent::GestureLongPress:
1337 if (arguments.size() >= 4) {
1338 event.data.longPress.width = static_cast<float>(arguments[2].toDouble());
1339 event.data.longPress.height = static_cast<float>(arguments[3].toDouble());
1342 case WebInputEvent::GestureLongTap:
1345 if (arguments.size() >= 4) {
1346 event.data.longPress.width = static_cast<float>(arguments[2].toDouble());
1347 event.data.longPress.height = static_cast<float>(arguments[3].toDouble());
1350 case WebInputEvent::GestureTwoFingerTap:
1353 if (arguments.size() >= 4) {
1354 event.data.twoFingerTap.firstFingerWidth = static_cast<float>(arguments[2].toDouble());
1355 event.data.twoFingerTap.firstFingerHeight = static_cast<float>(arguments[3].toDouble());
1359 BLINK_ASSERT_NOT_REACHED();
1362 event.globalX = event.x;
1363 event.globalY = event.y;
1364 event.timeStampSeconds = getCurrentEventTimeSec(m_delegate);
1366 if (shouldForceLayoutOnEvents())
1367 webview()->layout();
1369 webview()->handleInputEvent(event);
1371 // Long press might start a drag drop session. Complete it if so.
1372 if (type == WebInputEvent::GestureLongPress && !currentDragData.isNull()) {
1373 WebMouseEvent mouseEvent;
1374 initMouseEvent(WebInputEvent::MouseDown, pressedButton, point, &mouseEvent, getCurrentEventTimeSec(m_delegate));
1375 finishDragAndDrop(mouseEvent, blink::WebDragOperationNone);
1379 void EventSender::gestureFlingCancel(const CppArgumentList&, CppVariant* result)
1383 WebGestureEvent event;
1384 event.type = WebInputEvent::GestureFlingCancel;
1385 event.timeStampSeconds = getCurrentEventTimeSec(m_delegate);
1387 if (shouldForceLayoutOnEvents())
1388 webview()->layout();
1390 webview()->handleInputEvent(event);
1393 void EventSender::gestureFlingStart(const CppArgumentList& arguments, CppVariant* result)
1396 if (arguments.size() < 4)
1399 for (int i = 0; i < 4; i++)
1400 if (!arguments[i].isNumber())
1403 WebGestureEvent event;
1404 event.type = WebInputEvent::GestureFlingStart;
1406 event.x = static_cast<float>(arguments[0].toDouble());
1407 event.y = static_cast<float>(arguments[1].toDouble());
1408 event.globalX = event.x;
1409 event.globalY = event.y;
1411 event.data.flingStart.velocityX = static_cast<float>(arguments[2].toDouble());
1412 event.data.flingStart.velocityY = static_cast<float>(arguments[3].toDouble());
1413 event.timeStampSeconds = getCurrentEventTimeSec(m_delegate);
1415 if (shouldForceLayoutOnEvents())
1416 webview()->layout();
1418 webview()->handleInputEvent(event);
1422 // Unimplemented stubs
1425 void EventSender::enableDOMUIEventLogging(const CppArgumentList&, CppVariant* result)
1430 void EventSender::fireKeyboardEventsToElement(const CppArgumentList&, CppVariant* result)
1435 void EventSender::clearKillRing(const CppArgumentList&, CppVariant* result)