blob: 770eda740954cea0bd69c395e26d2e6ffc9d855f [file] [log] [blame]
// Copyright 2014 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.
#include "mojo/converters/blink/blink_input_events_type_converters.h"
#include <utility>
#include "base/logging.h"
#include "base/time/time.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
#include "ui/events/base_event_utils.h"
#include "ui/events/event.h"
#include "ui/events/keycodes/dom/keycode_converter.h"
namespace mojo {
namespace {
// TODO(majidvp): remove this and directly use ui::EventFlagsToWebEventModifiers
int EventFlagsToWebEventModifiers(int flags) {
int modifiers = 0;
if (flags & ui::EF_SHIFT_DOWN)
modifiers |= blink::WebInputEvent::ShiftKey;
if (flags & ui::EF_CONTROL_DOWN)
modifiers |= blink::WebInputEvent::ControlKey;
if (flags & ui::EF_ALT_DOWN)
modifiers |= blink::WebInputEvent::AltKey;
// TODO(beng): MetaKey/META_MASK
if (flags & ui::EF_LEFT_MOUSE_BUTTON)
modifiers |= blink::WebInputEvent::LeftButtonDown;
if (flags & ui::EF_MIDDLE_MOUSE_BUTTON)
modifiers |= blink::WebInputEvent::MiddleButtonDown;
if (flags & ui::EF_RIGHT_MOUSE_BUTTON)
modifiers |= blink::WebInputEvent::RightButtonDown;
if (flags & ui::EF_CAPS_LOCK_ON)
modifiers |= blink::WebInputEvent::CapsLockOn;
return modifiers;
}
// TODO(majidvp): remove this and directly use ui::EventFlagsToWebEventModifiers
int EventFlagsToWebInputEventModifiers(int flags) {
return (flags & ui::EF_SHIFT_DOWN ? blink::WebInputEvent::ShiftKey : 0) |
(flags & ui::EF_CONTROL_DOWN ? blink::WebInputEvent::ControlKey : 0) |
(flags & ui::EF_CAPS_LOCK_ON ? blink::WebInputEvent::CapsLockOn : 0) |
(flags & ui::EF_ALT_DOWN ? blink::WebInputEvent::AltKey : 0);
}
int GetClickCount(int flags) {
if (flags & ui::EF_IS_TRIPLE_CLICK)
return 3;
else if (flags & ui::EF_IS_DOUBLE_CLICK)
return 2;
return 1;
}
void SetWebMouseEventLocation(const ui::LocatedEvent& located_event,
blink::WebMouseEvent* web_event) {
web_event->x = static_cast<int>(located_event.x());
web_event->y = static_cast<int>(located_event.y());
web_event->globalX = static_cast<int>(located_event.root_location_f().x());
web_event->globalY = static_cast<int>(located_event.root_location_f().y());
}
std::unique_ptr<blink::WebInputEvent> BuildWebMouseEventFrom(
const ui::PointerEvent& event) {
std::unique_ptr<blink::WebMouseEvent> web_event(new blink::WebMouseEvent);
web_event->pointerType = blink::WebPointerProperties::PointerType::Mouse;
SetWebMouseEventLocation(event, web_event.get());
web_event->modifiers = EventFlagsToWebEventModifiers(event.flags());
web_event->timeStampSeconds = ui::EventTimeStampToSeconds(event.time_stamp());
web_event->button = blink::WebMouseEvent::Button::NoButton;
if (event.flags() & ui::EF_LEFT_MOUSE_BUTTON)
web_event->button = blink::WebMouseEvent::Button::Left;
if (event.flags() & ui::EF_MIDDLE_MOUSE_BUTTON)
web_event->button = blink::WebMouseEvent::Button::Middle;
if (event.flags() & ui::EF_RIGHT_MOUSE_BUTTON)
web_event->button = blink::WebMouseEvent::Button::Right;
switch (event.type()) {
case ui::ET_POINTER_DOWN:
web_event->type = blink::WebInputEvent::MouseDown;
break;
case ui::ET_POINTER_UP:
web_event->type = blink::WebInputEvent::MouseUp;
break;
case ui::ET_POINTER_MOVED:
web_event->type = blink::WebInputEvent::MouseMove;
break;
case ui::ET_MOUSE_EXITED:
web_event->type = blink::WebInputEvent::MouseLeave;
break;
default:
NOTIMPLEMENTED() << "Received unexpected event: " << event.type();
break;
}
web_event->clickCount = GetClickCount(event.flags());
return std::move(web_event);
}
std::unique_ptr<blink::WebInputEvent> BuildWebKeyboardEvent(
const ui::KeyEvent& event) {
std::unique_ptr<blink::WebKeyboardEvent> web_event(
new blink::WebKeyboardEvent);
web_event->modifiers = EventFlagsToWebInputEventModifiers(event.flags());
web_event->timeStampSeconds = ui::EventTimeStampToSeconds(event.time_stamp());
switch (event.type()) {
case ui::ET_KEY_PRESSED:
web_event->type = event.is_char() ? blink::WebInputEvent::Char
: blink::WebInputEvent::RawKeyDown;
break;
case ui::ET_KEY_RELEASED:
web_event->type = blink::WebInputEvent::KeyUp;
break;
default:
NOTREACHED();
}
if (web_event->modifiers & blink::WebInputEvent::AltKey)
web_event->isSystemKey = true;
web_event->windowsKeyCode = event.GetLocatedWindowsKeyboardCode();
web_event->nativeKeyCode =
ui::KeycodeConverter::DomCodeToNativeKeycode(event.code());
web_event->text[0] = event.GetText();
web_event->unmodifiedText[0] = event.GetUnmodifiedText();
return std::move(web_event);
}
std::unique_ptr<blink::WebInputEvent> BuildWebMouseWheelEventFrom(
const ui::MouseWheelEvent& event) {
std::unique_ptr<blink::WebMouseWheelEvent> web_event(
new blink::WebMouseWheelEvent);
web_event->type = blink::WebInputEvent::MouseWheel;
web_event->button = blink::WebMouseEvent::Button::NoButton;
web_event->modifiers = EventFlagsToWebEventModifiers(event.flags());
web_event->timeStampSeconds = ui::EventTimeStampToSeconds(event.time_stamp());
SetWebMouseEventLocation(event, web_event.get());
// TODO(rjkroege): Update the following code once Blink supports
// DOM Level 3 wheel events
// (http://www.w3.org/TR/DOM-Level-3-Events/#events-wheelevents)
web_event->deltaX = event.x_offset();
web_event->deltaY = event.y_offset();
web_event->wheelTicksX = web_event->deltaX / ui::MouseWheelEvent::kWheelDelta;
web_event->wheelTicksY = web_event->deltaY / ui::MouseWheelEvent::kWheelDelta;
// TODO(moshayedi): ui::WheelEvent currently only supports WHEEL_MODE_LINE.
// Add support for other wheel modes once ui::WheelEvent has support for them.
web_event->hasPreciseScrollingDeltas = false;
web_event->scrollByPage = false;
return std::move(web_event);
}
void SetWebTouchEventLocation(const ui::PointerEvent& event,
blink::WebTouchPoint* touch) {
touch->position.x = event.x();
touch->position.y = event.y();
touch->screenPosition.x = event.root_location_f().x();
touch->screenPosition.y = event.root_location_f().y();
}
std::unique_ptr<blink::WebInputEvent> BuildWebTouchEvent(
const ui::PointerEvent& event) {
std::unique_ptr<blink::WebTouchEvent> web_event(new blink::WebTouchEvent);
blink::WebTouchPoint* touch = &web_event->touches[event.pointer_id()];
// TODO(jonross): we will need to buffer input events, as blink expects all
// active touch points to be in each WebInputEvent (crbug.com/578160)
SetWebTouchEventLocation(event, touch);
touch->pointerType = blink::WebPointerProperties::PointerType::Touch;
touch->radiusX = event.pointer_details().radius_x;
touch->radiusY = event.pointer_details().radius_y;
web_event->modifiers = EventFlagsToWebEventModifiers(event.flags());
web_event->timeStampSeconds = ui::EventTimeStampToSeconds(event.time_stamp());
web_event->uniqueTouchEventId = ui::GetNextTouchEventId();
switch (event.type()) {
case ui::ET_POINTER_DOWN:
web_event->type = blink::WebInputEvent::TouchStart;
touch->state = blink::WebTouchPoint::StatePressed;
break;
case ui::ET_POINTER_UP:
web_event->type = blink::WebInputEvent::TouchEnd;
touch->state = blink::WebTouchPoint::StateReleased;
break;
case ui::ET_POINTER_MOVED:
web_event->type = blink::WebInputEvent::TouchMove;
touch->state = blink::WebTouchPoint::StateMoved;
break;
case ui::ET_POINTER_CANCELLED:
web_event->type = blink::WebInputEvent::TouchCancel;
touch->state = blink::WebTouchPoint::StateCancelled;
break;
default:
NOTIMPLEMENTED() << "Received non touch pointer event action: "
<< event.type();
break;
}
return std::move(web_event);
}
} // namespace
// static
std::unique_ptr<blink::WebInputEvent>
TypeConverter<std::unique_ptr<blink::WebInputEvent>, ui::Event>::Convert(
const ui::Event& event) {
DCHECK(event.IsKeyEvent() || event.IsPointerEvent() ||
event.IsMouseWheelEvent());
switch (event.type()) {
case ui::ET_POINTER_DOWN:
case ui::ET_POINTER_UP:
case ui::ET_POINTER_CANCELLED:
case ui::ET_POINTER_MOVED:
case ui::ET_POINTER_EXITED:
if (event.IsMousePointerEvent())
return BuildWebMouseEventFrom(*event.AsPointerEvent());
else if (event.IsTouchPointerEvent())
return BuildWebTouchEvent(*event.AsPointerEvent());
else
return nullptr;
case ui::ET_MOUSEWHEEL:
return BuildWebMouseWheelEventFrom(*event.AsMouseWheelEvent());
case ui::ET_KEY_PRESSED:
case ui::ET_KEY_RELEASED:
return BuildWebKeyboardEvent(*event.AsKeyEvent());
default:
return nullptr;
}
}
} // namespace mojo