blob: bdbc85b1058aae44ec03a08c0d5f200d964186e4 [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 "components/mus/public/interfaces/input_event_constants.mojom.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
#include "ui/events/base_event_utils.h"
#include "ui/events/event.h"
namespace mojo {
namespace {
double EventTimeToWebEventTime(const mus::mojom::EventPtr& event) {
return base::TimeDelta::FromInternalValue(event->time_stamp).InSecondsF();
}
int EventFlagsToWebEventModifiers(int flags) {
int modifiers = 0;
if (flags & mus::mojom::kEventFlagShiftDown)
modifiers |= blink::WebInputEvent::ShiftKey;
if (flags & mus::mojom::kEventFlagControlDown)
modifiers |= blink::WebInputEvent::ControlKey;
if (flags & mus::mojom::kEventFlagAltDown)
modifiers |= blink::WebInputEvent::AltKey;
// TODO(beng): MetaKey/META_MASK
if (flags & mus::mojom::kEventFlagLeftMouseButton)
modifiers |= blink::WebInputEvent::LeftButtonDown;
if (flags & mus::mojom::kEventFlagMiddleMouseButton)
modifiers |= blink::WebInputEvent::MiddleButtonDown;
if (flags & mus::mojom::kEventFlagRightMouseButton)
modifiers |= blink::WebInputEvent::RightButtonDown;
if (flags & mus::mojom::kEventFlagCapsLockOn)
modifiers |= blink::WebInputEvent::CapsLockOn;
return modifiers;
}
int EventFlagsToWebInputEventModifiers(int flags) {
return (flags & mus::mojom::kEventFlagShiftDown
? blink::WebInputEvent::ShiftKey
: 0) |
(flags & mus::mojom::kEventFlagControlDown
? blink::WebInputEvent::ControlKey
: 0) |
(flags & mus::mojom::kEventFlagCapsLockOn
? blink::WebInputEvent::CapsLockOn
: 0) |
(flags & mus::mojom::kEventFlagAltDown ? blink::WebInputEvent::AltKey
: 0);
}
int GetClickCount(int flags) {
if (flags & mus::mojom::kMouseEventFlagIsTripleClick)
return 3;
else if (flags & mus::mojom::kMouseEventFlagIsDoubleClick)
return 2;
return 1;
}
blink::WebPointerProperties::PointerType EventPointerKindToWebPointerType(
mus::mojom::PointerKind pointer_kind) {
switch (pointer_kind) {
case mus::mojom::PointerKind::MOUSE:
return blink::WebPointerProperties::PointerType::Mouse;
case mus::mojom::PointerKind::TOUCH:
return blink::WebPointerProperties::PointerType::Touch;
case mus::mojom::PointerKind::PEN:
return blink::WebPointerProperties::PointerType::Pen;
}
NOTREACHED();
return blink::WebPointerProperties::PointerType::Unknown;
}
void SetWebMouseEventLocation(const mus::mojom::LocationData& location_data,
blink::WebMouseEvent* web_event) {
web_event->x = static_cast<int>(location_data.x);
web_event->y = static_cast<int>(location_data.y);
web_event->globalX = static_cast<int>(location_data.screen_x);
web_event->globalY = static_cast<int>(location_data.screen_y);
}
scoped_ptr<blink::WebInputEvent> BuildWebMouseEventFrom(
const mus::mojom::EventPtr& event) {
scoped_ptr<blink::WebMouseEvent> web_event(new blink::WebMouseEvent);
web_event->pointerType =
EventPointerKindToWebPointerType(event->pointer_data->kind);
if (event->pointer_data && event->pointer_data->location)
SetWebMouseEventLocation(*(event->pointer_data->location), web_event.get());
web_event->modifiers = EventFlagsToWebEventModifiers(event->flags);
web_event->timeStampSeconds = EventTimeToWebEventTime(event);
web_event->button = blink::WebMouseEvent::ButtonNone;
if (event->flags & mus::mojom::kEventFlagLeftMouseButton)
web_event->button = blink::WebMouseEvent::ButtonLeft;
if (event->flags & mus::mojom::kEventFlagMiddleMouseButton)
web_event->button = blink::WebMouseEvent::ButtonMiddle;
if (event->flags & mus::mojom::kEventFlagRightMouseButton)
web_event->button = blink::WebMouseEvent::ButtonRight;
switch (event->action) {
case mus::mojom::EventType::POINTER_DOWN:
web_event->type = blink::WebInputEvent::MouseDown;
break;
case mus::mojom::EventType::POINTER_UP:
web_event->type = blink::WebInputEvent::MouseUp;
break;
case mus::mojom::EventType::POINTER_MOVE:
web_event->type = blink::WebInputEvent::MouseMove;
break;
case mus::mojom::EventType::MOUSE_EXIT:
web_event->type = blink::WebInputEvent::MouseLeave;
break;
default:
NOTIMPLEMENTED() << "Received unexpected event: " << event->action;
break;
}
web_event->clickCount = GetClickCount(event->flags);
return std::move(web_event);
}
scoped_ptr<blink::WebInputEvent> BuildWebKeyboardEvent(
const mus::mojom::EventPtr& event) {
scoped_ptr<blink::WebKeyboardEvent> web_event(new blink::WebKeyboardEvent);
web_event->modifiers = EventFlagsToWebInputEventModifiers(event->flags);
web_event->timeStampSeconds = EventTimeToWebEventTime(event);
switch (event->action) {
case mus::mojom::EventType::KEY_PRESSED:
web_event->type = event->key_data->is_char
? blink::WebInputEvent::Char
: blink::WebInputEvent::RawKeyDown;
break;
case mus::mojom::EventType::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 =
static_cast<int>(event->key_data->windows_key_code);
web_event->nativeKeyCode = event->key_data->native_key_code;
web_event->text[0] = event->key_data->text;
web_event->unmodifiedText[0] = event->key_data->unmodified_text;
web_event->setKeyIdentifierFromWindowsKeyCode();
return std::move(web_event);
}
scoped_ptr<blink::WebInputEvent> BuildWebMouseWheelEventFrom(
const mus::mojom::EventPtr& event) {
DCHECK(event->pointer_data && event->pointer_data->wheel_data);
const mus::mojom::WheelData& wheel_data = *event->pointer_data->wheel_data;
scoped_ptr<blink::WebMouseWheelEvent> web_event(
new blink::WebMouseWheelEvent);
web_event->type = blink::WebInputEvent::MouseWheel;
web_event->button = blink::WebMouseEvent::ButtonNone;
web_event->modifiers = EventFlagsToWebEventModifiers(event->flags);
web_event->timeStampSeconds = EventTimeToWebEventTime(event);
SetWebMouseEventLocation(*(event->pointer_data->location), 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 = wheel_data.delta_x;
web_event->deltaY = wheel_data.delta_y;
web_event->wheelTicksX = web_event->deltaX / ui::MouseWheelEvent::kWheelDelta;
web_event->wheelTicksY = web_event->deltaY / ui::MouseWheelEvent::kWheelDelta;
// TODO(rjkroege): Mandoline currently only generates WHEEL_MODE_LINE
// wheel events so the other modes are not yet tested. Verify that
// the implementation is correct.
switch (wheel_data.mode) {
case mus::mojom::WheelMode::PIXEL:
web_event->hasPreciseScrollingDeltas = true;
web_event->scrollByPage = false;
web_event->canScroll = true;
break;
case mus::mojom::WheelMode::LINE:
web_event->hasPreciseScrollingDeltas = false;
web_event->scrollByPage = false;
web_event->canScroll = true;
break;
case mus::mojom::WheelMode::PAGE:
web_event->hasPreciseScrollingDeltas = false;
web_event->scrollByPage = true;
web_event->canScroll = true;
break;
case mus::mojom::WheelMode::SCALING:
web_event->hasPreciseScrollingDeltas = false;
web_event->scrollByPage = false;
web_event->canScroll = false;
break;
}
return std::move(web_event);
}
void SetWebTouchEventLocation(const mus::mojom::PointerData& pointer_data,
mus::mojom::EventType action,
blink::WebTouchPoint* touch) {
if (pointer_data.location) {
touch->position.x = pointer_data.location->x;
touch->position.y = pointer_data.location->y;
touch->screenPosition.x = pointer_data.location->screen_x;
touch->screenPosition.y = pointer_data.location->screen_y;
}
if (pointer_data.brush_data) {
touch->radiusX = pointer_data.brush_data->width;
touch->radiusY = pointer_data.brush_data->height;
}
touch->pointerType = blink::WebPointerProperties::PointerType::Touch;
switch (action) {
case mus::mojom::EventType::POINTER_DOWN:
touch->state = blink::WebTouchPoint::StatePressed;
break;
case mus::mojom::EventType::POINTER_UP:
touch->state = blink::WebTouchPoint::StateReleased;
break;
case mus::mojom::EventType::POINTER_MOVE:
touch->state = blink::WebTouchPoint::StateMoved;
break;
case mus::mojom::EventType::POINTER_CANCEL:
touch->state = blink::WebTouchPoint::StateCancelled;
break;
case mus::mojom::EventType::UNKNOWN:
case mus::mojom::EventType::KEY_PRESSED:
case mus::mojom::EventType::KEY_RELEASED:
case mus::mojom::EventType::MOUSE_EXIT:
case mus::mojom::EventType::WHEEL:
NOTIMPLEMENTED() << "Received non touch event action: " << action;
break;
}
}
scoped_ptr<blink::WebInputEvent> BuildWebTouchEvent(
const mus::mojom::EventPtr& event) {
scoped_ptr<blink::WebTouchEvent> web_event(new blink::WebTouchEvent);
// TODO(jonross): we will need to buffer input events, as blink expects all
// active touch points to be in each WebInputEvent (crbug.com/578160)
if (event->pointer_data) {
SetWebTouchEventLocation(
*event->pointer_data, event->action,
&web_event->touches[event->pointer_data->pointer_id]);
}
web_event->modifiers = EventFlagsToWebEventModifiers(event->flags);
web_event->timeStampSeconds = EventTimeToWebEventTime(event);
web_event->uniqueTouchEventId = ui::GetNextTouchEventId();
switch (event->action) {
case mus::mojom::EventType::POINTER_DOWN:
web_event->type = blink::WebInputEvent::TouchStart;
break;
case mus::mojom::EventType::POINTER_UP:
web_event->type = blink::WebInputEvent::TouchEnd;
break;
case mus::mojom::EventType::POINTER_MOVE:
web_event->type = blink::WebInputEvent::TouchMove;
break;
case mus::mojom::EventType::POINTER_CANCEL:
web_event->type = blink::WebInputEvent::TouchCancel;
break;
case mus::mojom::EventType::UNKNOWN:
case mus::mojom::EventType::KEY_PRESSED:
case mus::mojom::EventType::KEY_RELEASED:
case mus::mojom::EventType::MOUSE_EXIT:
case mus::mojom::EventType::WHEEL:
NOTIMPLEMENTED() << "Received non touch event action: " << event->action;
break;
}
return std::move(web_event);
}
} // namespace
// static
scoped_ptr<blink::WebInputEvent>
TypeConverter<scoped_ptr<blink::WebInputEvent>, mus::mojom::EventPtr>::Convert(
const mus::mojom::EventPtr& event) {
switch (event->action) {
case mus::mojom::EventType::POINTER_DOWN:
case mus::mojom::EventType::POINTER_UP:
case mus::mojom::EventType::POINTER_CANCEL:
case mus::mojom::EventType::POINTER_MOVE:
case mus::mojom::EventType::MOUSE_EXIT:
if (event->pointer_data) {
switch (event->pointer_data->kind) {
case mus::mojom::PointerKind::MOUSE:
return BuildWebMouseEventFrom(event);
case mus::mojom::PointerKind::PEN:
return nullptr;
case mus::mojom::PointerKind::TOUCH:
return BuildWebTouchEvent(event);
}
}
return nullptr;
case mus::mojom::EventType::WHEEL:
return BuildWebMouseWheelEventFrom(event);
case mus::mojom::EventType::KEY_PRESSED:
case mus::mojom::EventType::KEY_RELEASED:
return BuildWebKeyboardEvent(event);
case mus::mojom::EventType::UNKNOWN:
return nullptr;
}
return nullptr;
}
} // namespace mojo