Home | History | Annotate | Download | only in renderer_host
      1 // Copyright (c) 2012 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 "content/browser/renderer_host/web_input_event_aura.h"
      6 
      7 #include "content/browser/renderer_host/input/web_input_event_util.h"
      8 #include "content/browser/renderer_host/ui_events_helper.h"
      9 #include "ui/aura/window.h"
     10 #include "ui/events/event.h"
     11 #include "ui/events/event_utils.h"
     12 
     13 #if defined(USE_X11) || defined(USE_OZONE)
     14 #include "ui/events/keycodes/dom4/keycode_converter.h"
     15 #endif
     16 
     17 namespace content {
     18 
     19 #if defined(OS_WIN)
     20 blink::WebMouseEvent MakeUntranslatedWebMouseEventFromNativeEvent(
     21     const base::NativeEvent& native_event);
     22 blink::WebMouseWheelEvent MakeUntranslatedWebMouseWheelEventFromNativeEvent(
     23     const base::NativeEvent& native_event);
     24 blink::WebKeyboardEvent MakeWebKeyboardEventFromNativeEvent(
     25     const base::NativeEvent& native_event);
     26 blink::WebGestureEvent MakeWebGestureEventFromNativeEvent(
     27     const base::NativeEvent& native_event);
     28 #endif
     29 #if defined(USE_X11) || defined(USE_OZONE)
     30 blink::WebKeyboardEvent MakeWebKeyboardEventFromAuraEvent(
     31     ui::KeyEvent* event) {
     32   blink::WebKeyboardEvent webkit_event;
     33 
     34   webkit_event.timeStampSeconds = event->time_stamp().InSecondsF();
     35   webkit_event.modifiers = EventFlagsToWebEventModifiers(event->flags());
     36 
     37   switch (event->type()) {
     38     case ui::ET_KEY_PRESSED:
     39       webkit_event.type = event->is_char() ? blink::WebInputEvent::Char :
     40           blink::WebInputEvent::RawKeyDown;
     41       break;
     42     case ui::ET_KEY_RELEASED:
     43       webkit_event.type = blink::WebInputEvent::KeyUp;
     44       break;
     45     default:
     46       NOTREACHED();
     47   }
     48 
     49   if (webkit_event.modifiers & blink::WebInputEvent::AltKey)
     50     webkit_event.isSystemKey = true;
     51 
     52   webkit_event.windowsKeyCode = event->GetLocatedWindowsKeyboardCode();
     53   webkit_event.nativeKeyCode =
     54     ui::KeycodeConverter::CodeToNativeKeycode(event->code().c_str());
     55   webkit_event.unmodifiedText[0] = event->GetUnmodifiedText();
     56   webkit_event.text[0] = event->GetText();
     57 
     58   webkit_event.setKeyIdentifierFromWindowsKeyCode();
     59 
     60   return webkit_event;
     61 }
     62 
     63 blink::WebMouseWheelEvent MakeWebMouseWheelEventFromAuraEvent(
     64     ui::ScrollEvent* event) {
     65   blink::WebMouseWheelEvent webkit_event;
     66 
     67   webkit_event.type = blink::WebInputEvent::MouseWheel;
     68   webkit_event.button = blink::WebMouseEvent::ButtonNone;
     69   webkit_event.modifiers = EventFlagsToWebEventModifiers(event->flags());
     70   webkit_event.timeStampSeconds = event->time_stamp().InSecondsF();
     71   webkit_event.hasPreciseScrollingDeltas = true;
     72 
     73   float offset_ordinal_x = 0.f;
     74   float offset_ordinal_y = 0.f;
     75   if ((event->flags() & ui::EF_SHIFT_DOWN) != 0 && event->x_offset() == 0) {
     76     webkit_event.deltaX = event->y_offset();
     77     webkit_event.deltaY = 0;
     78     offset_ordinal_x = event->y_offset_ordinal();
     79     offset_ordinal_y = event->x_offset_ordinal();
     80   } else {
     81     webkit_event.deltaX = event->x_offset();
     82     webkit_event.deltaY = event->y_offset();
     83     offset_ordinal_x = event->x_offset_ordinal();
     84     offset_ordinal_y = event->y_offset_ordinal();
     85   }
     86 
     87   if (offset_ordinal_x != 0.f && webkit_event.deltaX != 0.f)
     88     webkit_event.accelerationRatioX = offset_ordinal_x / webkit_event.deltaX;
     89   webkit_event.wheelTicksX = webkit_event.deltaX / kPixelsPerTick;
     90   webkit_event.wheelTicksY = webkit_event.deltaY / kPixelsPerTick;
     91   if (offset_ordinal_y != 0.f && webkit_event.deltaY != 0.f)
     92     webkit_event.accelerationRatioY = offset_ordinal_y / webkit_event.deltaY;
     93   return webkit_event;
     94 }
     95 
     96 blink::WebGestureEvent MakeWebGestureEventFromAuraEvent(
     97     ui::ScrollEvent* event) {
     98   blink::WebGestureEvent webkit_event;
     99 
    100   switch (event->type()) {
    101     case ui::ET_SCROLL_FLING_START:
    102       webkit_event.type = blink::WebInputEvent::GestureFlingStart;
    103       webkit_event.data.flingStart.velocityX = event->x_offset();
    104       webkit_event.data.flingStart.velocityY = event->y_offset();
    105       break;
    106     case ui::ET_SCROLL_FLING_CANCEL:
    107       webkit_event.type = blink::WebInputEvent::GestureFlingCancel;
    108       break;
    109     case ui::ET_SCROLL:
    110       NOTREACHED() << "Invalid gesture type: " << event->type();
    111       break;
    112     default:
    113       NOTREACHED() << "Unknown gesture type: " << event->type();
    114   }
    115 
    116   webkit_event.sourceDevice = blink::WebGestureDeviceTouchpad;
    117   webkit_event.modifiers = EventFlagsToWebEventModifiers(event->flags());
    118   webkit_event.timeStampSeconds = event->time_stamp().InSecondsF();
    119   return webkit_event;
    120 }
    121 
    122 #endif
    123 
    124 blink::WebMouseEvent MakeWebMouseEventFromAuraEvent(
    125     ui::MouseEvent* event);
    126 blink::WebMouseWheelEvent MakeWebMouseWheelEventFromAuraEvent(
    127     ui::MouseWheelEvent* event);
    128 
    129 // General approach:
    130 //
    131 // ui::Event only carries a subset of possible event data provided to Aura by
    132 // the host platform. WebKit utilizes a larger subset of that information than
    133 // Aura itself. WebKit includes some built in cracking functionality that we
    134 // rely on to obtain this information cleanly and consistently.
    135 //
    136 // The only place where an ui::Event's data differs from what the underlying
    137 // base::NativeEvent would provide is position data, since we would like to
    138 // provide coordinates relative to the aura::Window that is hosting the
    139 // renderer, not the top level platform window.
    140 //
    141 // The approach is to fully construct a blink::WebInputEvent from the
    142 // ui::Event's base::NativeEvent, and then replace the coordinate fields with
    143 // the translated values from the ui::Event.
    144 //
    145 // The exception is mouse events on linux. The ui::MouseEvent contains enough
    146 // necessary information to construct a WebMouseEvent. So instead of extracting
    147 // the information from the XEvent, which can be tricky when supporting both
    148 // XInput2 and XInput, the WebMouseEvent is constructed from the
    149 // ui::MouseEvent. This will not be necessary once only XInput2 is supported.
    150 //
    151 
    152 blink::WebMouseEvent MakeWebMouseEvent(ui::MouseEvent* event) {
    153   // Construct an untranslated event from the platform event data.
    154   blink::WebMouseEvent webkit_event =
    155 #if defined(OS_WIN)
    156   // On Windows we have WM_ events comming from desktop and pure aura
    157   // events comming from metro mode.
    158   event->native_event().message ?
    159       MakeUntranslatedWebMouseEventFromNativeEvent(event->native_event()) :
    160       MakeWebMouseEventFromAuraEvent(event);
    161 #else
    162   MakeWebMouseEventFromAuraEvent(event);
    163 #endif
    164   // Replace the event's coordinate fields with translated position data from
    165   // |event|.
    166   webkit_event.windowX = webkit_event.x = event->x();
    167   webkit_event.windowY = webkit_event.y = event->y();
    168 
    169 #if defined(OS_WIN)
    170   if (event->native_event().message)
    171     return webkit_event;
    172 #endif
    173   const gfx::Point root_point = event->root_location();
    174   webkit_event.globalX = root_point.x();
    175   webkit_event.globalY = root_point.y();
    176 
    177   return webkit_event;
    178 }
    179 
    180 blink::WebMouseWheelEvent MakeWebMouseWheelEvent(ui::MouseWheelEvent* event) {
    181 #if defined(OS_WIN)
    182   // Construct an untranslated event from the platform event data.
    183   blink::WebMouseWheelEvent webkit_event = event->native_event().message ?
    184       MakeUntranslatedWebMouseWheelEventFromNativeEvent(event->native_event()) :
    185       MakeWebMouseWheelEventFromAuraEvent(event);
    186 #else
    187   blink::WebMouseWheelEvent webkit_event =
    188       MakeWebMouseWheelEventFromAuraEvent(event);
    189 #endif
    190 
    191   // Replace the event's coordinate fields with translated position data from
    192   // |event|.
    193   webkit_event.windowX = webkit_event.x = event->x();
    194   webkit_event.windowY = webkit_event.y = event->y();
    195 
    196   const gfx::Point root_point = event->root_location();
    197   webkit_event.globalX = root_point.x();
    198   webkit_event.globalY = root_point.y();
    199 
    200   return webkit_event;
    201 }
    202 
    203 blink::WebMouseWheelEvent MakeWebMouseWheelEvent(ui::ScrollEvent* event) {
    204 #if defined(OS_WIN)
    205   // Construct an untranslated event from the platform event data.
    206   blink::WebMouseWheelEvent webkit_event =
    207       MakeUntranslatedWebMouseWheelEventFromNativeEvent(event->native_event());
    208 #else
    209   blink::WebMouseWheelEvent webkit_event =
    210       MakeWebMouseWheelEventFromAuraEvent(event);
    211 #endif
    212 
    213   // Replace the event's coordinate fields with translated position data from
    214   // |event|.
    215   webkit_event.windowX = webkit_event.x = event->x();
    216   webkit_event.windowY = webkit_event.y = event->y();
    217 
    218   const gfx::Point root_point = event->root_location();
    219   webkit_event.globalX = root_point.x();
    220   webkit_event.globalY = root_point.y();
    221 
    222   return webkit_event;
    223 }
    224 
    225 blink::WebKeyboardEvent MakeWebKeyboardEvent(ui::KeyEvent* event) {
    226   // Windows can figure out whether or not to construct a RawKeyDown or a Char
    227   // WebInputEvent based on the type of message carried in
    228   // event->native_event(). X11 is not so fortunate, there is no separate
    229   // translated event type, so DesktopHostLinux sends an extra KeyEvent with
    230   // is_char() == true. We need to pass the ui::KeyEvent to the X11 function
    231   // to detect this case so the right event type can be constructed.
    232 #if defined(OS_WIN)
    233   if (!event->HasNativeEvent())
    234     return blink::WebKeyboardEvent();
    235 
    236   // Key events require no translation by the aura system.
    237   return MakeWebKeyboardEventFromNativeEvent(event->native_event());
    238 #else
    239   return MakeWebKeyboardEventFromAuraEvent(event);
    240 #endif
    241 }
    242 
    243 blink::WebGestureEvent MakeWebGestureEvent(ui::GestureEvent* event) {
    244   blink::WebGestureEvent gesture_event;
    245 #if defined(OS_WIN)
    246   if (event->HasNativeEvent())
    247     gesture_event = MakeWebGestureEventFromNativeEvent(event->native_event());
    248   else
    249     gesture_event = MakeWebGestureEventFromUIEvent(*event);
    250 #else
    251   gesture_event = MakeWebGestureEventFromUIEvent(*event);
    252 #endif
    253 
    254   gesture_event.x = event->x();
    255   gesture_event.y = event->y();
    256 
    257   const gfx::Point root_point = event->root_location();
    258   gesture_event.globalX = root_point.x();
    259   gesture_event.globalY = root_point.y();
    260 
    261   return gesture_event;
    262 }
    263 
    264 blink::WebGestureEvent MakeWebGestureEvent(ui::ScrollEvent* event) {
    265   blink::WebGestureEvent gesture_event;
    266 
    267 #if defined(OS_WIN)
    268   gesture_event = MakeWebGestureEventFromNativeEvent(event->native_event());
    269 #else
    270   gesture_event = MakeWebGestureEventFromAuraEvent(event);
    271 #endif
    272 
    273   gesture_event.x = event->x();
    274   gesture_event.y = event->y();
    275 
    276   const gfx::Point root_point = event->root_location();
    277   gesture_event.globalX = root_point.x();
    278   gesture_event.globalY = root_point.y();
    279 
    280   return gesture_event;
    281 }
    282 
    283 blink::WebGestureEvent MakeWebGestureEventFlingCancel() {
    284   blink::WebGestureEvent gesture_event;
    285 
    286   // All other fields are ignored on a GestureFlingCancel event.
    287   gesture_event.type = blink::WebInputEvent::GestureFlingCancel;
    288   gesture_event.sourceDevice = blink::WebGestureDeviceTouchpad;
    289   return gesture_event;
    290 }
    291 
    292 blink::WebMouseEvent MakeWebMouseEventFromAuraEvent(ui::MouseEvent* event) {
    293   blink::WebMouseEvent webkit_event;
    294 
    295   webkit_event.modifiers = EventFlagsToWebEventModifiers(event->flags());
    296   webkit_event.timeStampSeconds = event->time_stamp().InSecondsF();
    297 
    298   webkit_event.button = blink::WebMouseEvent::ButtonNone;
    299   int button_flags = event->flags();
    300   if (event->type() == ui::ET_MOUSE_PRESSED ||
    301       event->type() == ui::ET_MOUSE_RELEASED) {
    302     // We want to use changed_button_flags() for mouse pressed & released.
    303     // These flags can be used only if they are set which is not always the case
    304     // (see e.g. GetChangedMouseButtonFlagsFromNative() in events_win.cc).
    305     if (event->changed_button_flags())
    306       button_flags = event->changed_button_flags();
    307   }
    308   if (button_flags & ui::EF_LEFT_MOUSE_BUTTON)
    309     webkit_event.button = blink::WebMouseEvent::ButtonLeft;
    310   if (button_flags & ui::EF_MIDDLE_MOUSE_BUTTON)
    311     webkit_event.button = blink::WebMouseEvent::ButtonMiddle;
    312   if (button_flags & ui::EF_RIGHT_MOUSE_BUTTON)
    313     webkit_event.button = blink::WebMouseEvent::ButtonRight;
    314 
    315   switch (event->type()) {
    316     case ui::ET_MOUSE_PRESSED:
    317       webkit_event.type = blink::WebInputEvent::MouseDown;
    318       webkit_event.clickCount = event->GetClickCount();
    319       break;
    320     case ui::ET_MOUSE_RELEASED:
    321       webkit_event.type = blink::WebInputEvent::MouseUp;
    322       webkit_event.clickCount = event->GetClickCount();
    323       break;
    324     case ui::ET_MOUSE_ENTERED:
    325     case ui::ET_MOUSE_EXITED:
    326     case ui::ET_MOUSE_MOVED:
    327     case ui::ET_MOUSE_DRAGGED:
    328       webkit_event.type = blink::WebInputEvent::MouseMove;
    329       break;
    330     default:
    331       NOTIMPLEMENTED() << "Received unexpected event: " << event->type();
    332       break;
    333   }
    334 
    335   return webkit_event;
    336 }
    337 
    338 blink::WebMouseWheelEvent MakeWebMouseWheelEventFromAuraEvent(
    339     ui::MouseWheelEvent* event) {
    340   blink::WebMouseWheelEvent webkit_event;
    341 
    342   webkit_event.type = blink::WebInputEvent::MouseWheel;
    343   webkit_event.button = blink::WebMouseEvent::ButtonNone;
    344   webkit_event.modifiers = EventFlagsToWebEventModifiers(event->flags());
    345   webkit_event.timeStampSeconds = event->time_stamp().InSecondsF();
    346 
    347   if ((event->flags() & ui::EF_SHIFT_DOWN) != 0 && event->x_offset() == 0) {
    348     webkit_event.deltaX = event->y_offset();
    349     webkit_event.deltaY = 0;
    350   } else {
    351     webkit_event.deltaX = event->x_offset();
    352     webkit_event.deltaY = event->y_offset();
    353   }
    354 
    355   webkit_event.wheelTicksX = webkit_event.deltaX / kPixelsPerTick;
    356   webkit_event.wheelTicksY = webkit_event.deltaY / kPixelsPerTick;
    357 
    358   return webkit_event;
    359 }
    360 
    361 }  // namespace content
    362