Upstream version 11.40.277.0
[platform/framework/web/crosswalk.git] / src / content / browser / renderer_host / web_input_event_aura.cc
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