This source file includes following definitions.
- InitMouseEvent
- GetKeyModifier
- GetKeyModifiers
- GetKeyModifiersFromV8
- OutsideMultiClickRadius
- MakeMenuItemStringsFor
- GetButtonTypeFromButtonNumber
- modifiers_
- runIfValid
- modifiers_
- runIfValid
- location_
- runIfValid
- NeedsShiftModifier
- GetEditCommand
- Install
- GetObjectTemplateBuilder
- EnableDOMUIEventLogging
- FireKeyboardEventsToElement
- ClearKillRing
- ContextClick
- TextZoomIn
- TextZoomOut
- ZoomPageIn
- ZoomPageOut
- SetPageScaleFactor
- ClearTouchPoints
- ReleaseTouchPoint
- UpdateTouchPoint
- CancelTouchPoint
- SetTouchModifier
- DumpFilenameBeingDragged
- GestureFlingCancel
- GestureFlingStart
- GestureScrollFirstPoint
- TouchStart
- TouchMove
- TouchCancel
- TouchEnd
- LeapForward
- BeginDragWithFiles
- AddTouchPoint
- MouseDragBegin
- MouseDragEnd
- MouseMomentumBegin
- GestureScrollBegin
- GestureScrollEnd
- GestureScrollUpdate
- GestureScrollUpdateWithoutPropagation
- GestureTap
- GestureTapDown
- GestureShowPress
- GestureTapCancel
- GestureLongPress
- GestureLongTap
- GestureTwoFingerTap
- ContinuousMouseScrollBy
- DispatchMessage
- MouseMoveTo
- MouseScrollBy
- MouseMomentumScrollBy
- MouseMomentumEnd
- ScheduleAsynchronousClick
- ScheduleAsynchronousKeyDown
- MouseDown
- MouseUp
- KeyDown
- ForceLayoutOnEvents
- SetForceLayoutOnEvents
- IsDragMode
- SetIsDragMode
- WmKeyDown
- SetWmKeyDown
- WmKeyUp
- SetWmKeyUp
- WmChar
- SetWmChar
- WmDeadChar
- SetWmDeadChar
- WmSysKeyDown
- SetWmSysKeyDown
- WmSysKeyUp
- SetWmSysKeyUp
- WmSysChar
- SetWmSysChar
- WmSysDeadChar
- SetWmSysDeadChar
- modifiers
- weak_factory_
- Reset
- Install
- SetDelegate
- SetWebView
- SetContextMenuData
- DoDragDrop
- MouseDown
- MouseUp
- KeyDown
- EnableDOMUIEventLogging
- FireKeyboardEventsToElement
- ClearKillRing
- ContextClick
- TextZoomIn
- TextZoomOut
- ZoomPageIn
- ZoomPageOut
- SetPageScaleFactor
- ClearTouchPoints
- ReleaseTouchPoint
- UpdateTouchPoint
- CancelTouchPoint
- SetTouchModifier
- DumpFilenameBeingDragged
- GestureFlingCancel
- GestureFlingStart
- GestureScrollFirstPoint
- TouchStart
- TouchMove
- TouchCancel
- TouchEnd
- LeapForward
- BeginDragWithFiles
- AddTouchPoint
- MouseDragBegin
- MouseDragEnd
- MouseMomentumBegin
- GestureScrollBegin
- GestureScrollEnd
- GestureScrollUpdate
- GestureScrollUpdateWithoutPropagation
- GestureTap
- GestureTapDown
- GestureShowPress
- GestureTapCancel
- GestureLongPress
- GestureLongTap
- GestureTwoFingerTap
- ContinuousMouseScrollBy
- DispatchMessage
- MouseMoveTo
- MouseScrollBy
- MouseMomentumScrollBy
- MouseMomentumEnd
- ScheduleAsynchronousClick
- ScheduleAsynchronousKeyDown
- GetCurrentEventTimeSec
- DoLeapForward
- SendCurrentTouchEvent
- GestureEvent
- UpdateClickCountForButton
- InitMouseWheelEvent
- FinishDragAndDrop
- DoMouseUp
- DoMouseMove
- ReplaySavedEvents
#include "content/shell/renderer/test_runner/event_sender.h"
#include "base/basictypes.h"
#include "base/logging.h"
#include "base/strings/stringprintf.h"
#include "content/shell/renderer/test_runner/KeyCodeMapping.h"
#include "content/shell/renderer/test_runner/MockSpellCheck.h"
#include "content/shell/renderer/test_runner/TestInterfaces.h"
#include "content/shell/renderer/test_runner/WebTestDelegate.h"
#include "content/shell/renderer/test_runner/WebTestProxy.h"
#include "gin/handle.h"
#include "gin/object_template_builder.h"
#include "gin/wrappable.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/platform/WebVector.h"
#include "third_party/WebKit/public/web/WebContextMenuData.h"
#include "third_party/WebKit/public/web/WebFrame.h"
#include "third_party/WebKit/public/web/WebKit.h"
#include "third_party/WebKit/public/web/WebView.h"
#include "v8/include/v8.h"
#if defined(OS_WIN)
#include "third_party/WebKit/public/web/win/WebInputEventFactory.h"
#elif defined(OS_MACOSX)
#include "third_party/WebKit/public/web/mac/WebInputEventFactory.h"
#elif defined(OS_ANDROID)
#include "third_party/WebKit/public/web/android/WebInputEventFactory.h"
#elif defined(TOOLKIT_GTK)
#include "third_party/WebKit/public/web/gtk/WebInputEventFactory.h"
#endif
using blink::WebContextMenuData;
using blink::WebDragData;
using blink::WebDragOperationsMask;
using blink::WebFloatPoint;
using blink::WebFrame;
using blink::WebGestureEvent;
using blink::WebInputEvent;
using blink::WebKeyboardEvent;
using blink::WebMouseEvent;
using blink::WebMouseWheelEvent;
using blink::WebPoint;
using blink::WebString;
using blink::WebTouchEvent;
using blink::WebTouchPoint;
using blink::WebVector;
using blink::WebView;
#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_ANDROID) || \
defined(TOOLKIT_GTK)
using blink::WebInputEventFactory;
#endif
namespace content {
namespace {
void InitMouseEvent(WebInputEvent::Type t,
WebMouseEvent::Button b,
const WebPoint& pos,
double time_stamp,
int click_count,
int modifiers,
WebMouseEvent* e) {
e->type = t;
e->button = b;
e->modifiers = modifiers;
e->x = pos.x;
e->y = pos.y;
e->globalX = pos.x;
e->globalY = pos.y;
e->timeStampSeconds = time_stamp;
e->clickCount = click_count;
}
int GetKeyModifier(const std::string& modifier_name) {
const char* characters = modifier_name.c_str();
if (!strcmp(characters, "ctrlKey")
#ifndef __APPLE__
|| !strcmp(characters, "addSelectionKey")
#endif
) {
return WebInputEvent::ControlKey;
} else if (!strcmp(characters, "shiftKey") ||
!strcmp(characters, "rangeSelectionKey")) {
return WebInputEvent::ShiftKey;
} else if (!strcmp(characters, "altKey")) {
return WebInputEvent::AltKey;
#ifdef __APPLE__
} else if (!strcmp(characters, "metaKey") ||
!strcmp(characters, "addSelectionKey")) {
return WebInputEvent::MetaKey;
#else
} else if (!strcmp(characters, "metaKey")) {
return WebInputEvent::MetaKey;
#endif
} else if (!strcmp(characters, "autoRepeat")) {
return WebInputEvent::IsAutoRepeat;
} else if (!strcmp(characters, "copyKey")) {
#ifdef __APPLE__
return WebInputEvent::AltKey;
#else
return WebInputEvent::ControlKey;
#endif
}
return 0;
}
int GetKeyModifiers(const std::vector<std::string>& modifier_names) {
int modifiers = 0;
for (std::vector<std::string>::const_iterator it = modifier_names.begin();
it != modifier_names.end(); ++it) {
modifiers |= GetKeyModifier(*it);
}
return modifiers;
}
int GetKeyModifiersFromV8(v8::Handle<v8::Value> value) {
std::vector<std::string> modifier_names;
if (value->IsString()) {
modifier_names.push_back(gin::V8ToString(value));
} else if (value->IsArray()) {
gin::Converter<std::vector<std::string> >::FromV8(
NULL, value, &modifier_names);
}
return GetKeyModifiers(modifier_names);
}
const double kMultipleClickTimeSec = 1;
const int kMultipleClickRadiusPixels = 5;
bool OutsideMultiClickRadius(const WebPoint& a, const WebPoint& b) {
return ((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)) >
kMultipleClickRadiusPixels * kMultipleClickRadiusPixels;
}
std::vector<std::string> MakeMenuItemStringsFor(
WebContextMenuData* context_menu,
WebTestRunner::WebTestDelegate* delegate) {
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
};
if (!context_menu)
return std::vector<std::string>();
std::vector<std::string> strings;
if (context_menu->isEditable) {
for (const char** item = kEditableMenuStrings; *item; ++item) {
strings.push_back(*item);
}
WebVector<WebString> suggestions;
WebTestRunner::MockSpellCheck::fillSuggestionList(
context_menu->misspelledWord, &suggestions);
for (size_t i = 0; i < suggestions.size(); ++i) {
strings.push_back(suggestions[i].utf8());
}
} else {
for (const char** item = kNonEditableMenuStrings; *item; ++item) {
strings.push_back(*item);
}
}
return strings;
}
const float kScrollbarPixelsPerTick = 40.0f;
WebMouseEvent::Button GetButtonTypeFromButtonNumber(int button_code) {
if (!button_code)
return WebMouseEvent::ButtonLeft;
if (button_code == 2)
return WebMouseEvent::ButtonRight;
return WebMouseEvent::ButtonMiddle;
}
class MouseDownTask : public WebTestRunner::WebMethodTask<EventSender> {
public:
MouseDownTask(EventSender* obj, int button_number, int modifiers)
: WebMethodTask<EventSender>(obj),
button_number_(button_number),
modifiers_(modifiers) {}
virtual void runIfValid() OVERRIDE {
m_object->MouseDown(button_number_, modifiers_);
}
private:
int button_number_;
int modifiers_;
};
class MouseUpTask : public WebTestRunner::WebMethodTask<EventSender> {
public:
MouseUpTask(EventSender* obj, int button_number, int modifiers)
: WebMethodTask<EventSender>(obj),
button_number_(button_number),
modifiers_(modifiers) {}
virtual void runIfValid() OVERRIDE {
m_object->MouseUp(button_number_, modifiers_);
}
private:
int button_number_;
int modifiers_;
};
class KeyDownTask : public WebTestRunner::WebMethodTask<EventSender> {
public:
KeyDownTask(EventSender* obj,
const std::string code_str,
int modifiers,
KeyLocationCode location)
: WebMethodTask<EventSender>(obj),
code_str_(code_str),
modifiers_(modifiers),
location_(location) {}
virtual void runIfValid() OVERRIDE {
m_object->KeyDown(code_str_, modifiers_, location_);
}
private:
std::string code_str_;
int modifiers_;
KeyLocationCode location_;
};
bool NeedsShiftModifier(int keyCode) {
return (keyCode & 0xFF) >= 'A' && (keyCode & 0xFF) <= 'Z';
}
bool GetEditCommand(const WebKeyboardEvent& event, std::string* name) {
#if defined(OS_MACOSX)
if ((event.modifiers & ~WebKeyboardEvent::ShiftKey) !=
WebKeyboardEvent::MetaKey)
return false;
switch (event.windowsKeyCode) {
case WebTestRunner::VKEY_LEFT:
*name = "MoveToBeginningOfLine";
break;
case WebTestRunner::VKEY_RIGHT:
*name = "MoveToEndOfLine";
break;
case WebTestRunner::VKEY_UP:
*name = "MoveToBeginningOfDocument";
break;
case WebTestRunner::VKEY_DOWN:
*name = "MoveToEndOfDocument";
break;
default:
return false;
}
if (event.modifiers & WebKeyboardEvent::ShiftKey)
name->append("AndModifySelection");
return true;
#else
return false;
#endif
}
}
class EventSenderBindings : public gin::Wrappable<EventSenderBindings> {
public:
static gin::WrapperInfo kWrapperInfo;
static void Install(base::WeakPtr<EventSender> sender,
blink::WebFrame* frame);
private:
explicit EventSenderBindings(base::WeakPtr<EventSender> sender);
virtual ~EventSenderBindings();
virtual gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
v8::Isolate* isolate) OVERRIDE;
void EnableDOMUIEventLogging();
void FireKeyboardEventsToElement();
void ClearKillRing();
std::vector<std::string> ContextClick();
void TextZoomIn();
void TextZoomOut();
void ZoomPageIn();
void ZoomPageOut();
void SetPageScaleFactor(gin::Arguments* args);
void ClearTouchPoints();
void ReleaseTouchPoint(unsigned index);
void UpdateTouchPoint(unsigned index, int x, int y);
void CancelTouchPoint(unsigned index);
void SetTouchModifier(const std::string& key_name, bool set_mask);
void DumpFilenameBeingDragged();
void GestureFlingCancel();
void GestureFlingStart(float x, float y, float velocity_x, float velocity_y);
void GestureScrollFirstPoint(int x, int y);
void TouchStart();
void TouchMove();
void TouchCancel();
void TouchEnd();
void LeapForward(int milliseconds);
void BeginDragWithFiles(const std::vector<std::string>& files);
void AddTouchPoint(gin::Arguments* args);
void MouseDragBegin();
void MouseDragEnd();
void MouseMomentumBegin();
void GestureScrollBegin(gin::Arguments* args);
void GestureScrollEnd(gin::Arguments* args);
void GestureScrollUpdate(gin::Arguments* args);
void GestureScrollUpdateWithoutPropagation(gin::Arguments* args);
void GestureTap(gin::Arguments* args);
void GestureTapDown(gin::Arguments* args);
void GestureShowPress(gin::Arguments* args);
void GestureTapCancel(gin::Arguments* args);
void GestureLongPress(gin::Arguments* args);
void GestureLongTap(gin::Arguments* args);
void GestureTwoFingerTap(gin::Arguments* args);
void ContinuousMouseScrollBy(gin::Arguments* args);
void DispatchMessage(int msg, int wparam, int lparam);
void MouseMoveTo(gin::Arguments* args);
void MouseScrollBy(gin::Arguments* args);
void MouseMomentumScrollBy(gin::Arguments* args);
void MouseMomentumEnd();
void ScheduleAsynchronousClick(gin::Arguments* args);
void ScheduleAsynchronousKeyDown(gin::Arguments* args);
void MouseDown(gin::Arguments* args);
void MouseUp(gin::Arguments* args);
void KeyDown(gin::Arguments* args);
bool ForceLayoutOnEvents() const;
void SetForceLayoutOnEvents(bool force);
bool IsDragMode() const;
void SetIsDragMode(bool drag_mode);
#if defined(OS_WIN)
int WmKeyDown() const;
void SetWmKeyDown(int key_down);
int WmKeyUp() const;
void SetWmKeyUp(int key_up);
int WmChar() const;
void SetWmChar(int wm_char);
int WmDeadChar() const;
void SetWmDeadChar(int dead_char);
int WmSysKeyDown() const;
void SetWmSysKeyDown(int key_down);
int WmSysKeyUp() const;
void SetWmSysKeyUp(int key_up);
int WmSysChar() const;
void SetWmSysChar(int sys_char);
int WmSysDeadChar() const;
void SetWmSysDeadChar(int sys_dead_char);
#endif
base::WeakPtr<EventSender> sender_;
DISALLOW_COPY_AND_ASSIGN(EventSenderBindings);
};
gin::WrapperInfo EventSenderBindings::kWrapperInfo = {gin::kEmbedderNativeGin};
EventSenderBindings::EventSenderBindings(base::WeakPtr<EventSender> sender)
: sender_(sender) {
}
EventSenderBindings::~EventSenderBindings() {}
void EventSenderBindings::Install(base::WeakPtr<EventSender> sender,
WebFrame* frame) {
v8::Isolate* isolate = blink::mainThreadIsolate();
v8::HandleScope handle_scope(isolate);
v8::Handle<v8::Context> context = frame->mainWorldScriptContext();
if (context.IsEmpty())
return;
v8::Context::Scope context_scope(context);
gin::Handle<EventSenderBindings> bindings =
gin::CreateHandle(isolate, new EventSenderBindings(sender));
v8::Handle<v8::Object> global = context->Global();
global->Set(gin::StringToV8(isolate, "eventSender"), bindings.ToV8());
}
gin::ObjectTemplateBuilder
EventSenderBindings::GetObjectTemplateBuilder(v8::Isolate* isolate) {
return gin::Wrappable<EventSenderBindings>::GetObjectTemplateBuilder(isolate)
.SetMethod("enableDOMUIEventLogging",
&EventSenderBindings::EnableDOMUIEventLogging)
.SetMethod("fireKeyboardEventsToElement",
&EventSenderBindings::FireKeyboardEventsToElement)
.SetMethod("clearKillRing", &EventSenderBindings::ClearKillRing)
.SetMethod("contextClick", &EventSenderBindings::ContextClick)
.SetMethod("textZoomIn", &EventSenderBindings::TextZoomIn)
.SetMethod("textZoomOut", &EventSenderBindings::TextZoomOut)
.SetMethod("zoomPageIn", &EventSenderBindings::ZoomPageIn)
.SetMethod("zoomPageOut", &EventSenderBindings::ZoomPageOut)
.SetMethod("setPageScaleFactor", &EventSenderBindings::SetPageScaleFactor)
.SetMethod("clearTouchPoints", &EventSenderBindings::ClearTouchPoints)
.SetMethod("releaseTouchPoint", &EventSenderBindings::ReleaseTouchPoint)
.SetMethod("updateTouchPoint", &EventSenderBindings::UpdateTouchPoint)
.SetMethod("cancelTouchPoint", &EventSenderBindings::CancelTouchPoint)
.SetMethod("setTouchModifier", &EventSenderBindings::SetTouchModifier)
.SetMethod("dumpFilenameBeingDragged",
&EventSenderBindings::DumpFilenameBeingDragged)
.SetMethod("gestureFlingCancel", &EventSenderBindings::GestureFlingCancel)
.SetMethod("gestureFlingStart", &EventSenderBindings::GestureFlingStart)
.SetMethod("gestureScrollFirstPoint",
&EventSenderBindings::GestureScrollFirstPoint)
.SetMethod("touchStart", &EventSenderBindings::TouchStart)
.SetMethod("touchMove", &EventSenderBindings::TouchMove)
.SetMethod("touchCancel", &EventSenderBindings::TouchCancel)
.SetMethod("touchEnd", &EventSenderBindings::TouchEnd)
.SetMethod("leapForward", &EventSenderBindings::LeapForward)
.SetMethod("beginDragWithFiles", &EventSenderBindings::BeginDragWithFiles)
.SetMethod("addTouchPoint", &EventSenderBindings::AddTouchPoint)
.SetMethod("mouseDragBegin", &EventSenderBindings::MouseDragBegin)
.SetMethod("mouseDragEnd", &EventSenderBindings::MouseDragEnd)
.SetMethod("mouseMomentumBegin", &EventSenderBindings::MouseMomentumBegin)
.SetMethod("gestureScrollBegin", &EventSenderBindings::GestureScrollBegin)
.SetMethod("gestureScrollEnd", &EventSenderBindings::GestureScrollEnd)
.SetMethod("gestureScrollUpdate",
&EventSenderBindings::GestureScrollUpdate)
.SetMethod("gestureScrollUpdateWithoutPropagation",
&EventSenderBindings::GestureScrollUpdateWithoutPropagation)
.SetMethod("gestureTap", &EventSenderBindings::GestureTap)
.SetMethod("gestureTapDown", &EventSenderBindings::GestureTapDown)
.SetMethod("gestureShowPress", &EventSenderBindings::GestureShowPress)
.SetMethod("gestureTapCancel", &EventSenderBindings::GestureTapCancel)
.SetMethod("gestureLongPress", &EventSenderBindings::GestureLongPress)
.SetMethod("gestureLongTap", &EventSenderBindings::GestureLongTap)
.SetMethod("gestureTwoFingerTap",
&EventSenderBindings::GestureTwoFingerTap)
.SetMethod("continuousMouseScrollBy",
&EventSenderBindings::ContinuousMouseScrollBy)
.SetMethod("dispatchMessage", &EventSenderBindings::DispatchMessage)
.SetMethod("keyDown", &EventSenderBindings::KeyDown)
.SetMethod("mouseDown", &EventSenderBindings::MouseDown)
.SetMethod("mouseMoveTo", &EventSenderBindings::MouseMoveTo)
.SetMethod("mouseScrollBy", &EventSenderBindings::MouseScrollBy)
.SetMethod("mouseUp", &EventSenderBindings::MouseUp)
.SetMethod("mouseMomentumScrollBy",
&EventSenderBindings::MouseMomentumScrollBy)
.SetMethod("mouseMomentumEnd", &EventSenderBindings::MouseMomentumEnd)
.SetMethod("scheduleAsynchronousClick",
&EventSenderBindings::ScheduleAsynchronousClick)
.SetMethod("scheduleAsynchronousKeyDown",
&EventSenderBindings::ScheduleAsynchronousKeyDown)
.SetProperty("forceLayoutOnEvents",
&EventSenderBindings::ForceLayoutOnEvents,
&EventSenderBindings::SetForceLayoutOnEvents)
.SetProperty("dragMode",
&EventSenderBindings::IsDragMode,
&EventSenderBindings::SetIsDragMode)
#if defined(OS_WIN)
.SetProperty("WM_KEYDOWN",
&EventSenderBindings::WmKeyDown,
&EventSenderBindings::SetWmKeyDown)
.SetProperty("WM_KEYUP",
&EventSenderBindings::WmKeyUp,
&EventSenderBindings::SetWmKeyUp)
.SetProperty("WM_CHAR",
&EventSenderBindings::WmChar,
&EventSenderBindings::SetWmChar)
.SetProperty("WM_DEADCHAR",
&EventSenderBindings::WmDeadChar,
&EventSenderBindings::SetWmDeadChar)
.SetProperty("WM_SYSKEYDOWN",
&EventSenderBindings::WmSysKeyDown,
&EventSenderBindings::SetWmSysKeyDown)
.SetProperty("WM_SYSKEYUP",
&EventSenderBindings::WmSysKeyUp,
&EventSenderBindings::SetWmSysKeyUp)
.SetProperty("WM_SYSCHAR",
&EventSenderBindings::WmSysChar,
&EventSenderBindings::SetWmSysChar)
.SetProperty("WM_SYSDEADCHAR",
&EventSenderBindings::WmSysDeadChar,
&EventSenderBindings::SetWmSysDeadChar);
#else
;
#endif
}
void EventSenderBindings::EnableDOMUIEventLogging() {
if (sender_)
sender_->EnableDOMUIEventLogging();
}
void EventSenderBindings::FireKeyboardEventsToElement() {
if (sender_)
sender_->FireKeyboardEventsToElement();
}
void EventSenderBindings::ClearKillRing() {
if (sender_)
sender_->ClearKillRing();
}
std::vector<std::string> EventSenderBindings::ContextClick() {
if (sender_)
return sender_->ContextClick();
return std::vector<std::string>();
}
void EventSenderBindings::TextZoomIn() {
if (sender_)
sender_->TextZoomIn();
}
void EventSenderBindings::TextZoomOut() {
if (sender_)
sender_->TextZoomOut();
}
void EventSenderBindings::ZoomPageIn() {
if (sender_)
sender_->ZoomPageIn();
}
void EventSenderBindings::ZoomPageOut() {
if (sender_)
sender_->ZoomPageOut();
}
void EventSenderBindings::SetPageScaleFactor(gin::Arguments* args) {
if (!sender_)
return;
float scale_factor;
int x;
int y;
if (args->PeekNext().IsEmpty())
return;
args->GetNext(&scale_factor);
if (args->PeekNext().IsEmpty())
return;
args->GetNext(&x);
if (args->PeekNext().IsEmpty())
return;
args->GetNext(&y);
sender_->SetPageScaleFactor(scale_factor, x, y);
}
void EventSenderBindings::ClearTouchPoints() {
if (sender_)
sender_->ClearTouchPoints();
}
void EventSenderBindings::ReleaseTouchPoint(unsigned index) {
if (sender_)
sender_->ReleaseTouchPoint(index);
}
void EventSenderBindings::UpdateTouchPoint(unsigned index, int x, int y) {
if (sender_)
sender_->UpdateTouchPoint(index, x, y);
}
void EventSenderBindings::CancelTouchPoint(unsigned index) {
if (sender_)
sender_->CancelTouchPoint(index);
}
void EventSenderBindings::SetTouchModifier(const std::string& key_name,
bool set_mask) {
if (sender_)
sender_->SetTouchModifier(key_name, set_mask);
}
void EventSenderBindings::DumpFilenameBeingDragged() {
if (sender_)
sender_->DumpFilenameBeingDragged();
}
void EventSenderBindings::GestureFlingCancel() {
if (sender_)
sender_->GestureFlingCancel();
}
void EventSenderBindings::GestureFlingStart(float x,
float y,
float velocity_x,
float velocity_y) {
if (sender_)
sender_->GestureFlingStart(x, y, velocity_x, velocity_y);
}
void EventSenderBindings::GestureScrollFirstPoint(int x, int y) {
if (sender_)
sender_->GestureScrollFirstPoint(x, y);
}
void EventSenderBindings::TouchStart() {
if (sender_)
sender_->TouchStart();
}
void EventSenderBindings::TouchMove() {
if (sender_)
sender_->TouchMove();
}
void EventSenderBindings::TouchCancel() {
if (sender_)
sender_->TouchCancel();
}
void EventSenderBindings::TouchEnd() {
if (sender_)
sender_->TouchEnd();
}
void EventSenderBindings::LeapForward(int milliseconds) {
if (sender_)
sender_->LeapForward(milliseconds);
}
void EventSenderBindings::BeginDragWithFiles(
const std::vector<std::string>& files) {
if (sender_)
sender_->BeginDragWithFiles(files);
}
void EventSenderBindings::AddTouchPoint(gin::Arguments* args) {
if (sender_)
sender_->AddTouchPoint(args);
}
void EventSenderBindings::MouseDragBegin() {
if (sender_)
sender_->MouseDragBegin();
}
void EventSenderBindings::MouseDragEnd() {
if (sender_)
sender_->MouseDragEnd();
}
void EventSenderBindings::MouseMomentumBegin() {
if (sender_)
sender_->MouseMomentumBegin();
}
void EventSenderBindings::GestureScrollBegin(gin::Arguments* args) {
if (sender_)
sender_->GestureScrollBegin(args);
}
void EventSenderBindings::GestureScrollEnd(gin::Arguments* args) {
if (sender_)
sender_->GestureScrollEnd(args);
}
void EventSenderBindings::GestureScrollUpdate(gin::Arguments* args) {
if (sender_)
sender_->GestureScrollUpdate(args);
}
void EventSenderBindings::GestureScrollUpdateWithoutPropagation(
gin::Arguments* args) {
if (sender_)
sender_->GestureScrollUpdateWithoutPropagation(args);
}
void EventSenderBindings::GestureTap(gin::Arguments* args) {
if (sender_)
sender_->GestureTap(args);
}
void EventSenderBindings::GestureTapDown(gin::Arguments* args) {
if (sender_)
sender_->GestureTapDown(args);
}
void EventSenderBindings::GestureShowPress(gin::Arguments* args) {
if (sender_)
sender_->GestureShowPress(args);
}
void EventSenderBindings::GestureTapCancel(gin::Arguments* args) {
if (sender_)
sender_->GestureTapCancel(args);
}
void EventSenderBindings::GestureLongPress(gin::Arguments* args) {
if (sender_)
sender_->GestureLongPress(args);
}
void EventSenderBindings::GestureLongTap(gin::Arguments* args) {
if (sender_)
sender_->GestureLongTap(args);
}
void EventSenderBindings::GestureTwoFingerTap(gin::Arguments* args) {
if (sender_)
sender_->GestureTwoFingerTap(args);
}
void EventSenderBindings::ContinuousMouseScrollBy(gin::Arguments* args) {
if (sender_)
sender_->ContinuousMouseScrollBy(args);
}
void EventSenderBindings::DispatchMessage(int msg, int wparam, int lparam) {
if (sender_)
sender_->DispatchMessage(msg, wparam, lparam);
}
void EventSenderBindings::MouseMoveTo(gin::Arguments* args) {
if (sender_)
sender_->MouseMoveTo(args);
}
void EventSenderBindings::MouseScrollBy(gin::Arguments* args) {
if (sender_)
sender_->MouseScrollBy(args);
}
void EventSenderBindings::MouseMomentumScrollBy(gin::Arguments* args) {
if (sender_)
sender_->MouseMomentumScrollBy(args);
}
void EventSenderBindings::MouseMomentumEnd() {
if (sender_)
sender_->MouseMomentumEnd();
}
void EventSenderBindings::ScheduleAsynchronousClick(gin::Arguments* args) {
if (!sender_)
return;
int button_number = 0;
int modifiers = 0;
if (!args->PeekNext().IsEmpty()) {
args->GetNext(&button_number);
if (!args->PeekNext().IsEmpty())
modifiers = GetKeyModifiersFromV8(args->PeekNext());
}
sender_->ScheduleAsynchronousClick(button_number, modifiers);
}
void EventSenderBindings::ScheduleAsynchronousKeyDown(gin::Arguments* args) {
if (!sender_)
return;
std::string code_str;
int modifiers = 0;
int location = DOMKeyLocationStandard;
args->GetNext(&code_str);
if (!args->PeekNext().IsEmpty()) {
v8::Handle<v8::Value> value;
args->GetNext(&value);
modifiers = GetKeyModifiersFromV8(value);
if (!args->PeekNext().IsEmpty())
args->GetNext(&location);
}
sender_->ScheduleAsynchronousKeyDown(code_str, modifiers,
static_cast<KeyLocationCode>(location));
}
void EventSenderBindings::MouseDown(gin::Arguments* args) {
if (!sender_)
return;
int button_number = 0;
int modifiers = 0;
if (!args->PeekNext().IsEmpty()) {
args->GetNext(&button_number);
if (!args->PeekNext().IsEmpty())
modifiers = GetKeyModifiersFromV8(args->PeekNext());
}
sender_->MouseDown(button_number, modifiers);
}
void EventSenderBindings::MouseUp(gin::Arguments* args) {
if (!sender_)
return;
int button_number = 0;
int modifiers = 0;
if (!args->PeekNext().IsEmpty()) {
args->GetNext(&button_number);
if (!args->PeekNext().IsEmpty())
modifiers = GetKeyModifiersFromV8(args->PeekNext());
}
sender_->MouseUp(button_number, modifiers);
}
void EventSenderBindings::KeyDown(gin::Arguments* args) {
if (!sender_)
return;
std::string code_str;
int modifiers = 0;
int location = DOMKeyLocationStandard;
args->GetNext(&code_str);
if (!args->PeekNext().IsEmpty()) {
v8::Handle<v8::Value> value;
args->GetNext(&value);
modifiers = GetKeyModifiersFromV8(value);
if (!args->PeekNext().IsEmpty())
args->GetNext(&location);
}
sender_->KeyDown(code_str, modifiers, static_cast<KeyLocationCode>(location));
}
bool EventSenderBindings::ForceLayoutOnEvents() const {
if (sender_)
return sender_->force_layout_on_events();
return false;
}
void EventSenderBindings::SetForceLayoutOnEvents(bool force) {
if (sender_)
sender_->set_force_layout_on_events(force);
}
bool EventSenderBindings::IsDragMode() const {
if (sender_)
return sender_->is_drag_mode();
return true;
}
void EventSenderBindings::SetIsDragMode(bool drag_mode) {
if (sender_)
sender_->set_is_drag_mode(drag_mode);
}
#if defined(OS_WIN)
int EventSenderBindings::WmKeyDown() const {
if (sender_)
return sender_->wm_key_down();
return 0;
}
void EventSenderBindings::SetWmKeyDown(int key_down) {
if (sender_)
sender_->set_wm_key_down(key_down);
}
int EventSenderBindings::WmKeyUp() const {
if (sender_)
return sender_->wm_key_up();
return 0;
}
void EventSenderBindings::SetWmKeyUp(int key_up) {
if (sender_)
sender_->set_wm_key_up(key_up);
}
int EventSenderBindings::WmChar() const {
if (sender_)
return sender_->wm_char();
return 0;
}
void EventSenderBindings::SetWmChar(int wm_char) {
if (sender_)
sender_->set_wm_char(wm_char);
}
int EventSenderBindings::WmDeadChar() const {
if (sender_)
return sender_->wm_dead_char();
return 0;
}
void EventSenderBindings::SetWmDeadChar(int dead_char) {
if (sender_)
sender_->set_wm_dead_char(dead_char);
}
int EventSenderBindings::WmSysKeyDown() const {
if (sender_)
return sender_->wm_sys_key_down();
return 0;
}
void EventSenderBindings::SetWmSysKeyDown(int key_down) {
if (sender_)
sender_->set_wm_sys_key_down(key_down);
}
int EventSenderBindings::WmSysKeyUp() const {
if (sender_)
return sender_->wm_sys_key_up();
return 0;
}
void EventSenderBindings::SetWmSysKeyUp(int key_up) {
if (sender_)
sender_->set_wm_sys_key_up(key_up);
}
int EventSenderBindings::WmSysChar() const {
if (sender_)
return sender_->wm_sys_char();
return 0;
}
void EventSenderBindings::SetWmSysChar(int sys_char) {
if (sender_)
sender_->set_wm_sys_char(sys_char);
}
int EventSenderBindings::WmSysDeadChar() const {
if (sender_)
return sender_->wm_sys_dead_char();
return 0;
}
void EventSenderBindings::SetWmSysDeadChar(int sys_dead_char) {
if (sender_)
sender_->set_wm_sys_dead_char(sys_dead_char);
}
#endif
WebMouseEvent::Button EventSender::pressed_button_ = WebMouseEvent::ButtonNone;
WebPoint EventSender::last_mouse_pos_;
WebMouseEvent::Button EventSender::last_button_type_ =
WebMouseEvent::ButtonNone;
EventSender::SavedEvent::SavedEvent()
: type(TYPE_UNSPECIFIED),
button_type(WebMouseEvent::ButtonNone),
milliseconds(0),
modifiers(0) {}
EventSender::EventSender(WebTestRunner::TestInterfaces* interfaces)
: interfaces_(interfaces),
delegate_(NULL),
view_(NULL),
force_layout_on_events_(false),
is_drag_mode_(true),
touch_modifiers_(0),
replaying_saved_events_(false),
current_drag_effects_allowed_(blink::WebDragOperationNone),
last_click_time_sec_(0),
current_drag_effect_(blink::WebDragOperationNone),
time_offset_ms_(0),
click_count_(0),
#if defined(OS_WIN)
wm_key_down_(0),
wm_key_up_(0),
wm_char_(0),
wm_dead_char_(0),
wm_sys_key_down_(0),
wm_sys_key_up_(0),
wm_sys_char_(0),
wm_sys_dead_char_(0),
#endif
weak_factory_(this) {}
EventSender::~EventSender() {}
void EventSender::Reset() {
DCHECK(current_drag_data_.isNull());
current_drag_data_.reset();
current_drag_effect_ = blink::WebDragOperationNone;
current_drag_effects_allowed_ = blink::WebDragOperationNone;
if (view_ && pressed_button_ != WebMouseEvent::ButtonNone)
view_->mouseCaptureLost();
pressed_button_ = WebMouseEvent::ButtonNone;
is_drag_mode_ = true;
force_layout_on_events_ = true;
#if defined(OS_WIN)
wm_key_down_ = WM_KEYDOWN;
wm_key_up_ = WM_KEYUP;
wm_char_ = WM_CHAR;
wm_dead_char_ = WM_DEADCHAR;
wm_sys_key_down_ = WM_SYSKEYDOWN;
wm_sys_key_up_ = WM_SYSKEYUP;
wm_sys_char_ = WM_SYSCHAR;
wm_sys_dead_char_ = WM_SYSDEADCHAR;
#endif
last_mouse_pos_ = WebPoint(0, 0);
last_click_time_sec_ = 0;
last_click_pos_ = WebPoint(0, 0);
last_button_type_ = WebMouseEvent::ButtonNone;
touch_points_.clear();
last_context_menu_data_.reset();
task_list_.revokeAll();
current_gesture_location_ = WebPoint(0, 0);
mouse_event_queue_.clear();
time_offset_ms_ = 0;
click_count_ = 0;
}
void EventSender::Install(WebFrame* frame) {
EventSenderBindings::Install(weak_factory_.GetWeakPtr(), frame);
}
void EventSender::SetDelegate(WebTestRunner::WebTestDelegate* delegate) {
delegate_ = delegate;
}
void EventSender::SetWebView(WebView* view) {
view_ = view;
}
void EventSender::SetContextMenuData(const WebContextMenuData& data) {
last_context_menu_data_.reset(new WebContextMenuData(data));
}
void EventSender::DoDragDrop(const WebDragData& drag_data,
WebDragOperationsMask mask) {
WebMouseEvent event;
InitMouseEvent(WebInputEvent::MouseDown,
pressed_button_,
last_mouse_pos_,
GetCurrentEventTimeSec(),
click_count_,
0,
&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_ = view_->dragTargetDragEnter(
drag_data, client_point, screen_point, current_drag_effects_allowed_, 0);
ReplaySavedEvents();
}
void EventSender::MouseDown(int button_number, int modifiers) {
if (force_layout_on_events_)
view_->layout();
DCHECK_NE(-1, button_number);
WebMouseEvent::Button button_type =
GetButtonTypeFromButtonNumber(button_number);
UpdateClickCountForButton(button_type);
pressed_button_ = button_type;
WebMouseEvent event;
InitMouseEvent(WebInputEvent::MouseDown,
button_type,
last_mouse_pos_,
GetCurrentEventTimeSec(),
click_count_,
modifiers,
&event);
view_->handleInputEvent(event);
}
void EventSender::MouseUp(int button_number, int modifiers) {
if (force_layout_on_events_)
view_->layout();
DCHECK_NE(-1, button_number);
WebMouseEvent::Button button_type =
GetButtonTypeFromButtonNumber(button_number);
if (is_drag_mode_ && !replaying_saved_events_) {
SavedEvent saved_event;
saved_event.type = SavedEvent::TYPE_MOUSE_UP;
saved_event.button_type = button_type;
saved_event.modifiers = modifiers;
mouse_event_queue_.push_back(saved_event);
ReplaySavedEvents();
} else {
WebMouseEvent event;
InitMouseEvent(WebInputEvent::MouseUp,
button_type,
last_mouse_pos_,
GetCurrentEventTimeSec(),
click_count_,
modifiers,
&event);
DoMouseUp(event);
}
}
void EventSender::KeyDown(const std::string& code_str,
int modifiers,
KeyLocationCode location) {
bool generate_char = false;
int code = 0;
int text = 0;
bool needs_shift_key_modifier = false;
if ("\n" == code_str) {
generate_char = true;
text = code = WebTestRunner::VKEY_RETURN;
} else if ("rightArrow" == code_str) {
code = WebTestRunner::VKEY_RIGHT;
} else if ("downArrow" == code_str) {
code = WebTestRunner::VKEY_DOWN;
} else if ("leftArrow" == code_str) {
code = WebTestRunner::VKEY_LEFT;
} else if ("upArrow" == code_str) {
code = WebTestRunner::VKEY_UP;
} else if ("insert" == code_str) {
code = WebTestRunner::VKEY_INSERT;
} else if ("delete" == code_str) {
code = WebTestRunner::VKEY_DELETE;
} else if ("pageUp" == code_str) {
code = WebTestRunner::VKEY_PRIOR;
} else if ("pageDown" == code_str) {
code = WebTestRunner::VKEY_NEXT;
} else if ("home" == code_str) {
code = WebTestRunner::VKEY_HOME;
} else if ("end" == code_str) {
code = WebTestRunner::VKEY_END;
} else if ("printScreen" == code_str) {
code = WebTestRunner::VKEY_SNAPSHOT;
} else if ("menu" == code_str) {
code = WebTestRunner::VKEY_APPS;
} else if ("leftControl" == code_str) {
code = WebTestRunner::VKEY_LCONTROL;
} else if ("rightControl" == code_str) {
code = WebTestRunner::VKEY_RCONTROL;
} else if ("leftShift" == code_str) {
code = WebTestRunner::VKEY_LSHIFT;
} else if ("rightShift" == code_str) {
code = WebTestRunner::VKEY_RSHIFT;
} else if ("leftAlt" == code_str) {
code = WebTestRunner::VKEY_LMENU;
} else if ("rightAlt" == code_str) {
code = WebTestRunner::VKEY_RMENU;
} else if ("numLock" == code_str) {
code = WebTestRunner::VKEY_NUMLOCK;
} else {
for (int i = 1; i <= 24; ++i) {
std::string function_key_name = base::StringPrintf("F%d", i);
if (function_key_name == code_str) {
code = WebTestRunner::VKEY_F1 + (i - 1);
break;
}
}
if (!code) {
WebString web_code_str =
WebString::fromUTF8(code_str.data(), code_str.size());
DCHECK_EQ(1u, web_code_str.length());
text = code = web_code_str.at(0);
needs_shift_key_modifier = NeedsShiftModifier(code);
if ((code & 0xFF) >= 'a' && (code & 0xFF) <= 'z')
code -= 'a' - 'A';
generate_char = true;
}
if ("(" == code_str) {
code = '9';
needs_shift_key_modifier = true;
}
}
WebKeyboardEvent event_down;
event_down.type = WebInputEvent::RawKeyDown;
event_down.modifiers = modifiers;
event_down.windowsKeyCode = code;
#if defined(OS_LINUX) && defined(TOOLKIT_GTK)
event_down.nativeKeyCode =
WebTestRunner::NativeKeyCodeForWindowsKeyCode(code);
#endif
if (generate_char) {
event_down.text[0] = text;
event_down.unmodifiedText[0] = text;
}
event_down.setKeyIdentifierFromWindowsKeyCode();
#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_ANDROID) || \
defined(TOOLKIT_GTK)
if (event_down.modifiers != 0)
event_down.isSystemKey = WebInputEventFactory::isSystemKeyEvent(event_down);
#endif
if (needs_shift_key_modifier)
event_down.modifiers |= WebInputEvent::ShiftKey;
if (location == DOMKeyLocationNumpad)
event_down.modifiers |= WebInputEvent::IsKeyPad;
WebKeyboardEvent event_up;
event_up = event_down;
event_up.type = WebInputEvent::KeyUp;
if (force_layout_on_events_)
view_->layout();
std::string edit_command;
if (GetEditCommand(event_down, &edit_command))
delegate_->setEditCommand(edit_command, "");
view_->handleInputEvent(event_down);
if (code == WebTestRunner::VKEY_ESCAPE && !current_drag_data_.isNull()) {
WebMouseEvent event;
InitMouseEvent(WebInputEvent::MouseDown,
pressed_button_,
last_mouse_pos_,
GetCurrentEventTimeSec(),
click_count_,
0,
&event);
FinishDragAndDrop(event, blink::WebDragOperationNone);
}
delegate_->clearEditCommand();
if (generate_char) {
WebKeyboardEvent event_char = event_up;
event_char.type = WebInputEvent::Char;
event_char.keyIdentifier[0] = '\0';
view_->handleInputEvent(event_char);
}
view_->handleInputEvent(event_up);
}
void EventSender::EnableDOMUIEventLogging() {}
void EventSender::FireKeyboardEventsToElement() {}
void EventSender::ClearKillRing() {}
std::vector<std::string> EventSender::ContextClick() {
if (force_layout_on_events_) {
view_->layout();
}
UpdateClickCountForButton(WebMouseEvent::ButtonRight);
last_context_menu_data_.reset();
WebMouseEvent event;
if (pressed_button_ == WebMouseEvent::ButtonNone) {
pressed_button_ = WebMouseEvent::ButtonRight;
}
InitMouseEvent(WebInputEvent::MouseDown,
WebMouseEvent::ButtonRight,
last_mouse_pos_,
GetCurrentEventTimeSec(),
click_count_,
0,
&event);
view_->handleInputEvent(event);
#if defined(OS_WIN)
InitMouseEvent(WebInputEvent::MouseUp,
WebMouseEvent::ButtonRight,
last_mouse_pos_,
GetCurrentEventTimeSec(),
click_count_,
0,
&event);
view_->handleInputEvent(event);
pressed_button_= WebMouseEvent::ButtonNone;
#endif
return MakeMenuItemStringsFor(last_context_menu_data_.release(), delegate_);
}
void EventSender::TextZoomIn() {
view_->setTextZoomFactor(view_->textZoomFactor() * 1.2f);
}
void EventSender::TextZoomOut() {
view_->setTextZoomFactor(view_->textZoomFactor() / 1.2f);
}
void EventSender::ZoomPageIn() {
const std::vector<WebTestRunner::WebTestProxyBase*>& window_list =
interfaces_->windowList();
for (size_t i = 0; i < window_list.size(); ++i) {
window_list.at(i)->webView()->setZoomLevel(
window_list.at(i)->webView()->zoomLevel() + 1);
}
}
void EventSender::ZoomPageOut() {
const std::vector<WebTestRunner::WebTestProxyBase*>& window_list =
interfaces_->windowList();
for (size_t i = 0; i < window_list.size(); ++i) {
window_list.at(i)->webView()->setZoomLevel(
window_list.at(i)->webView()->zoomLevel() - 1);
}
}
void EventSender::SetPageScaleFactor(float scale_factor, int x, int y) {
view_->setPageScaleFactorLimits(scale_factor, scale_factor);
view_->setPageScaleFactor(scale_factor, WebPoint(x, y));
}
void EventSender::ClearTouchPoints() {
touch_points_.clear();
}
void EventSender::ReleaseTouchPoint(unsigned index) {
DCHECK_LT(index, touch_points_.size());
WebTouchPoint* touch_point = &touch_points_[index];
touch_point->state = WebTouchPoint::StateReleased;
}
void EventSender::UpdateTouchPoint(unsigned index, int x, int y) {
DCHECK_LT(index, touch_points_.size());
WebTouchPoint* touch_point = &touch_points_[index];
touch_point->state = WebTouchPoint::StateMoved;
touch_point->position = WebFloatPoint(x, y);
touch_point->screenPosition = touch_point->position;
}
void EventSender::CancelTouchPoint(unsigned index) {
DCHECK_LT(index, touch_points_.size());
WebTouchPoint* touch_point = &touch_points_[index];
touch_point->state = WebTouchPoint::StateCancelled;
}
void EventSender::SetTouchModifier(const std::string& key_name,
bool set_mask) {
int mask = 0;
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 (set_mask)
touch_modifiers_ |= mask;
else
touch_modifiers_ &= ~mask;
}
void EventSender::DumpFilenameBeingDragged() {
WebString filename;
WebVector<WebDragData::Item> items = current_drag_data_.items();
for (size_t i = 0; i < items.size(); ++i) {
if (items[i].storageType == WebDragData::Item::StorageTypeBinaryData) {
filename = items[i].title;
break;
}
}
delegate_->printMessage(std::string("Filename being dragged: ") +
filename.utf8().data() + "\n");
}
void EventSender::GestureFlingCancel() {
WebGestureEvent event;
event.type = WebInputEvent::GestureFlingCancel;
event.timeStampSeconds = GetCurrentEventTimeSec();
if (force_layout_on_events_)
view_->layout();
view_->handleInputEvent(event);
}
void EventSender::GestureFlingStart(float x,
float y,
float velocity_x,
float velocity_y) {
WebGestureEvent event;
event.type = WebInputEvent::GestureFlingStart;
event.x = x;
event.y = y;
event.globalX = event.x;
event.globalY = event.y;
event.data.flingStart.velocityX = velocity_x;
event.data.flingStart.velocityY = velocity_y;
event.timeStampSeconds = GetCurrentEventTimeSec();
if (force_layout_on_events_)
view_->layout();
view_->handleInputEvent(event);
}
void EventSender::GestureScrollFirstPoint(int x, int y) {
current_gesture_location_ = WebPoint(x, y);
}
void EventSender::TouchStart() {
SendCurrentTouchEvent(WebInputEvent::TouchStart);
}
void EventSender::TouchMove() {
SendCurrentTouchEvent(WebInputEvent::TouchMove);
}
void EventSender::TouchCancel() {
SendCurrentTouchEvent(WebInputEvent::TouchCancel);
}
void EventSender::TouchEnd() {
SendCurrentTouchEvent(WebInputEvent::TouchEnd);
}
void EventSender::LeapForward(int milliseconds) {
if (is_drag_mode_ && pressed_button_ == WebMouseEvent::ButtonLeft &&
!replaying_saved_events_) {
SavedEvent saved_event;
saved_event.type = SavedEvent::TYPE_LEAP_FORWARD;
saved_event.milliseconds = milliseconds;
mouse_event_queue_.push_back(saved_event);
} else {
DoLeapForward(milliseconds);
}
}
void EventSender::BeginDragWithFiles(const std::vector<std::string>& files) {
current_drag_data_.initialize();
WebVector<WebString> absolute_filenames(files.size());
for (size_t i = 0; i < files.size(); ++i) {
WebDragData::Item item;
item.storageType = WebDragData::Item::StorageTypeFilename;
item.filenameData = delegate_->getAbsoluteWebStringFromUTF8Path(files[i]);
current_drag_data_.addItem(item);
absolute_filenames[i] = item.filenameData;
}
current_drag_data_.setFilesystemId(
delegate_->registerIsolatedFileSystem(absolute_filenames));
current_drag_effects_allowed_ = blink::WebDragOperationCopy;
view_->dragTargetDragEnter(current_drag_data_,
last_mouse_pos_,
last_mouse_pos_,
current_drag_effects_allowed_,
0);
is_drag_mode_ = false;
pressed_button_ = WebMouseEvent::ButtonLeft;
}
void EventSender::AddTouchPoint(gin::Arguments* args) {
int x;
int y;
args->GetNext(&x);
args->GetNext(&y);
WebTouchPoint touch_point;
touch_point.state = WebTouchPoint::StatePressed;
touch_point.position = WebFloatPoint(x, y);
touch_point.screenPosition = touch_point.position;
if (!args->PeekNext().IsEmpty()) {
int radius_x;
if (!args->GetNext(&radius_x)) {
args->ThrowError();
return;
}
int radius_y = radius_x;
if (!args->PeekNext().IsEmpty()) {
if (!args->GetNext(&radius_y)) {
args->ThrowError();
return;
}
}
touch_point.radiusX = radius_x;
touch_point.radiusY = radius_y;
}
int lowest_id = 0;
for (size_t i = 0; i < touch_points_.size(); i++) {
if (touch_points_[i].id == lowest_id)
lowest_id++;
}
touch_point.id = lowest_id;
touch_points_.push_back(touch_point);
}
void EventSender::MouseDragBegin() {
WebMouseWheelEvent event;
InitMouseEvent(WebInputEvent::MouseWheel,
WebMouseEvent::ButtonNone,
last_mouse_pos_,
GetCurrentEventTimeSec(),
click_count_,
0,
&event);
event.phase = WebMouseWheelEvent::PhaseBegan;
event.hasPreciseScrollingDeltas = true;
view_->handleInputEvent(event);
}
void EventSender::MouseDragEnd() {
WebMouseWheelEvent event;
InitMouseEvent(WebInputEvent::MouseWheel,
WebMouseEvent::ButtonNone,
last_mouse_pos_,
GetCurrentEventTimeSec(),
click_count_,
0,
&event);
event.phase = WebMouseWheelEvent::PhaseEnded;
event.hasPreciseScrollingDeltas = true;
view_->handleInputEvent(event);
}
void EventSender::MouseMomentumBegin() {
WebMouseWheelEvent event;
InitMouseEvent(WebInputEvent::MouseWheel,
WebMouseEvent::ButtonNone,
last_mouse_pos_,
GetCurrentEventTimeSec(),
click_count_,
0,
&event);
event.momentumPhase = WebMouseWheelEvent::PhaseBegan;
event.hasPreciseScrollingDeltas = true;
view_->handleInputEvent(event);
}
void EventSender::GestureScrollBegin(gin::Arguments* args) {
GestureEvent(WebInputEvent::GestureScrollBegin, args);
}
void EventSender::GestureScrollEnd(gin::Arguments* args) {
GestureEvent(WebInputEvent::GestureScrollEnd, args);
}
void EventSender::GestureScrollUpdate(gin::Arguments* args) {
GestureEvent(WebInputEvent::GestureScrollUpdate, args);
}
void EventSender::GestureScrollUpdateWithoutPropagation(gin::Arguments* args) {
GestureEvent(WebInputEvent::GestureScrollUpdateWithoutPropagation, args);
}
void EventSender::GestureTap(gin::Arguments* args) {
GestureEvent(WebInputEvent::GestureTap, args);
}
void EventSender::GestureTapDown(gin::Arguments* args) {
GestureEvent(WebInputEvent::GestureTapDown, args);
}
void EventSender::GestureShowPress(gin::Arguments* args) {
GestureEvent(WebInputEvent::GestureShowPress, args);
}
void EventSender::GestureTapCancel(gin::Arguments* args) {
GestureEvent(WebInputEvent::GestureTapCancel, args);
}
void EventSender::GestureLongPress(gin::Arguments* args) {
GestureEvent(WebInputEvent::GestureLongPress, args);
}
void EventSender::GestureLongTap(gin::Arguments* args) {
GestureEvent(WebInputEvent::GestureLongTap, args);
}
void EventSender::GestureTwoFingerTap(gin::Arguments* args) {
GestureEvent(WebInputEvent::GestureTwoFingerTap, args);
}
void EventSender::ContinuousMouseScrollBy(gin::Arguments* args) {
WebMouseWheelEvent event;
InitMouseWheelEvent(args, true, &event);
view_->handleInputEvent(event);
}
void EventSender::DispatchMessage(int msg, int wparam, int lparam) {
#if defined(OS_WIN)
if (msg == WM_DEADCHAR || msg == WM_SYSDEADCHAR)
return;
if (force_layout_on_events_)
view_->layout();
view_->handleInputEvent(
WebInputEventFactory::keyboardEvent(0, msg, wparam, lparam));
#endif
}
void EventSender::MouseMoveTo(gin::Arguments* args) {
if (force_layout_on_events_)
view_->layout();
int x;
int y;
args->GetNext(&x);
args->GetNext(&y);
WebPoint mouse_pos(x, y);
int modifiers = 0;
if (!args->PeekNext().IsEmpty())
modifiers = GetKeyModifiersFromV8(args->PeekNext());
if (is_drag_mode_ && pressed_button_ == WebMouseEvent::ButtonLeft &&
!replaying_saved_events_) {
SavedEvent saved_event;
saved_event.type = SavedEvent::TYPE_MOUSE_MOVE;
saved_event.pos = mouse_pos;
saved_event.modifiers = modifiers;
mouse_event_queue_.push_back(saved_event);
} else {
WebMouseEvent event;
InitMouseEvent(WebInputEvent::MouseMove,
pressed_button_,
mouse_pos,
GetCurrentEventTimeSec(),
click_count_,
modifiers,
&event);
DoMouseMove(event);
}
}
void EventSender::MouseScrollBy(gin::Arguments* args) {
WebMouseWheelEvent event;
InitMouseWheelEvent(args, false, &event);
view_->handleInputEvent(event);
}
void EventSender::MouseMomentumScrollBy(gin::Arguments* args) {
WebMouseWheelEvent event;
InitMouseWheelEvent(args, true, &event);
event.momentumPhase = WebMouseWheelEvent::PhaseChanged;
event.hasPreciseScrollingDeltas = true;
view_->handleInputEvent(event);
}
void EventSender::MouseMomentumEnd() {
WebMouseWheelEvent event;
InitMouseEvent(WebInputEvent::MouseWheel,
WebMouseEvent::ButtonNone,
last_mouse_pos_,
GetCurrentEventTimeSec(),
click_count_,
0,
&event);
event.momentumPhase = WebMouseWheelEvent::PhaseEnded;
event.hasPreciseScrollingDeltas = true;
view_->handleInputEvent(event);
}
void EventSender::ScheduleAsynchronousClick(int button_number, int modifiers) {
delegate_->postTask(new MouseDownTask(this, button_number, modifiers));
delegate_->postTask(new MouseUpTask(this, button_number, modifiers));
}
void EventSender::ScheduleAsynchronousKeyDown(const std::string& code_str,
int modifiers,
KeyLocationCode location) {
delegate_->postTask(new KeyDownTask(this, code_str, modifiers, location));
}
double EventSender::GetCurrentEventTimeSec() {
return (delegate_->getCurrentTimeInMillisecond() + time_offset_ms_) / 1000.0;
}
void EventSender::DoLeapForward(int milliseconds) {
time_offset_ms_ += milliseconds;
}
void EventSender::SendCurrentTouchEvent(WebInputEvent::Type type) {
DCHECK_GT(static_cast<unsigned>(WebTouchEvent::touchesLengthCap),
touch_points_.size());
if (force_layout_on_events_)
view_->layout();
WebTouchEvent touch_event;
touch_event.type = type;
touch_event.modifiers = touch_modifiers_;
touch_event.timeStampSeconds = GetCurrentEventTimeSec();
touch_event.touchesLength = touch_points_.size();
for (size_t i = 0; i < touch_points_.size(); ++i)
touch_event.touches[i] = touch_points_[i];
view_->handleInputEvent(touch_event);
for (size_t i = 0; i < touch_points_.size(); ++i) {
WebTouchPoint* touch_point = &touch_points_[i];
if (touch_point->state == WebTouchPoint::StateReleased) {
touch_points_.erase(touch_points_.begin() + i);
--i;
} else
touch_point->state = WebTouchPoint::StateStationary;
}
}
void EventSender::GestureEvent(WebInputEvent::Type type,
gin::Arguments* args) {
double x;
double y;
args->GetNext(&x);
args->GetNext(&y);
WebPoint point(x, y);
WebGestureEvent event;
event.type = type;
switch (type) {
case WebInputEvent::GestureScrollUpdate:
case WebInputEvent::GestureScrollUpdateWithoutPropagation:
event.data.scrollUpdate.deltaX = static_cast<float>(x);
event.data.scrollUpdate.deltaY = static_cast<float>(y);
event.x = current_gesture_location_.x;
event.y = current_gesture_location_.y;
current_gesture_location_.x =
current_gesture_location_.x + event.data.scrollUpdate.deltaX;
current_gesture_location_.y =
current_gesture_location_.y + event.data.scrollUpdate.deltaY;
break;
case WebInputEvent::GestureScrollBegin:
current_gesture_location_ = WebPoint(point.x, point.y);
event.x = current_gesture_location_.x;
event.y = current_gesture_location_.y;
break;
case WebInputEvent::GestureScrollEnd:
case WebInputEvent::GestureFlingStart:
event.x = current_gesture_location_.x;
event.y = current_gesture_location_.y;
break;
case WebInputEvent::GestureTap:
if (!args->PeekNext().IsEmpty()) {
float tap_count;
if (!args->GetNext(&tap_count)) {
args->ThrowError();
return;
}
event.data.tap.tapCount = tap_count;
} else {
event.data.tap.tapCount = 1;
}
event.x = point.x;
event.y = point.y;
break;
case WebInputEvent::GestureTapUnconfirmed:
if (!args->PeekNext().IsEmpty()) {
float tap_count;
if (!args->GetNext(&tap_count)) {
args->ThrowError();
return;
}
event.data.tap.tapCount = tap_count;
} else {
event.data.tap.tapCount = 1;
}
event.x = point.x;
event.y = point.y;
break;
case WebInputEvent::GestureTapDown:
event.x = point.x;
event.y = point.y;
if (!args->PeekNext().IsEmpty()) {
float width;
if (!args->GetNext(&width)) {
args->ThrowError();
return;
}
event.data.tapDown.width = width;
}
if (!args->PeekNext().IsEmpty()) {
float height;
if (!args->GetNext(&height)) {
args->ThrowError();
return;
}
event.data.tapDown.height = height;
}
break;
case WebInputEvent::GestureShowPress:
event.x = point.x;
event.y = point.y;
if (!args->PeekNext().IsEmpty()) {
float width;
if (!args->GetNext(&width)) {
args->ThrowError();
return;
}
event.data.showPress.width = width;
if (!args->PeekNext().IsEmpty()) {
float height;
if (!args->GetNext(&height)) {
args->ThrowError();
return;
}
event.data.showPress.height = height;
}
}
break;
case WebInputEvent::GestureTapCancel:
event.x = point.x;
event.y = point.y;
break;
case WebInputEvent::GestureLongPress:
event.x = point.x;
event.y = point.y;
if (!args->PeekNext().IsEmpty()) {
float width;
if (!args->GetNext(&width)) {
args->ThrowError();
return;
}
event.data.longPress.width = width;
if (!args->PeekNext().IsEmpty()) {
float height;
if (!args->GetNext(&height)) {
args->ThrowError();
return;
}
event.data.longPress.height = height;
}
}
break;
case WebInputEvent::GestureLongTap:
event.x = point.x;
event.y = point.y;
if (!args->PeekNext().IsEmpty()) {
float width;
if (!args->GetNext(&width)) {
args->ThrowError();
return;
}
event.data.longPress.width = width;
if (!args->PeekNext().IsEmpty()) {
float height;
if (!args->GetNext(&height)) {
args->ThrowError();
return;
}
event.data.longPress.height = height;
}
}
break;
case WebInputEvent::GestureTwoFingerTap:
event.x = point.x;
event.y = point.y;
if (!args->PeekNext().IsEmpty()) {
float first_finger_width;
if (!args->GetNext(&first_finger_width)) {
args->ThrowError();
return;
}
event.data.twoFingerTap.firstFingerWidth = first_finger_width;
if (!args->PeekNext().IsEmpty()) {
float first_finger_height;
if (!args->GetNext(&first_finger_height)) {
args->ThrowError();
return;
}
event.data.twoFingerTap.firstFingerHeight = first_finger_height;
}
}
break;
default:
NOTREACHED();
}
event.globalX = event.x;
event.globalY = event.y;
event.timeStampSeconds = GetCurrentEventTimeSec();
if (force_layout_on_events_)
view_->layout();
view_->handleInputEvent(event);
if (type == WebInputEvent::GestureLongPress && !current_drag_data_.isNull()) {
WebMouseEvent mouse_event;
InitMouseEvent(WebInputEvent::MouseDown,
pressed_button_,
point,
GetCurrentEventTimeSec(),
click_count_,
0,
&mouse_event);
FinishDragAndDrop(mouse_event, blink::WebDragOperationNone);
}
}
void EventSender::UpdateClickCountForButton(
WebMouseEvent::Button button_type) {
if ((GetCurrentEventTimeSec() - last_click_time_sec_ <
kMultipleClickTimeSec) &&
(!OutsideMultiClickRadius(last_mouse_pos_, last_click_pos_)) &&
(button_type == last_button_type_)) {
++click_count_;
} else {
click_count_ = 1;
last_button_type_ = button_type;
}
}
void EventSender::InitMouseWheelEvent(gin::Arguments* args,
bool continuous,
WebMouseWheelEvent* event) {
if (force_layout_on_events_)
view_->layout();
double horizontal;
if (!args->GetNext(&horizontal)) {
args->ThrowError();
return;
}
double vertical;
if (!args->GetNext(&vertical)) {
args->ThrowError();
return;
}
bool paged = false;
bool has_precise_scrolling_deltas = false;
int modifiers = 0;
if (!args->PeekNext().IsEmpty()) {
args->GetNext(&paged);
if (!args->PeekNext().IsEmpty()) {
args->GetNext(&has_precise_scrolling_deltas);
if (!args->PeekNext().IsEmpty())
modifiers = GetKeyModifiersFromV8(args->PeekNext());
}
}
InitMouseEvent(WebInputEvent::MouseWheel,
pressed_button_,
last_mouse_pos_,
GetCurrentEventTimeSec(),
click_count_,
modifiers,
event);
event->wheelTicksX = static_cast<float>(horizontal);
event->wheelTicksY = static_cast<float>(vertical);
event->deltaX = event->wheelTicksX;
event->deltaY = event->wheelTicksY;
event->scrollByPage = paged;
event->hasPreciseScrollingDeltas = has_precise_scrolling_deltas;
if (continuous) {
event->wheelTicksX /= kScrollbarPixelsPerTick;
event->wheelTicksY /= kScrollbarPixelsPerTick;
} else {
event->deltaX *= kScrollbarPixelsPerTick;
event->deltaY *= kScrollbarPixelsPerTick;
}
}
void EventSender::FinishDragAndDrop(const WebMouseEvent& e,
blink::WebDragOperation drag_effect) {
WebPoint client_point(e.x, e.y);
WebPoint screen_point(e.globalX, e.globalY);
current_drag_effect_ = drag_effect;
if (current_drag_effect_) {
view_->dragTargetDrop(client_point, screen_point, e.modifiers);
} else {
view_->dragTargetDragLeave();
}
view_->dragSourceEndedAt(client_point, screen_point, current_drag_effect_);
view_->dragSourceSystemDragEnded();
current_drag_data_.reset();
}
void EventSender::DoMouseUp(const WebMouseEvent& e) {
view_->handleInputEvent(e);
pressed_button_ = WebMouseEvent::ButtonNone;
last_click_time_sec_ = e.timeStampSeconds;
last_click_pos_ = last_mouse_pos_;
if (current_drag_data_.isNull())
return;
WebPoint client_point(e.x, e.y);
WebPoint screen_point(e.globalX, e.globalY);
FinishDragAndDrop(
e,
view_->dragTargetDragOver(
client_point, screen_point, current_drag_effects_allowed_, 0));
}
void EventSender::DoMouseMove(const WebMouseEvent& e) {
last_mouse_pos_ = WebPoint(e.x, e.y);
view_->handleInputEvent(e);
if (pressed_button_ == WebMouseEvent::ButtonNone ||
current_drag_data_.isNull()) {
return;
}
WebPoint client_point(e.x, e.y);
WebPoint screen_point(e.globalX, e.globalY);
current_drag_effect_ = view_->dragTargetDragOver(
client_point, screen_point, current_drag_effects_allowed_, 0);
}
void EventSender::ReplaySavedEvents() {
replaying_saved_events_ = true;
while (!mouse_event_queue_.empty()) {
SavedEvent e = mouse_event_queue_.front();
mouse_event_queue_.pop_front();
switch (e.type) {
case SavedEvent::TYPE_MOUSE_MOVE: {
WebMouseEvent event;
InitMouseEvent(WebInputEvent::MouseMove,
pressed_button_,
e.pos,
GetCurrentEventTimeSec(),
click_count_,
e.modifiers,
&event);
DoMouseMove(event);
break;
}
case SavedEvent::TYPE_LEAP_FORWARD:
DoLeapForward(e.milliseconds);
break;
case SavedEvent::TYPE_MOUSE_UP: {
WebMouseEvent event;
InitMouseEvent(WebInputEvent::MouseUp,
e.button_type,
last_mouse_pos_,
GetCurrentEventTimeSec(),
click_count_,
e.modifiers,
&event);
DoMouseUp(event);
break;
}
default:
NOTREACHED();
}
}
replaying_saved_events_ = false;
}
}