blob: ff1a2cb08c77d2675a4641689dbfa5038bb5fbb5 [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/services/html_viewer/blink_input_events_type_converters.h"
#include "base/logging.h"
#include "base/time/time.h"
#include "mojo/services/public/interfaces/input_events/input_event_constants.mojom.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
namespace mojo {
namespace {
// Used for scrolling. This matches Firefox behavior.
const int kPixelsPerTick = 53;
int EventFlagsToWebEventModifiers(int flags) {
int modifiers = 0;
if (flags & mojo::EVENT_FLAGS_SHIFT_DOWN)
modifiers |= blink::WebInputEvent::ShiftKey;
if (flags & mojo::EVENT_FLAGS_CONTROL_DOWN)
modifiers |= blink::WebInputEvent::ControlKey;
if (flags & mojo::EVENT_FLAGS_ALT_DOWN)
modifiers |= blink::WebInputEvent::AltKey;
// TODO(beng): MetaKey/META_MASK
if (flags & mojo::EVENT_FLAGS_LEFT_MOUSE_BUTTON)
modifiers |= blink::WebInputEvent::LeftButtonDown;
if (flags & mojo::EVENT_FLAGS_MIDDLE_MOUSE_BUTTON)
modifiers |= blink::WebInputEvent::MiddleButtonDown;
if (flags & mojo::EVENT_FLAGS_RIGHT_MOUSE_BUTTON)
modifiers |= blink::WebInputEvent::RightButtonDown;
if (flags & mojo::EVENT_FLAGS_CAPS_LOCK_DOWN)
modifiers |= blink::WebInputEvent::CapsLockOn;
return modifiers;
}
int EventFlagsToWebInputEventModifiers(int flags) {
return
(flags & mojo::EVENT_FLAGS_SHIFT_DOWN ?
blink::WebInputEvent::ShiftKey : 0) |
(flags & mojo::EVENT_FLAGS_CONTROL_DOWN ?
blink::WebInputEvent::ControlKey : 0) |
(flags & mojo::EVENT_FLAGS_CAPS_LOCK_DOWN ?
blink::WebInputEvent::CapsLockOn : 0) |
(flags & mojo::EVENT_FLAGS_ALT_DOWN ?
blink::WebInputEvent::AltKey : 0);
}
int GetClickCount(int flags) {
if (flags & mojo::MOUSE_EVENT_FLAGS_IS_TRIPLE_CLICK)
return 3;
else if (flags & mojo::MOUSE_EVENT_FLAGS_IS_DOUBLE_CLICK)
return 2;
return 1;
}
scoped_ptr<blink::WebInputEvent> BuildWebMouseEventFrom(const EventPtr& event) {
scoped_ptr<blink::WebMouseEvent> web_event(new blink::WebMouseEvent);
web_event->x = event->location_data->in_view_location->x;
web_event->y = event->location_data->in_view_location->y;
// TODO(erg): Remove this if check once we can rely on screen_location
// actually being passed to us. As written today, getting the screen
// location from ui::Event objects can only be done by querying the
// underlying native events, so all synthesized events don't have screen
// locations.
if (!event->location_data->screen_location.is_null()) {
web_event->globalX = event->location_data->screen_location->x;
web_event->globalY = event->location_data->screen_location->y;
}
web_event->modifiers = EventFlagsToWebEventModifiers(event->flags);
web_event->timeStampSeconds =
base::TimeDelta::FromInternalValue(event->time_stamp).InSecondsF();
web_event->button = blink::WebMouseEvent::ButtonNone;
if (event->flags & mojo::EVENT_FLAGS_LEFT_MOUSE_BUTTON)
web_event->button = blink::WebMouseEvent::ButtonLeft;
if (event->flags & mojo::EVENT_FLAGS_MIDDLE_MOUSE_BUTTON)
web_event->button = blink::WebMouseEvent::ButtonMiddle;
if (event->flags & mojo::EVENT_FLAGS_RIGHT_MOUSE_BUTTON)
web_event->button = blink::WebMouseEvent::ButtonRight;
switch (event->action) {
case EVENT_TYPE_MOUSE_PRESSED:
web_event->type = blink::WebInputEvent::MouseDown;
break;
case EVENT_TYPE_MOUSE_RELEASED:
web_event->type = blink::WebInputEvent::MouseUp;
break;
case EVENT_TYPE_MOUSE_ENTERED:
web_event->type = blink::WebInputEvent::MouseLeave;
web_event->button = blink::WebMouseEvent::ButtonNone;
break;
case EVENT_TYPE_MOUSE_EXITED:
case EVENT_TYPE_MOUSE_MOVED:
case EVENT_TYPE_MOUSE_DRAGGED:
web_event->type = blink::WebInputEvent::MouseMove;
break;
default:
NOTIMPLEMENTED() << "Received unexpected event: " << event->action;
break;
}
web_event->clickCount = GetClickCount(event->flags);
return web_event.PassAs<blink::WebInputEvent>();
}
scoped_ptr<blink::WebInputEvent> BuildWebKeyboardEvent(
const EventPtr& event) {
scoped_ptr<blink::WebKeyboardEvent> web_event(new blink::WebKeyboardEvent);
web_event->modifiers = EventFlagsToWebInputEventModifiers(event->flags);
web_event->timeStampSeconds =
base::TimeDelta::FromInternalValue(event->time_stamp).InSecondsF();
switch (event->action) {
case EVENT_TYPE_KEY_PRESSED:
web_event->type = event->key_data->is_char ? blink::WebInputEvent::Char :
blink::WebInputEvent::RawKeyDown;
break;
case EVENT_TYPE_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->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 web_event.PassAs<blink::WebInputEvent>();
}
scoped_ptr<blink::WebInputEvent> BuildWebMouseWheelEventFrom(
const EventPtr& event) {
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 =
base::TimeDelta::FromInternalValue(event->time_stamp).InSecondsF();
web_event->x = event->location_data->in_view_location->x;
web_event->y = event->location_data->in_view_location->y;
// TODO(erg): Remove this null check as parallel to above.
if (!event->location_data->screen_location.is_null()) {
web_event->globalX = event->location_data->screen_location->x;
web_event->globalY = event->location_data->screen_location->y;
}
if ((event->flags & mojo::EVENT_FLAGS_SHIFT_DOWN) != 0 &&
event->wheel_data->x_offset == 0) {
web_event->deltaX = event->wheel_data->y_offset;
web_event->deltaY = 0;
} else {
web_event->deltaX = event->wheel_data->x_offset;
web_event->deltaY = event->wheel_data->y_offset;
}
web_event->wheelTicksX = web_event->deltaX / kPixelsPerTick;
web_event->wheelTicksY = web_event->deltaY / kPixelsPerTick;
return web_event.PassAs<blink::WebInputEvent>();
}
} // namespace
// static
scoped_ptr<blink::WebInputEvent>
TypeConverter<scoped_ptr<blink::WebInputEvent>, EventPtr>::Convert(
const EventPtr& event) {
if (event->action == EVENT_TYPE_MOUSE_PRESSED ||
event->action == EVENT_TYPE_MOUSE_RELEASED ||
event->action == EVENT_TYPE_MOUSE_ENTERED ||
event->action == EVENT_TYPE_MOUSE_EXITED ||
event->action == EVENT_TYPE_MOUSE_MOVED ||
event->action == EVENT_TYPE_MOUSE_DRAGGED) {
return BuildWebMouseEventFrom(event);
} else if ((event->action == EVENT_TYPE_KEY_PRESSED ||
event->action == EVENT_TYPE_KEY_RELEASED) &&
event->key_data) {
return BuildWebKeyboardEvent(event);
} else if (event->action == EVENT_TYPE_MOUSEWHEEL) {
return BuildWebMouseWheelEventFrom(event);
}
return scoped_ptr<blink::WebInputEvent>();
}
} // namespace mojo