Index: webkit/tools/test_shell/event_sending_controller.cc |
diff --git a/webkit/tools/test_shell/event_sending_controller.cc b/webkit/tools/test_shell/event_sending_controller.cc |
deleted file mode 100644 |
index cf9aaf26404134746269b975d770fef525d970fd..0000000000000000000000000000000000000000 |
--- a/webkit/tools/test_shell/event_sending_controller.cc |
+++ /dev/null |
@@ -1,1079 +0,0 @@ |
-// Copyright (c) 2010 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-// This file contains the definition for EventSendingController. |
-// |
-// Some notes about drag and drop handling: |
-// Windows drag and drop goes through a system call to DoDragDrop. At that |
-// point, program control is given to Windows which then periodically makes |
-// callbacks into the webview. This won't work for layout tests, so instead, |
-// we queue up all the mouse move and mouse up events. When the test tries to |
-// start a drag (by calling EvenSendingController::DoDragDrop), we take the |
-// events in the queue and replay them. |
-// The behavior of queuing events and replaying them can be disabled by a |
-// layout test by setting eventSender.dragMode to false. |
- |
-#include "webkit/tools/test_shell/event_sending_controller.h" |
- |
-#include <queue> |
-#include <vector> |
- |
-#include "base/compiler_specific.h" |
-#include "base/file_path.h" |
-#include "base/file_util.h" |
-#include "base/logging.h" |
-#include "base/message_loop.h" |
-#include "base/time.h" |
-#include "base/string_number_conversions.h" |
-#include "base/string_util.h" |
-#include "base/utf_string_conversions.h" |
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebDragData.h" |
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebDragOperation.h" |
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebPoint.h" |
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h" |
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebTouchPoint.h" |
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" |
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebBindings.h" |
-#include "ui/base/keycodes/keyboard_codes.h" |
-#include "webkit/glue/webkit_glue.h" |
-#include "webkit/tools/test_shell/test_shell.h" |
-#include "webkit/tools/test_shell/test_webview_delegate.h" |
- |
-#if defined(OS_WIN) |
-#include "third_party/WebKit/Source/WebKit/chromium/public/win/WebInputEventFactory.h" |
-using WebKit::WebInputEventFactory; |
-#endif |
- |
-// TODO(mpcomplete): layout before each event? |
- |
-using base::Time; |
-using base::TimeTicks; |
-using WebKit::WebDragOperation; |
-using WebKit::WebDragOperationsMask; |
-using WebKit::WebDragData; |
-using WebKit::WebInputEvent; |
-using WebKit::WebKeyboardEvent; |
-using WebKit::WebMouseEvent; |
-using WebKit::WebMouseWheelEvent; |
-using WebKit::WebPoint; |
-using WebKit::WebString; |
-using WebKit::WebTouchEvent; |
-using WebKit::WebTouchPoint; |
-using WebKit::WebView; |
- |
-gfx::Point EventSendingController::last_mouse_pos_; |
-WebMouseEvent::Button EventSendingController::pressed_button_ = |
- WebMouseEvent::ButtonNone; |
- |
-WebMouseEvent::Button EventSendingController::last_button_type_ = |
- WebMouseEvent::ButtonNone; |
- |
-namespace { |
- |
-struct SavedEvent { |
- enum SavedEventType { |
- Unspecified, |
- MouseUp, |
- MouseMove, |
- LeapForward |
- }; |
- |
- SavedEventType type; |
- WebMouseEvent::Button button_type; // For MouseUp |
- gfx::Point pos; // For MouseMove. |
- int milliseconds; // For LeapForward. |
- |
- SavedEvent() |
- : type(Unspecified), |
- button_type(WebMouseEvent::ButtonNone), |
- milliseconds(0) { |
- } |
-}; |
- |
-static WebDragData current_drag_data; |
-static WebDragOperation current_drag_effect; |
-static WebDragOperationsMask current_drag_effects_allowed; |
-static bool replaying_saved_events = false; |
-static std::queue<SavedEvent> mouse_event_queue; |
-static int touch_modifiers; |
-static std::vector<WebTouchPoint> touch_points; |
- |
-// Time and place of the last mouse up event. |
-static double last_click_time_sec = 0; |
-static gfx::Point last_click_pos; |
-static int click_count = 0; |
- |
-// maximum distance (in space and time) for a mouse click |
-// to register as a double or triple click |
-static const double kMultiClickTimeSec = 1; |
-static const int kMultiClickRadiusPixels = 5; |
- |
-// How much we should scroll per event - the value here is chosen to |
-// match the WebKit impl and layout test results. |
-static const float kScrollbarPixelsPerTick = 40.0f; |
- |
-inline bool outside_multiclick_radius(const gfx::Point &a, |
- const gfx::Point &b) { |
- return ((a.x() - b.x()) * (a.x() - b.x()) + |
- (a.y() - b.y()) * (a.y() - b.y())) > |
- kMultiClickRadiusPixels * kMultiClickRadiusPixels; |
-} |
- |
-// Used to offset the time the event hander things an event happened. This is |
-// done so tests can run without a delay, but bypass checks that are time |
-// dependent (e.g., dragging has a timeout vs selection). |
-static uint32 time_offset_ms = 0; |
- |
-double GetCurrentEventTimeSec() { |
- return (TimeTicks::Now().ToInternalValue() |
- / Time::kMicrosecondsPerMillisecond + |
- time_offset_ms) / 1000.0; |
-} |
- |
-void AdvanceEventTime(int32 delta_ms) { |
- time_offset_ms += delta_ms; |
-} |
- |
-void InitMouseEvent(WebInputEvent::Type t, WebMouseEvent::Button b, |
- const gfx::Point& pos, WebMouseEvent* e) { |
- e->type = t; |
- e->button = b; |
- e->modifiers = 0; |
- e->x = pos.x(); |
- e->y = pos.y(); |
- e->globalX = pos.x(); |
- e->globalY = pos.y(); |
- e->timeStampSeconds = GetCurrentEventTimeSec(); |
- e->clickCount = click_count; |
-} |
- |
-// Returns true if the specified key is the system key. |
-bool ApplyKeyModifier(const std::string& key, WebInputEvent* event) { |
- bool system_key = false; |
- if (key == "ctrlKey" |
-#if !defined(OS_MACOSX) |
- || key == "addSelectionKey" |
-#endif |
- ) { |
- event->modifiers |= WebInputEvent::ControlKey; |
- } else if (key == "shiftKey" || key == "rangeSelectionKey") { |
- event->modifiers |= WebInputEvent::ShiftKey; |
- } else if (key == "altKey") { |
- event->modifiers |= WebInputEvent::AltKey; |
-#if !defined(OS_MACOSX) |
- // On Windows all keys with Alt modifier will be marked as system key. |
- // We keep the same behavior on Linux and everywhere non-Mac, see: |
- // third_party/WebKit/Source/WebKit/chromium/src/gtk/WebInputEventFactory.cpp |
- // If we want to change this behavior on Linux, this piece of code must be |
- // kept in sync with the related code in above file. |
- system_key = true; |
-#endif |
-#if defined(OS_MACOSX) |
- } else if (key == "metaKey" || key == "addSelectionKey") { |
- event->modifiers |= WebInputEvent::MetaKey; |
- // On Mac only command key presses are marked as system key. |
- // See the related code in: |
- // third_party/WebKit/Source/WebKit/chromium/src/mac/WebInputEventFactory.cpp |
- // It must be kept in sync with the related code in above file. |
- system_key = true; |
-#else |
- } else if (key == "metaKey") { |
- event->modifiers |= WebInputEvent::MetaKey; |
-#endif |
- } |
- return system_key; |
-} |
- |
-bool ApplyKeyModifiers(const CppVariant* arg, WebInputEvent* event) { |
- bool system_key = false; |
- if (arg->isObject()) { |
- std::vector<std::string> args = arg->ToStringVector(); |
- for (std::vector<std::string>::const_iterator i = args.begin(); |
- i != args.end(); ++i) { |
- system_key |= ApplyKeyModifier(*i, event); |
- } |
- } else if (arg->isString()) { |
- system_key = ApplyKeyModifier(arg->ToString(), event); |
- } |
- return system_key; |
-} |
- |
-// Get the edit command corresponding to a keyboard event. |
-// Returns true if the specified event corresponds to an edit command, the name |
-// of the edit command will be stored in |*name|. |
-bool GetEditCommand(const WebKeyboardEvent& event, std::string* name) { |
-#if defined(OS_MACOSX) |
- // We only cares about Left,Right,Up,Down keys with Command or Command+Shift |
- // modifiers. These key events correspond to some special movement and |
- // selection editor commands, and was supposed to be handled in |
- // third_party/WebKit/Source/WebKit/chromium/src/EditorClientImpl.cpp. But these keys |
- // will be marked as system key, which prevents them from being handled. |
- // Thus they must be handled specially. |
- if ((event.modifiers & ~WebKeyboardEvent::ShiftKey) != |
- WebKeyboardEvent::MetaKey) |
- return false; |
- |
- switch (event.windowsKeyCode) { |
- case ui::VKEY_LEFT: |
- *name = "MoveToBeginningOfLine"; |
- break; |
- case ui::VKEY_RIGHT: |
- *name = "MoveToEndOfLine"; |
- break; |
- case ui::VKEY_UP: |
- *name = "MoveToBeginningOfDocument"; |
- break; |
- case ui::VKEY_DOWN: |
- *name = "MoveToEndOfDocument"; |
- break; |
- default: |
- return false; |
- } |
- |
- if (event.modifiers & WebKeyboardEvent::ShiftKey) |
- name->append("AndModifySelection"); |
- |
- return true; |
-#else |
- return false; |
-#endif |
-} |
- |
-// Key event location code introduced in DOM Level 3. |
-// See also: http://www.w3.org/TR/DOM-Level-3-Events/#events-keyboardevents |
-enum KeyLocationCode { |
- DOM_KEY_LOCATION_STANDARD = 0x00, |
- DOM_KEY_LOCATION_LEFT = 0x01, |
- DOM_KEY_LOCATION_RIGHT = 0x02, |
- DOM_KEY_LOCATION_NUMPAD = 0x03 |
-}; |
- |
-} // anonymous namespace |
- |
-EventSendingController::EventSendingController(TestShell* shell) |
- : ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)), |
- shell_(shell) { |
- // Initialize the map that associates methods of this class with the names |
- // they will use when called by JavaScript. The actual binding of those |
- // names to their methods will be done by calling BindToJavaScript() (defined |
- // by CppBoundClass, the parent to EventSendingController). |
- BindMethod("mouseDown", &EventSendingController::mouseDown); |
- BindMethod("mouseUp", &EventSendingController::mouseUp); |
- BindMethod("contextClick", &EventSendingController::contextClick); |
- BindMethod("mouseMoveTo", &EventSendingController::mouseMoveTo); |
- BindMethod("leapForward", &EventSendingController::leapForward); |
- BindMethod("keyDown", &EventSendingController::keyDown); |
- BindMethod("dispatchMessage", &EventSendingController::dispatchMessage); |
- BindMethod("enableDOMUIEventLogging", |
- &EventSendingController::enableDOMUIEventLogging); |
- BindMethod("fireKeyboardEventsToElement", |
- &EventSendingController::fireKeyboardEventsToElement); |
- BindMethod("clearKillRing", &EventSendingController::clearKillRing); |
- BindMethod("textZoomIn", &EventSendingController::textZoomIn); |
- BindMethod("textZoomOut", &EventSendingController::textZoomOut); |
- BindMethod("zoomPageIn", &EventSendingController::zoomPageIn); |
- BindMethod("zoomPageOut", &EventSendingController::zoomPageOut); |
- BindMethod("mouseScrollBy", &EventSendingController::mouseScrollBy); |
- BindMethod("continuousMouseScrollBy", |
- &EventSendingController::continuousMouseScrollBy); |
- BindMethod("scheduleAsynchronousClick", |
- &EventSendingController::scheduleAsynchronousClick); |
- BindMethod("beginDragWithFiles", |
- &EventSendingController::beginDragWithFiles); |
- BindMethod("addTouchPoint", &EventSendingController::addTouchPoint); |
- BindMethod("cancelTouchPoint", &EventSendingController::cancelTouchPoint); |
- BindMethod("clearTouchPoints", &EventSendingController::clearTouchPoints); |
- BindMethod("releaseTouchPoint", &EventSendingController::releaseTouchPoint); |
- BindMethod("updateTouchPoint", &EventSendingController::updateTouchPoint); |
- BindMethod("setTouchModifier", &EventSendingController::setTouchModifier); |
- BindMethod("touchCancel", &EventSendingController::touchCancel); |
- BindMethod("touchEnd", &EventSendingController::touchEnd); |
- BindMethod("touchMove", &EventSendingController::touchMove); |
- BindMethod("touchStart", &EventSendingController::touchStart); |
- |
- // When set to true (the default value), we batch mouse move and mouse up |
- // events so we can simulate drag & drop. |
- BindProperty("dragMode", &dragMode); |
-#if defined(OS_WIN) |
- BindProperty("WM_KEYDOWN", &wmKeyDown); |
- BindProperty("WM_KEYUP", &wmKeyUp); |
- BindProperty("WM_CHAR", &wmChar); |
- BindProperty("WM_DEADCHAR", &wmDeadChar); |
- BindProperty("WM_SYSKEYDOWN", &wmSysKeyDown); |
- BindProperty("WM_SYSKEYUP", &wmSysKeyUp); |
- BindProperty("WM_SYSCHAR", &wmSysChar); |
- BindProperty("WM_SYSDEADCHAR", &wmSysDeadChar); |
-#endif |
-} |
- |
-EventSendingController::~EventSendingController() { |
-} |
- |
-void EventSendingController::Reset() { |
- // The test should have finished a drag and the mouse button state. |
- DCHECK(current_drag_data.isNull()); |
- current_drag_data.reset(); |
- current_drag_effect = WebKit::WebDragOperationNone; |
- current_drag_effects_allowed = WebKit::WebDragOperationNone; |
- pressed_button_ = WebMouseEvent::ButtonNone; |
- dragMode.Set(true); |
-#if defined(OS_WIN) |
- wmKeyDown.Set(WM_KEYDOWN); |
- wmKeyUp.Set(WM_KEYUP); |
- wmChar.Set(WM_CHAR); |
- wmDeadChar.Set(WM_DEADCHAR); |
- wmSysKeyDown.Set(WM_SYSKEYDOWN); |
- wmSysKeyUp.Set(WM_SYSKEYUP); |
- wmSysChar.Set(WM_SYSCHAR); |
- wmSysDeadChar.Set(WM_SYSDEADCHAR); |
-#endif |
- last_mouse_pos_.SetPoint(0, 0); |
- last_click_time_sec = 0; |
- last_click_pos.SetPoint(0, 0); |
- click_count = 0; |
- last_button_type_ = WebMouseEvent::ButtonNone; |
- time_offset_ms = 0; |
- touch_modifiers = 0; |
- touch_points.clear(); |
-} |
- |
-WebView* EventSendingController::webview() { |
- return shell_->webView(); |
-} |
- |
-void EventSendingController::DoDragDrop(const WebDragData& drag_data, |
- WebDragOperationsMask mask) { |
- WebMouseEvent event; |
- InitMouseEvent(WebInputEvent::MouseDown, pressed_button_, last_mouse_pos_, |
- &event); |
- WebPoint client_point(event.x, event.y); |
- WebPoint screen_point(event.globalX, event.globalY); |
- current_drag_data = drag_data; |
- current_drag_effects_allowed = mask; |
- current_drag_effect = webview()->dragTargetDragEnter( |
- drag_data, 0, client_point, screen_point, current_drag_effects_allowed); |
- |
- // Finish processing events. |
- ReplaySavedEvents(); |
-} |
- |
-WebMouseEvent::Button EventSendingController::GetButtonTypeFromButtonNumber( |
- int button_code) { |
- if (button_code == 0) |
- return WebMouseEvent::ButtonLeft; |
- else if (button_code == 2) |
- return WebMouseEvent::ButtonRight; |
- |
- return WebMouseEvent::ButtonMiddle; |
-} |
- |
-// static |
-int EventSendingController::GetButtonNumberFromSingleArg( |
- const CppArgumentList& args) { |
- int button_code = 0; |
- |
- if (args.size() > 0 && args[0].isNumber()) { |
- button_code = args[0].ToInt32(); |
- } |
- |
- return button_code; |
-} |
- |
-void EventSendingController::UpdateClickCountForButton( |
- WebMouseEvent::Button button_type) { |
- if ((GetCurrentEventTimeSec() - last_click_time_sec < kMultiClickTimeSec) && |
- (!outside_multiclick_radius(last_mouse_pos_, last_click_pos)) && |
- (button_type == last_button_type_)) { |
- ++click_count; |
- } else { |
- click_count = 1; |
- last_button_type_ = button_type; |
- } |
-} |
- |
-// |
-// Implemented javascript methods. |
-// |
- |
-void EventSendingController::mouseDown( |
- const CppArgumentList& args, CppVariant* result) { |
- if (result) // Could be NULL if invoked asynchronously. |
- result->SetNull(); |
- |
- webview()->layout(); |
- |
- int button_number = GetButtonNumberFromSingleArg(args); |
- DCHECK(button_number != -1); |
- |
- WebMouseEvent::Button button_type = GetButtonTypeFromButtonNumber( |
- button_number); |
- |
- UpdateClickCountForButton(button_type); |
- |
- WebMouseEvent event; |
- pressed_button_ = button_type; |
- InitMouseEvent(WebInputEvent::MouseDown, button_type, |
- last_mouse_pos_, &event); |
- if (args.size() >= 2 && (args[1].isObject() || args[1].isString())) |
- ApplyKeyModifiers(&(args[1]), &event); |
- webview()->handleInputEvent(event); |
-} |
- |
-void EventSendingController::mouseUp( |
- const CppArgumentList& args, CppVariant* result) { |
- if (result) // Could be NULL if invoked asynchronously. |
- result->SetNull(); |
- |
- webview()->layout(); |
- |
- int button_number = GetButtonNumberFromSingleArg(args); |
- DCHECK(button_number != -1); |
- |
- WebMouseEvent::Button button_type = GetButtonTypeFromButtonNumber( |
- button_number); |
- |
- if (drag_mode() && !replaying_saved_events) { |
- SavedEvent saved_event; |
- saved_event.type = SavedEvent::MouseUp; |
- saved_event.button_type = button_type; |
- mouse_event_queue.push(saved_event); |
- ReplaySavedEvents(); |
- } else { |
- WebMouseEvent event; |
- InitMouseEvent(WebInputEvent::MouseUp, button_type, |
- last_mouse_pos_, &event); |
- if (args.size() >= 2 && (args[1].isObject() || args[1].isString())) |
- ApplyKeyModifiers(&(args[1]), &event); |
- DoMouseUp(event); |
- } |
-} |
- |
-void EventSendingController::DoMouseUp(const WebMouseEvent& e) { |
- webview()->handleInputEvent(e); |
- |
- pressed_button_ = WebMouseEvent::ButtonNone; |
- last_click_time_sec = e.timeStampSeconds; |
- last_click_pos = last_mouse_pos_; |
- |
- // If we're in a drag operation, complete it. |
- if (!current_drag_data.isNull()) { |
- WebPoint client_point(e.x, e.y); |
- WebPoint screen_point(e.globalX, e.globalY); |
- |
- current_drag_effect = webview()->dragTargetDragOver( |
- client_point, screen_point, current_drag_effects_allowed); |
- if (current_drag_effect) { |
- webview()->dragTargetDrop(client_point, screen_point); |
- } else { |
- webview()->dragTargetDragLeave(); |
- } |
- webview()->dragSourceEndedAt( |
- client_point, screen_point, current_drag_effect); |
- webview()->dragSourceSystemDragEnded(); |
- |
- current_drag_data.reset(); |
- } |
-} |
- |
-void EventSendingController::mouseMoveTo( |
- const CppArgumentList& args, CppVariant* result) { |
- result->SetNull(); |
- |
- if (args.size() >= 2 && args[0].isNumber() && args[1].isNumber()) { |
- webview()->layout(); |
- |
- gfx::Point mouse_pos; |
- mouse_pos.SetPoint(args[0].ToInt32(), args[1].ToInt32()); |
- |
- if (drag_mode() && pressed_button_ == WebMouseEvent::ButtonLeft && |
- !replaying_saved_events) { |
- SavedEvent saved_event; |
- saved_event.type = SavedEvent::MouseMove; |
- saved_event.pos = mouse_pos; |
- mouse_event_queue.push(saved_event); |
- } else { |
- WebMouseEvent event; |
- InitMouseEvent(WebInputEvent::MouseMove, pressed_button_, |
- mouse_pos, &event); |
- DoMouseMove(event); |
- } |
- } |
-} |
- |
-void EventSendingController::DoMouseMove(const WebMouseEvent& e) { |
- last_mouse_pos_.SetPoint(e.x, e.y); |
- |
- webview()->handleInputEvent(e); |
- |
- if (pressed_button_ != WebMouseEvent::ButtonNone && |
- !current_drag_data.isNull()) { |
- WebPoint client_point(e.x, e.y); |
- WebPoint screen_point(e.globalX, e.globalY); |
- |
- current_drag_effect = webview()->dragTargetDragOver( |
- client_point, screen_point, current_drag_effects_allowed); |
- } |
-} |
- |
-void EventSendingController::keyDown( |
- const CppArgumentList& args, CppVariant* result) { |
- result->SetNull(); |
- |
- bool generate_char = false; |
- |
- if (args.size() >= 1 && args[0].isString()) { |
- // TODO(mpcomplete): I'm not exactly sure how we should convert the string |
- // to a key event. This seems to work in the cases I tested. |
- // TODO(mpcomplete): Should we also generate a KEY_UP? |
- std::wstring code_str = UTF8ToWide(args[0].ToString()); |
- |
- // Convert \n -> VK_RETURN. Some layout tests use \n to mean "Enter", when |
- // Windows uses \r for "Enter". |
- int code = 0; |
- int text = 0; |
- bool needs_shift_key_modifier = false; |
- if (L"\n" == code_str) { |
- generate_char = true; |
- text = code = ui::VKEY_RETURN; |
- } else if (L"rightArrow" == code_str) { |
- code = ui::VKEY_RIGHT; |
- } else if (L"downArrow" == code_str) { |
- code = ui::VKEY_DOWN; |
- } else if (L"leftArrow" == code_str) { |
- code = ui::VKEY_LEFT; |
- } else if (L"upArrow" == code_str) { |
- code = ui::VKEY_UP; |
- } else if (L"insert" == code_str) { |
- code = ui::VKEY_INSERT; |
- } else if (L"delete" == code_str) { |
- code = ui::VKEY_DELETE; |
- } else if (L"pageUp" == code_str) { |
- code = ui::VKEY_PRIOR; |
- } else if (L"pageDown" == code_str) { |
- code = ui::VKEY_NEXT; |
- } else if (L"home" == code_str) { |
- code = ui::VKEY_HOME; |
- } else if (L"end" == code_str) { |
- code = ui::VKEY_END; |
- } else if (L"printScreen" == code_str) { |
- code = ui::VKEY_SNAPSHOT; |
- } else { |
- // Compare the input string with the function-key names defined by the |
- // DOM spec (i.e. "F1",...,"F24"). If the input string is a function-key |
- // name, set its key code. |
- for (int i = 1; i <= 24; ++i) { |
- std::wstring function_key_name; |
- function_key_name += L"F"; |
- function_key_name += UTF8ToWide(base::IntToString(i)); |
- if (function_key_name == code_str) { |
- code = ui::VKEY_F1 + (i - 1); |
- break; |
- } |
- } |
- if (!code) { |
- DCHECK(code_str.length() == 1); |
- text = code = code_str[0]; |
- needs_shift_key_modifier = NeedsShiftModifier(code); |
- if ((code & 0xFF) >= 'a' && (code & 0xFF) <= 'z') |
- code -= 'a' - 'A'; |
- generate_char = true; |
- } |
- } |
- |
- // For one generated keyboard event, we need to generate a keyDown/keyUp |
- // pair; refer to EventSender.cpp in WebKit/Tools/DumpRenderTree/win. |
- // On Windows, we might also need to generate a char event to mimic the |
- // Windows event flow; on other platforms we create a merged event and test |
- // the event flow that that platform provides. |
- WebKeyboardEvent event_down, event_char, event_up; |
- event_down.type = WebInputEvent::RawKeyDown; |
- event_down.modifiers = 0; |
- event_down.windowsKeyCode = code; |
- if (generate_char) { |
- event_down.text[0] = text; |
- event_down.unmodifiedText[0] = text; |
- } |
- event_down.setKeyIdentifierFromWindowsKeyCode(); |
- |
- if (args.size() >= 2 && (args[1].isObject() || args[1].isString())) |
- event_down.isSystemKey = ApplyKeyModifiers(&(args[1]), &event_down); |
- |
- if (needs_shift_key_modifier) |
- event_down.modifiers |= WebInputEvent::ShiftKey; |
- |
- // See if KeyLocation argument is given. |
- if (args.size() >= 3 && args[2].isNumber()) { |
- int location = args[2].ToInt32(); |
- if (location == DOM_KEY_LOCATION_NUMPAD) { |
- event_down.modifiers |= WebInputEvent::IsKeyPad; |
- } |
- } |
- |
- event_char = event_up = event_down; |
- event_up.type = WebInputEvent::KeyUp; |
- // EventSendingController.m forces a layout here, with at least one |
- // test (fast\forms\focus-control-to-page.html) relying on this. |
- webview()->layout(); |
- |
- // In the browser, if a keyboard event corresponds to an editor command, |
- // the command will be dispatched to the renderer just before dispatching |
- // the keyboard event, and then it will be executed in the |
- // RenderView::handleCurrentKeyboardEvent() method, which is called from |
- // third_party/WebKit/Source/WebKit/chromium/src/EditorClientImpl.cpp. |
- // We just simulate the same behavior here. |
- std::string edit_command; |
- if (GetEditCommand(event_down, &edit_command)) |
- shell_->delegate()->SetEditCommand(edit_command, ""); |
- |
- webview()->handleInputEvent(event_down); |
- |
- shell_->delegate()->ClearEditCommand(); |
- |
- if (generate_char) { |
- event_char.type = WebInputEvent::Char; |
- event_char.keyIdentifier[0] = '\0'; |
- webview()->handleInputEvent(event_char); |
- } |
- |
- webview()->handleInputEvent(event_up); |
- } |
-} |
- |
-void EventSendingController::dispatchMessage( |
- const CppArgumentList& args, CppVariant* result) { |
- result->SetNull(); |
- |
-#if defined(OS_WIN) |
- if (args.size() == 3) { |
- // Grab the message id to see if we need to dispatch it. |
- int msg = args[0].ToInt32(); |
- |
- // WebKit's version of this function stuffs a MSG struct and uses |
- // TranslateMessage and DispatchMessage. We use a WebKeyboardEvent, which |
- // doesn't need to receive the DeadChar and SysDeadChar messages. |
- if (msg == WM_DEADCHAR || msg == WM_SYSDEADCHAR) |
- return; |
- |
- webview()->layout(); |
- |
- unsigned long lparam = static_cast<unsigned long>(args[2].ToDouble()); |
- webview()->handleInputEvent(WebInputEventFactory::keyboardEvent( |
- NULL, msg, args[1].ToInt32(), lparam)); |
- } else { |
- NOTREACHED() << L"Wrong number of arguments"; |
- } |
-#endif |
-} |
- |
-bool EventSendingController::NeedsShiftModifier(int key_code) { |
- // If code is an uppercase letter, assign a SHIFT key to |
- // event_down.modifier, this logic comes from |
- // WebKit/Tools/DumpRenderTree/Win/EventSender.cpp |
- if ((key_code & 0xFF) >= 'A' && (key_code & 0xFF) <= 'Z') |
- return true; |
- return false; |
-} |
- |
-void EventSendingController::leapForward( |
- const CppArgumentList& args, CppVariant* result) { |
- result->SetNull(); |
- |
- if (args.size() <1 || !args[0].isNumber()) |
- return; |
- |
- int milliseconds = args[0].ToInt32(); |
- if (drag_mode() && pressed_button_ == WebMouseEvent::ButtonLeft && |
- !replaying_saved_events) { |
- SavedEvent saved_event; |
- saved_event.type = SavedEvent::LeapForward; |
- saved_event.milliseconds = milliseconds; |
- mouse_event_queue.push(saved_event); |
- } else { |
- DoLeapForward(milliseconds); |
- } |
-} |
- |
-// static |
-void EventSendingController::DoLeapForward(int milliseconds) { |
- AdvanceEventTime(milliseconds); |
-} |
- |
-// Apple's port of WebKit zooms by a factor of 1.2 (see |
-// WebKit/WebView/WebView.mm) |
-void EventSendingController::textZoomIn( |
- const CppArgumentList& args, CppVariant* result) { |
- webview()->setZoomLevel(true, webview()->zoomLevel() + 1); |
- result->SetNull(); |
-} |
- |
-void EventSendingController::textZoomOut( |
- const CppArgumentList& args, CppVariant* result) { |
- webview()->setZoomLevel(true, webview()->zoomLevel() - 1); |
- result->SetNull(); |
-} |
- |
-void EventSendingController::zoomPageIn( |
- const CppArgumentList& args, CppVariant* result) { |
- webview()->setZoomLevel(false, webview()->zoomLevel() + 1); |
- result->SetNull(); |
-} |
- |
-void EventSendingController::zoomPageOut( |
- const CppArgumentList& args, CppVariant* result) { |
- webview()->setZoomLevel(false, webview()->zoomLevel() - 1); |
- result->SetNull(); |
-} |
- |
-void EventSendingController::mouseScrollBy(const CppArgumentList& args, |
- CppVariant* result) { |
- handleMouseWheel(args, result, false); |
-} |
- |
-void EventSendingController::continuousMouseScrollBy( |
- const CppArgumentList& args, |
- CppVariant* result) { |
- handleMouseWheel(args, result, true); |
-} |
- |
-void EventSendingController::ReplaySavedEvents() { |
- replaying_saved_events = true; |
- while (!mouse_event_queue.empty()) { |
- SavedEvent e = mouse_event_queue.front(); |
- mouse_event_queue.pop(); |
- |
- switch (e.type) { |
- case SavedEvent::MouseMove: { |
- WebMouseEvent event; |
- InitMouseEvent(WebInputEvent::MouseMove, pressed_button_, |
- e.pos, &event); |
- DoMouseMove(event); |
- break; |
- } |
- case SavedEvent::LeapForward: |
- DoLeapForward(e.milliseconds); |
- break; |
- case SavedEvent::MouseUp: { |
- WebMouseEvent event; |
- InitMouseEvent(WebInputEvent::MouseUp, e.button_type, |
- last_mouse_pos_, &event); |
- DoMouseUp(event); |
- break; |
- } |
- default: |
- NOTREACHED(); |
- } |
- } |
- |
- replaying_saved_events = false; |
-} |
- |
-// Because actual context menu is implemented by the browser side, |
-// this function does only what LayoutTests are expecting: |
-// - Many test checks the count of items. So returning non-zero value |
-// makes sense. |
-// - Some test compares the count before and after some action. So |
-// changing the count based on flags also makes sense. This function |
-// is doing such for some flags. |
-// - Some test even checks actual string content. So providing it |
-// would be also helpful. |
-static std::vector<WebString> |
-MakeMenuItemStringsFor(const WebKit::WebContextMenuData* context_menu, |
- MockSpellCheck* spellcheck) { |
- // These constants are based on Safari's context menu because tests |
- // are made for it. |
- static const char* kNonEditableMenuStrings[] = { |
- "Back", "Reload Page", "Open in Dashbaord", "<separator>", |
- "View Source", "Save Page As", "Print Page", "Inspect Element", |
- 0 }; |
- static const char* kEditableMenuStrings[] = { |
- "Cut", "Copy", "<separator>", "Paste", "Spelling and Grammar", |
- "Substitutions, Transformations", "Font", "Speech", |
- "Paragraph Direction", "<separator>", 0 }; |
- |
- // This is possible because mouse events are cancelleable. |
- if (!context_menu) |
- return std::vector<WebString>(); |
- |
- std::vector<WebString> strings; |
- |
- if (context_menu->isEditable) { |
- for (const char** item = kEditableMenuStrings; *item; ++item) |
- strings.push_back(WebString::fromUTF8(*item)); |
- std::vector<string16> suggestions; |
- spellcheck->FillSuggestions(context_menu->misspelledWord, &suggestions); |
- for (size_t i = 0; i < suggestions.size(); ++i) |
- strings.push_back(WebString(suggestions[i])); |
- } else { |
- for (const char** item = kNonEditableMenuStrings; *item; ++item) |
- strings.push_back(WebString::fromUTF8(*item)); |
- } |
- |
- return strings; |
-} |
- |
-void EventSendingController::contextClick( |
- const CppArgumentList& args, CppVariant* result) { |
- result->SetNull(); |
- |
- webview()->layout(); |
- |
- // Clears last context menu data because we need to know if the |
- // context menu be requested after following mouse events. |
- shell_->delegate()->ClearContextMenuData(); |
- |
- UpdateClickCountForButton(WebMouseEvent::ButtonRight); |
- |
- // Generate right mouse down and up. |
- |
- WebMouseEvent event; |
- pressed_button_ = WebMouseEvent::ButtonRight; |
- InitMouseEvent(WebInputEvent::MouseDown, WebMouseEvent::ButtonRight, |
- last_mouse_pos_, &event); |
- webview()->handleInputEvent(event); |
- |
- InitMouseEvent(WebInputEvent::MouseUp, WebMouseEvent::ButtonRight, |
- last_mouse_pos_, &event); |
- webview()->handleInputEvent(event); |
- |
- pressed_button_ = WebMouseEvent::ButtonNone; |
- |
- result->Set(WebKit::WebBindings::makeStringArray( |
- MakeMenuItemStringsFor( |
- shell_->delegate()->last_context_menu_data(), |
- shell_->delegate()->mock_spellcheck()))); |
- |
-} |
- |
-void EventSendingController::scheduleAsynchronousClick( |
- const CppArgumentList& args, CppVariant* result) { |
- result->SetNull(); |
- |
- MessageLoop::current()->PostTask(FROM_HERE, |
- method_factory_.NewRunnableMethod(&EventSendingController::mouseDown, |
- args, static_cast<CppVariant*>(NULL))); |
- MessageLoop::current()->PostTask(FROM_HERE, |
- method_factory_.NewRunnableMethod(&EventSendingController::mouseUp, |
- args, static_cast<CppVariant*>(NULL))); |
-} |
- |
-void EventSendingController::beginDragWithFiles( |
- const CppArgumentList& args, CppVariant* result) { |
- current_drag_data.initialize(); |
- std::vector<std::string> files = args[0].ToStringVector(); |
- for (size_t i = 0; i < files.size(); ++i) { |
- std::wstring file = UTF8ToWide(files[i]); |
- FilePath file_path = FilePath::FromWStringHack(file); |
- file_util::AbsolutePath(&file_path); |
- current_drag_data.appendToFilenames( |
- webkit_glue::FilePathStringToWebString(file_path.value())); |
- } |
- current_drag_effects_allowed = WebKit::WebDragOperationCopy; |
- |
- // Provide a drag source. |
- WebPoint client_point(last_mouse_pos_.x(), last_mouse_pos_.y()); |
- WebPoint screen_point(last_mouse_pos_.x(), last_mouse_pos_.y()); |
- webview()->dragTargetDragEnter( |
- current_drag_data, 0, client_point, screen_point, |
- current_drag_effects_allowed); |
- |
- // dragMode saves events and then replays them later. We don't need/want that. |
- dragMode.Set(false); |
- |
- // Make the rest of eventSender think a drag is in progress. |
- pressed_button_ = WebMouseEvent::ButtonLeft; |
- |
- result->SetNull(); |
-} |
- |
-void EventSendingController::addTouchPoint( |
- const CppArgumentList& args, CppVariant* result) { |
- result->SetNull(); |
- |
- WebTouchPoint touch_point; |
- touch_point.state = WebTouchPoint::StatePressed; |
- touch_point.position = WebPoint(args[0].ToInt32(), args[1].ToInt32()); |
- touch_point.screenPosition = touch_point.position; |
- touch_point.id = touch_points.size(); |
- touch_points.push_back(touch_point); |
-} |
- |
-void EventSendingController::clearTouchPoints( |
- const CppArgumentList& args, CppVariant* result) { |
- result->SetNull(); |
- |
- touch_points.clear(); |
-} |
- |
-void EventSendingController::releaseTouchPoint( |
- const CppArgumentList& args, CppVariant* result) { |
- result->SetNull(); |
- |
- const unsigned int index = args[0].ToInt32(); |
- if (index >= touch_points.size()) { |
- NOTREACHED() << "Invalid touch point index"; |
- } |
- |
- WebTouchPoint* touch_point = &touch_points[index]; |
- touch_point->state = WebTouchPoint::StateReleased; |
-} |
- |
-void EventSendingController::setTouchModifier( |
- const CppArgumentList& args, CppVariant* result) { |
- result->SetNull(); |
- |
- int mask = 0; |
- const std::string key_name = args[0].ToString(); |
- if (key_name == "shift") { |
- mask = WebInputEvent::ShiftKey; |
- } else if (key_name == "alt") { |
- mask = WebInputEvent::AltKey; |
- } else if (key_name == "ctrl") { |
- mask = WebInputEvent::ControlKey; |
- } else if (key_name == "meta") { |
- mask = WebInputEvent::MetaKey; |
- } |
- |
- if (args[1].ToBoolean() == true) { |
- touch_modifiers |= mask; |
- } else { |
- touch_modifiers &= ~mask; |
- } |
-} |
- |
-void EventSendingController::updateTouchPoint( |
- const CppArgumentList& args, CppVariant* result) { |
- result->SetNull(); |
- |
- const unsigned int index = args[0].ToInt32(); |
- if (index >= touch_points.size()) { |
- NOTREACHED() << "Invalid touch point index"; |
- } |
- |
- WebPoint position(args[1].ToInt32(), args[2].ToInt32()); |
- |
- WebTouchPoint* touch_point = &touch_points[index]; |
- touch_point->state = WebTouchPoint::StateMoved; |
- touch_point->position = position; |
- touch_point->screenPosition = position; |
-} |
- |
-void EventSendingController::cancelTouchPoint( |
- const CppArgumentList& args, CppVariant* result) { |
- result->SetNull(); |
- |
- const unsigned int index = args[0].ToInt32(); |
- if (index >= touch_points.size()) { |
- NOTREACHED() << "Invalid touch point index"; |
- } |
- |
- WebTouchPoint* touch_point = &touch_points[index]; |
- touch_point->state = WebTouchPoint::StateCancelled; |
-} |
- |
-void EventSendingController::SendCurrentTouchEvent( |
- const WebInputEvent::Type type) { |
- webview()->layout(); |
- |
- if (static_cast<unsigned int>(WebTouchEvent::touchPointsLengthCap) <= |
- touch_points.size()) { |
- NOTREACHED() << "Too many touch points for event"; |
- } |
- |
- WebTouchEvent touch_event; |
- touch_event.type = type; |
- touch_event.modifiers = touch_modifiers; |
- touch_event.timeStampSeconds = GetCurrentEventTimeSec(); |
- touch_event.touchPointsLength = touch_points.size(); |
- for (unsigned int i = 0; i < touch_points.size(); ++i) { |
- touch_event.touchPoints[i] = touch_points[i]; |
- } |
- webview()->handleInputEvent(touch_event); |
- |
- std::vector<WebTouchPoint>::iterator i = touch_points.begin(); |
- while (i != touch_points.end()) { |
- WebTouchPoint* touch_point = &(*i); |
- if (touch_point->state == WebTouchPoint::StateReleased) { |
- i = touch_points.erase(i); |
- } else { |
- touch_point->state = WebTouchPoint::StateStationary; |
- ++i; |
- } |
- } |
-} |
- |
-void EventSendingController::handleMouseWheel(const CppArgumentList& args, |
- CppVariant* result, |
- bool continuous) { |
- result->SetNull(); |
- |
- if (args.size() < 2 || !args[0].isNumber() || !args[1].isNumber()) |
- return; |
- |
- // Force a layout here just to make sure every position has been |
- // determined before we send events (as well as all the other methods |
- // that send an event do). |
- webview()->layout(); |
- |
- int horizontal = args[0].ToInt32(); |
- int vertical = args[1].ToInt32(); |
- |
- WebMouseWheelEvent event; |
- InitMouseEvent(WebInputEvent::MouseWheel, pressed_button_, last_mouse_pos_, |
- &event); |
- event.wheelTicksX = static_cast<float>(horizontal); |
- event.wheelTicksY = static_cast<float>(vertical); |
- event.deltaX = event.wheelTicksX; |
- event.deltaY = event.wheelTicksY; |
- if (continuous) { |
- event.wheelTicksX /= kScrollbarPixelsPerTick; |
- event.wheelTicksY /= kScrollbarPixelsPerTick; |
- } else { |
- event.deltaX *= kScrollbarPixelsPerTick; |
- event.deltaY *= kScrollbarPixelsPerTick; |
- } |
- webview()->handleInputEvent(event); |
-} |
- |
-void EventSendingController::touchEnd( |
- const CppArgumentList& args, CppVariant* result) { |
- result->SetNull(); |
- SendCurrentTouchEvent(WebInputEvent::TouchEnd); |
-} |
- |
-void EventSendingController::touchMove( |
- const CppArgumentList& args, CppVariant* result) { |
- result->SetNull(); |
- SendCurrentTouchEvent(WebInputEvent::TouchMove); |
-} |
- |
-void EventSendingController::touchStart( |
- const CppArgumentList& args, CppVariant* result) { |
- result->SetNull(); |
- SendCurrentTouchEvent(WebInputEvent::TouchStart); |
-} |
- |
-void EventSendingController::touchCancel( |
- const CppArgumentList& args, CppVariant* result) { |
- result->SetNull(); |
- SendCurrentTouchEvent(WebInputEvent::TouchCancel); |
-} |
- |
-// |
-// Unimplemented stubs |
-// |
- |
-void EventSendingController::enableDOMUIEventLogging( |
- const CppArgumentList& args, CppVariant* result) { |
- result->SetNull(); |
-} |
- |
-void EventSendingController::fireKeyboardEventsToElement( |
- const CppArgumentList& args, CppVariant* result) { |
- result->SetNull(); |
-} |
- |
-void EventSendingController::clearKillRing( |
- const CppArgumentList& args, CppVariant* result) { |
- result->SetNull(); |
-} |