Home | History | Annotate | Download | only in blink
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "mojo/converters/blink/blink_input_events_type_converters.h"
      6 
      7 #include <utility>
      8 
      9 #include "base/logging.h"
     10 #include "base/time/time.h"
     11 #include "third_party/WebKit/public/web/WebInputEvent.h"
     12 #include "ui/events/base_event_utils.h"
     13 #include "ui/events/event.h"
     14 #include "ui/events/keycodes/dom/keycode_converter.h"
     15 
     16 namespace mojo {
     17 namespace {
     18 
     19 // TODO(majidvp): remove this and directly use ui::EventFlagsToWebEventModifiers
     20 int EventFlagsToWebEventModifiers(int flags) {
     21   int modifiers = 0;
     22 
     23   if (flags & ui::EF_SHIFT_DOWN)
     24     modifiers |= blink::WebInputEvent::ShiftKey;
     25   if (flags & ui::EF_CONTROL_DOWN)
     26     modifiers |= blink::WebInputEvent::ControlKey;
     27   if (flags & ui::EF_ALT_DOWN)
     28     modifiers |= blink::WebInputEvent::AltKey;
     29   // TODO(beng): MetaKey/META_MASK
     30   if (flags & ui::EF_LEFT_MOUSE_BUTTON)
     31     modifiers |= blink::WebInputEvent::LeftButtonDown;
     32   if (flags & ui::EF_MIDDLE_MOUSE_BUTTON)
     33     modifiers |= blink::WebInputEvent::MiddleButtonDown;
     34   if (flags & ui::EF_RIGHT_MOUSE_BUTTON)
     35     modifiers |= blink::WebInputEvent::RightButtonDown;
     36   if (flags & ui::EF_CAPS_LOCK_ON)
     37     modifiers |= blink::WebInputEvent::CapsLockOn;
     38   return modifiers;
     39 }
     40 
     41 // TODO(majidvp): remove this and directly use ui::EventFlagsToWebEventModifiers
     42 int EventFlagsToWebInputEventModifiers(int flags) {
     43   return (flags & ui::EF_SHIFT_DOWN ? blink::WebInputEvent::ShiftKey : 0) |
     44          (flags & ui::EF_CONTROL_DOWN ? blink::WebInputEvent::ControlKey : 0) |
     45          (flags & ui::EF_CAPS_LOCK_ON ? blink::WebInputEvent::CapsLockOn : 0) |
     46          (flags & ui::EF_ALT_DOWN ? blink::WebInputEvent::AltKey : 0);
     47 }
     48 
     49 int GetClickCount(int flags) {
     50   if (flags & ui::EF_IS_TRIPLE_CLICK)
     51     return 3;
     52   else if (flags & ui::EF_IS_DOUBLE_CLICK)
     53     return 2;
     54 
     55   return 1;
     56 }
     57 
     58 void SetWebMouseEventLocation(const ui::LocatedEvent& located_event,
     59                               blink::WebMouseEvent* web_event) {
     60   web_event->x = static_cast<int>(located_event.x());
     61   web_event->y = static_cast<int>(located_event.y());
     62   web_event->globalX = static_cast<int>(located_event.root_location_f().x());
     63   web_event->globalY = static_cast<int>(located_event.root_location_f().y());
     64 }
     65 
     66 std::unique_ptr<blink::WebInputEvent> BuildWebMouseEventFrom(
     67     const ui::PointerEvent& event) {
     68   std::unique_ptr<blink::WebMouseEvent> web_event(new blink::WebMouseEvent);
     69 
     70   web_event->pointerType = blink::WebPointerProperties::PointerType::Mouse;
     71   SetWebMouseEventLocation(event, web_event.get());
     72 
     73   web_event->modifiers = EventFlagsToWebEventModifiers(event.flags());
     74   web_event->timeStampSeconds = ui::EventTimeStampToSeconds(event.time_stamp());
     75 
     76   web_event->button = blink::WebMouseEvent::ButtonNone;
     77   if (event.flags() & ui::EF_LEFT_MOUSE_BUTTON)
     78     web_event->button = blink::WebMouseEvent::ButtonLeft;
     79   if (event.flags() & ui::EF_MIDDLE_MOUSE_BUTTON)
     80     web_event->button = blink::WebMouseEvent::ButtonMiddle;
     81   if (event.flags() & ui::EF_RIGHT_MOUSE_BUTTON)
     82     web_event->button = blink::WebMouseEvent::ButtonRight;
     83 
     84   switch (event.type()) {
     85     case ui::ET_POINTER_DOWN:
     86       web_event->type = blink::WebInputEvent::MouseDown;
     87       break;
     88     case ui::ET_POINTER_UP:
     89       web_event->type = blink::WebInputEvent::MouseUp;
     90       break;
     91     case ui::ET_POINTER_MOVED:
     92       web_event->type = blink::WebInputEvent::MouseMove;
     93       break;
     94     case ui::ET_MOUSE_EXITED:
     95       web_event->type = blink::WebInputEvent::MouseLeave;
     96       break;
     97     default:
     98       NOTIMPLEMENTED() << "Received unexpected event: " << event.type();
     99       break;
    100   }
    101 
    102   web_event->clickCount = GetClickCount(event.flags());
    103 
    104   return std::move(web_event);
    105 }
    106 
    107 std::unique_ptr<blink::WebInputEvent> BuildWebKeyboardEvent(
    108     const ui::KeyEvent& event) {
    109   std::unique_ptr<blink::WebKeyboardEvent> web_event(
    110       new blink::WebKeyboardEvent);
    111 
    112   web_event->modifiers = EventFlagsToWebInputEventModifiers(event.flags());
    113   web_event->timeStampSeconds = ui::EventTimeStampToSeconds(event.time_stamp());
    114 
    115   switch (event.type()) {
    116     case ui::ET_KEY_PRESSED:
    117       web_event->type = event.is_char() ? blink::WebInputEvent::Char
    118                                         : blink::WebInputEvent::RawKeyDown;
    119       break;
    120     case ui::ET_KEY_RELEASED:
    121       web_event->type = blink::WebInputEvent::KeyUp;
    122       break;
    123     default:
    124       NOTREACHED();
    125   }
    126 
    127   if (web_event->modifiers & blink::WebInputEvent::AltKey)
    128     web_event->isSystemKey = true;
    129 
    130   web_event->windowsKeyCode = event.GetLocatedWindowsKeyboardCode();
    131   web_event->nativeKeyCode =
    132       ui::KeycodeConverter::DomCodeToNativeKeycode(event.code());
    133   web_event->text[0] = event.GetText();
    134   web_event->unmodifiedText[0] = event.GetUnmodifiedText();
    135   return std::move(web_event);
    136 }
    137 
    138 std::unique_ptr<blink::WebInputEvent> BuildWebMouseWheelEventFrom(
    139     const ui::MouseWheelEvent& event) {
    140   std::unique_ptr<blink::WebMouseWheelEvent> web_event(
    141       new blink::WebMouseWheelEvent);
    142   web_event->type = blink::WebInputEvent::MouseWheel;
    143   web_event->button = blink::WebMouseEvent::ButtonNone;
    144   web_event->modifiers = EventFlagsToWebEventModifiers(event.flags());
    145   web_event->timeStampSeconds = ui::EventTimeStampToSeconds(event.time_stamp());
    146 
    147   SetWebMouseEventLocation(event, web_event.get());
    148 
    149   // TODO(rjkroege): Update the following code once Blink supports
    150   // DOM Level 3 wheel events
    151   // (http://www.w3.org/TR/DOM-Level-3-Events/#events-wheelevents)
    152   web_event->deltaX = event.x_offset();
    153   web_event->deltaY = event.y_offset();
    154 
    155   web_event->wheelTicksX = web_event->deltaX / ui::MouseWheelEvent::kWheelDelta;
    156   web_event->wheelTicksY = web_event->deltaY / ui::MouseWheelEvent::kWheelDelta;
    157 
    158   // TODO(moshayedi): ui::WheelEvent currently only supports WHEEL_MODE_LINE.
    159   // Add support for other wheel modes once ui::WheelEvent has support for them.
    160   web_event->hasPreciseScrollingDeltas = false;
    161   web_event->scrollByPage = false;
    162 
    163   return std::move(web_event);
    164 }
    165 
    166 void SetWebTouchEventLocation(const ui::PointerEvent& event,
    167                               blink::WebTouchPoint* touch) {
    168   touch->position.x = event.x();
    169   touch->position.y = event.y();
    170   touch->screenPosition.x = event.root_location_f().x();
    171   touch->screenPosition.y = event.root_location_f().y();
    172 }
    173 
    174 std::unique_ptr<blink::WebInputEvent> BuildWebTouchEvent(
    175     const ui::PointerEvent& event) {
    176   std::unique_ptr<blink::WebTouchEvent> web_event(new blink::WebTouchEvent);
    177   blink::WebTouchPoint* touch = &web_event->touches[event.pointer_id()];
    178 
    179   // TODO(jonross): we will need to buffer input events, as blink expects all
    180   // active touch points to be in each WebInputEvent (crbug.com/578160)
    181   SetWebTouchEventLocation(event, touch);
    182   touch->pointerType = blink::WebPointerProperties::PointerType::Touch;
    183   touch->radiusX = event.pointer_details().radius_x;
    184   touch->radiusY = event.pointer_details().radius_y;
    185 
    186   web_event->modifiers = EventFlagsToWebEventModifiers(event.flags());
    187   web_event->timeStampSeconds = ui::EventTimeStampToSeconds(event.time_stamp());
    188   web_event->uniqueTouchEventId = ui::GetNextTouchEventId();
    189 
    190   switch (event.type()) {
    191     case ui::ET_POINTER_DOWN:
    192       web_event->type = blink::WebInputEvent::TouchStart;
    193       touch->state = blink::WebTouchPoint::StatePressed;
    194       break;
    195     case ui::ET_POINTER_UP:
    196       web_event->type = blink::WebInputEvent::TouchEnd;
    197       touch->state = blink::WebTouchPoint::StateReleased;
    198       break;
    199     case ui::ET_POINTER_MOVED:
    200       web_event->type = blink::WebInputEvent::TouchMove;
    201       touch->state = blink::WebTouchPoint::StateMoved;
    202       break;
    203     case ui::ET_POINTER_CANCELLED:
    204       web_event->type = blink::WebInputEvent::TouchCancel;
    205       touch->state = blink::WebTouchPoint::StateCancelled;
    206       break;
    207     default:
    208       NOTIMPLEMENTED() << "Received non touch pointer event action: "
    209                        << event.type();
    210       break;
    211   }
    212 
    213   return std::move(web_event);
    214 }
    215 
    216 }  // namespace
    217 
    218 // static
    219 std::unique_ptr<blink::WebInputEvent>
    220 TypeConverter<std::unique_ptr<blink::WebInputEvent>, ui::Event>::Convert(
    221     const ui::Event& event) {
    222   DCHECK(event.IsKeyEvent() || event.IsPointerEvent() ||
    223          event.IsMouseWheelEvent());
    224   switch (event.type()) {
    225     case ui::ET_POINTER_DOWN:
    226     case ui::ET_POINTER_UP:
    227     case ui::ET_POINTER_CANCELLED:
    228     case ui::ET_POINTER_MOVED:
    229     case ui::ET_POINTER_EXITED:
    230       if (event.IsMousePointerEvent())
    231         return BuildWebMouseEventFrom(*event.AsPointerEvent());
    232       else if (event.IsTouchPointerEvent())
    233         return BuildWebTouchEvent(*event.AsPointerEvent());
    234       else
    235         return nullptr;
    236     case ui::ET_MOUSEWHEEL:
    237       return BuildWebMouseWheelEventFrom(*event.AsMouseWheelEvent());
    238     case ui::ET_KEY_PRESSED:
    239     case ui::ET_KEY_RELEASED:
    240       return BuildWebKeyboardEvent(*event.AsKeyEvent());
    241     default:
    242       return nullptr;
    243   }
    244 }
    245 
    246 }  // namespace mojo
    247