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

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

Powered by Google App Engine
This is Rietveld 408576698