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 = WebPoint(arguments[0].toInt32(), arguments[1].toInt32());
971 touchPoint.screenPosition = touchPoint.position;
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();
979 touchPoint.radiusX = radiusX;
980 touchPoint.radiusY = radiusY;
984 for (size_t i = 0; i < touchPoints.size(); i++) {
985 if (touchPoints[i].id == lowestId)
988 touchPoint.id = lowestId;
989 touchPoints.push_back(touchPoint);
992 void EventSender::clearTouchPoints(const CppArgumentList&, CppVariant* result)
998 void EventSender::releaseTouchPoint(const CppArgumentList& arguments, CppVariant* result)
1002 const unsigned index = arguments[0].toInt32();
1003 BLINK_ASSERT(index < touchPoints.size());
1005 WebTouchPoint* touchPoint = &touchPoints[index];
1006 touchPoint->state = WebTouchPoint::StateReleased;
1009 void EventSender::setTouchModifier(const CppArgumentList& arguments, CppVariant* result)
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;
1024 if (arguments[1].toBoolean())
1025 touchModifiers |= mask;
1027 touchModifiers &= ~mask;
1030 void EventSender::updateTouchPoint(const CppArgumentList& arguments, CppVariant* result)
1034 const unsigned index = arguments[0].toInt32();
1035 BLINK_ASSERT(index < touchPoints.size());
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;
1044 void EventSender::cancelTouchPoint(const CppArgumentList& arguments, CppVariant* result)
1048 const unsigned index = arguments[0].toInt32();
1049 BLINK_ASSERT(index < touchPoints.size());
1051 WebTouchPoint* touchPoint = &touchPoints[index];
1052 touchPoint->state = WebTouchPoint::StateCancelled;
1055 void EventSender::sendCurrentTouchEvent(const WebInputEvent::Type type)
1057 BLINK_ASSERT(static_cast<unsigned>(WebTouchEvent::touchesLengthCap) > touchPoints.size());
1058 if (shouldForceLayoutOnEvents())
1059 webview()->layout();
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);
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);
1076 touchPoint->state = WebTouchPoint::StateStationary;
1080 void EventSender::mouseDragBegin(const CppArgumentList& arguments, CppVariant* result)
1082 WebMouseWheelEvent event;
1083 initMouseEvent(WebInputEvent::MouseWheel, WebMouseEvent::ButtonNone, lastMousePos, &event, getCurrentEventTimeSec(m_delegate));
1084 event.phase = WebMouseWheelEvent::PhaseBegan;
1085 event.hasPreciseScrollingDeltas = true;
1086 webview()->handleInputEvent(event);
1089 void EventSender::mouseDragEnd(const CppArgumentList& arguments, CppVariant* result)
1091 WebMouseWheelEvent event;
1092 initMouseEvent(WebInputEvent::MouseWheel, WebMouseEvent::ButtonNone, lastMousePos, &event, getCurrentEventTimeSec(m_delegate));
1093 event.phase = WebMouseWheelEvent::PhaseEnded;
1094 event.hasPreciseScrollingDeltas = true;
1095 webview()->handleInputEvent(event);
1098 void EventSender::mouseMomentumBegin(const CppArgumentList& arguments, CppVariant* result)
1100 WebMouseWheelEvent event;
1101 initMouseEvent(WebInputEvent::MouseWheel, WebMouseEvent::ButtonNone, lastMousePos, &event, getCurrentEventTimeSec(m_delegate));
1102 event.momentumPhase = WebMouseWheelEvent::PhaseBegan;
1103 event.hasPreciseScrollingDeltas = true;
1104 webview()->handleInputEvent(event);
1107 void EventSender::mouseMomentumScrollBy(const CppArgumentList& arguments, CppVariant* result)
1109 WebMouseWheelEvent event;
1110 initMouseWheelEvent(arguments, result, true, &event);
1111 event.momentumPhase = WebMouseWheelEvent::PhaseChanged;
1112 event.hasPreciseScrollingDeltas = true;
1113 webview()->handleInputEvent(event);
1116 void EventSender::mouseMomentumEnd(const CppArgumentList& arguments, CppVariant* result)
1118 WebMouseWheelEvent event;
1119 initMouseEvent(WebInputEvent::MouseWheel, WebMouseEvent::ButtonNone, lastMousePos, &event, getCurrentEventTimeSec(m_delegate));
1120 event.momentumPhase = WebMouseWheelEvent::PhaseEnded;
1121 event.hasPreciseScrollingDeltas = true;
1122 webview()->handleInputEvent(event);
1125 void EventSender::initMouseWheelEvent(const CppArgumentList& arguments, CppVariant* result, bool continuous, WebMouseWheelEvent* event)
1129 if (arguments.size() < 2 || !arguments[0].isNumber() || !arguments[1].isNumber())
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();
1138 int horizontal = arguments[0].toInt32();
1139 int vertical = arguments[1].toInt32();
1141 int hasPreciseScrollingDeltas = false;
1143 if (arguments.size() > 2 && arguments[2].isBool())
1144 paged = arguments[2].toBoolean();
1146 if (arguments.size() > 3 && arguments[3].isBool())
1147 hasPreciseScrollingDeltas = arguments[3].toBoolean();
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;
1158 event->wheelTicksX /= scrollbarPixelsPerTick;
1159 event->wheelTicksY /= scrollbarPixelsPerTick;
1161 event->deltaX *= scrollbarPixelsPerTick;
1162 event->deltaY *= scrollbarPixelsPerTick;
1166 void EventSender::touchEnd(const CppArgumentList&, CppVariant* result)
1169 sendCurrentTouchEvent(WebInputEvent::TouchEnd);
1172 void EventSender::touchMove(const CppArgumentList&, CppVariant* result)
1175 sendCurrentTouchEvent(WebInputEvent::TouchMove);
1178 void EventSender::touchStart(const CppArgumentList&, CppVariant* result)
1181 sendCurrentTouchEvent(WebInputEvent::TouchStart);
1184 void EventSender::touchCancel(const CppArgumentList&, CppVariant* result)
1187 sendCurrentTouchEvent(WebInputEvent::TouchCancel);
1190 void EventSender::gestureScrollBegin(const CppArgumentList& arguments, CppVariant* result)
1193 gestureEvent(WebInputEvent::GestureScrollBegin, arguments);
1196 void EventSender::gestureScrollEnd(const CppArgumentList& arguments, CppVariant* result)
1199 gestureEvent(WebInputEvent::GestureScrollEnd, arguments);
1202 void EventSender::gestureScrollUpdate(const CppArgumentList& arguments, CppVariant* result)
1205 gestureEvent(WebInputEvent::GestureScrollUpdate, arguments);
1208 void EventSender::gestureScrollUpdateWithoutPropagation(const CppArgumentList& arguments, CppVariant* result)
1211 gestureEvent(WebInputEvent::GestureScrollUpdateWithoutPropagation, arguments);
1214 void EventSender::gestureTap(const CppArgumentList& arguments, CppVariant* result)
1217 gestureEvent(WebInputEvent::GestureTap, arguments);
1220 void EventSender::gestureTapDown(const CppArgumentList& arguments, CppVariant* result)
1223 gestureEvent(WebInputEvent::GestureTapDown, arguments);
1226 void EventSender::gestureShowPress(const CppArgumentList& arguments, CppVariant* result)
1229 gestureEvent(WebInputEvent::GestureShowPress, arguments);
1232 void EventSender::gestureTapCancel(const CppArgumentList& arguments, CppVariant* result)
1235 gestureEvent(WebInputEvent::GestureTapCancel, arguments);
1238 void EventSender::gestureLongPress(const CppArgumentList& arguments, CppVariant* result)
1241 gestureEvent(WebInputEvent::GestureLongPress, arguments);
1244 void EventSender::gestureLongTap(const CppArgumentList& arguments, CppVariant* result)
1247 gestureEvent(WebInputEvent::GestureLongTap, arguments);
1250 void EventSender::gestureTwoFingerTap(const CppArgumentList& arguments, CppVariant* result)
1253 gestureEvent(WebInputEvent::GestureTwoFingerTap, arguments);
1256 void EventSender::gestureScrollFirstPoint(const CppArgumentList& arguments, CppVariant* result)
1259 if (arguments.size() < 2 || !arguments[0].isNumber() || !arguments[1].isNumber())
1262 WebPoint point(arguments[0].toInt32(), arguments[1].toInt32());
1263 m_currentGestureLocation = point;
1266 void EventSender::gestureEvent(WebInputEvent::Type type, const CppArgumentList& arguments)
1268 if (arguments.size() < 2 || !arguments[0].isNumber() || !arguments[1].isNumber())
1271 WebPoint point(arguments[0].toInt32(), arguments[1].toInt32());
1273 WebGestureEvent event;
1277 case WebInputEvent::GestureScrollUpdate:
1278 case WebInputEvent::GestureScrollUpdateWithoutPropagation:
1279 event.data.scrollUpdate.deltaX = static_cast<float>(arguments[0].toDouble());
1280 event.data.scrollUpdate.deltaY = static_cast<float>(arguments[1].toDouble());
1281 event.x = m_currentGestureLocation.x;
1282 event.y = m_currentGestureLocation.y;
1283 m_currentGestureLocation.x = m_currentGestureLocation.x + event.data.scrollUpdate.deltaX;
1284 m_currentGestureLocation.y = m_currentGestureLocation.y + event.data.scrollUpdate.deltaY;
1287 case WebInputEvent::GestureScrollBegin:
1288 m_currentGestureLocation = WebPoint(point.x, point.y);
1289 event.x = m_currentGestureLocation.x;
1290 event.y = m_currentGestureLocation.y;
1292 case WebInputEvent::GestureScrollEnd:
1293 case WebInputEvent::GestureFlingStart:
1294 event.x = m_currentGestureLocation.x;
1295 event.y = m_currentGestureLocation.y;
1297 case WebInputEvent::GestureTap:
1298 if (arguments.size() >= 3)
1299 event.data.tap.tapCount = static_cast<float>(arguments[2].toDouble());
1301 event.data.tap.tapCount = 1;
1305 case WebInputEvent::GestureTapUnconfirmed:
1306 if (arguments.size() >= 3)
1307 event.data.tap.tapCount = static_cast<float>(arguments[2].toDouble());
1309 event.data.tap.tapCount = 1;
1313 case WebInputEvent::GestureTapDown:
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());
1321 case WebInputEvent::GestureShowPress:
1324 if (arguments.size() >= 4) {
1325 event.data.showPress.width = static_cast<float>(arguments[2].toDouble());
1326 event.data.showPress.height = static_cast<float>(arguments[3].toDouble());
1329 case WebInputEvent::GestureTapCancel:
1333 case WebInputEvent::GestureLongPress:
1336 if (arguments.size() >= 4) {
1337 event.data.longPress.width = static_cast<float>(arguments[2].toDouble());
1338 event.data.longPress.height = static_cast<float>(arguments[3].toDouble());
1341 case WebInputEvent::GestureLongTap:
1344 if (arguments.size() >= 4) {
1345 event.data.longPress.width = static_cast<float>(arguments[2].toDouble());
1346 event.data.longPress.height = static_cast<float>(arguments[3].toDouble());
1349 case WebInputEvent::GestureTwoFingerTap:
1352 if (arguments.size() >= 4) {
1353 event.data.twoFingerTap.firstFingerWidth = static_cast<float>(arguments[2].toDouble());
1354 event.data.twoFingerTap.firstFingerHeight = static_cast<float>(arguments[3].toDouble());
1358 BLINK_ASSERT_NOT_REACHED();
1361 event.globalX = event.x;
1362 event.globalY = event.y;
1363 event.timeStampSeconds = getCurrentEventTimeSec(m_delegate);
1365 if (shouldForceLayoutOnEvents())
1366 webview()->layout();
1368 webview()->handleInputEvent(event);
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, &mouseEvent, getCurrentEventTimeSec(m_delegate));
1374 finishDragAndDrop(mouseEvent, blink::WebDragOperationNone);
1378 void EventSender::gestureFlingCancel(const CppArgumentList&, CppVariant* result)
1382 WebGestureEvent event;
1383 event.type = WebInputEvent::GestureFlingCancel;
1384 event.timeStampSeconds = getCurrentEventTimeSec(m_delegate);
1386 if (shouldForceLayoutOnEvents())
1387 webview()->layout();
1389 webview()->handleInputEvent(event);
1392 void EventSender::gestureFlingStart(const CppArgumentList& arguments, CppVariant* result)
1395 if (arguments.size() < 4)
1398 for (int i = 0; i < 4; i++)
1399 if (!arguments[i].isNumber())
1402 WebGestureEvent event;
1403 event.type = WebInputEvent::GestureFlingStart;
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;
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);
1414 if (shouldForceLayoutOnEvents())
1415 webview()->layout();
1417 webview()->handleInputEvent(event);
1421 // Unimplemented stubs
1424 void EventSender::enableDOMUIEventLogging(const CppArgumentList&, CppVariant* result)
1429 void EventSender::fireKeyboardEventsToElement(const CppArgumentList&, CppVariant* result)
1434 void EventSender::clearKillRing(const CppArgumentList&, CppVariant* result)