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.
5 #include "content/browser/renderer_host/web_input_event_aura.h"
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"
13 #if defined(USE_X11) || defined(USE_OZONE)
14 #include "ui/events/keycodes/dom4/keycode_converter.h"
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);
29 #if defined(USE_X11) || defined(USE_OZONE)
30 blink::WebKeyboardEvent MakeWebKeyboardEventFromAuraEvent(
31 ui::KeyEvent* event) {
32 blink::WebKeyboardEvent webkit_event;
34 webkit_event.timeStampSeconds = event->time_stamp().InSecondsF();
35 webkit_event.modifiers = EventFlagsToWebEventModifiers(event->flags());
37 switch (event->type()) {
38 case ui::ET_KEY_PRESSED:
39 webkit_event.type = event->is_char() ? blink::WebInputEvent::Char :
40 blink::WebInputEvent::RawKeyDown;
42 case ui::ET_KEY_RELEASED:
43 webkit_event.type = blink::WebInputEvent::KeyUp;
49 if (webkit_event.modifiers & blink::WebInputEvent::AltKey)
50 webkit_event.isSystemKey = true;
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();
58 webkit_event.setKeyIdentifierFromWindowsKeyCode();
63 blink::WebMouseWheelEvent MakeWebMouseWheelEventFromAuraEvent(
64 ui::ScrollEvent* event) {
65 blink::WebMouseWheelEvent webkit_event;
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;
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();
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();
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;
96 blink::WebGestureEvent MakeWebGestureEventFromAuraEvent(
97 ui::ScrollEvent* event) {
98 blink::WebGestureEvent webkit_event;
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();
106 case ui::ET_SCROLL_FLING_CANCEL:
107 webkit_event.type = blink::WebInputEvent::GestureFlingCancel;
110 NOTREACHED() << "Invalid gesture type: " << event->type();
113 NOTREACHED() << "Unknown gesture type: " << event->type();
116 webkit_event.sourceDevice = blink::WebGestureDeviceTouchpad;
117 webkit_event.modifiers = EventFlagsToWebEventModifiers(event->flags());
118 webkit_event.timeStampSeconds = event->time_stamp().InSecondsF();
124 blink::WebMouseEvent MakeWebMouseEventFromAuraEvent(
125 ui::MouseEvent* event);
126 blink::WebMouseWheelEvent MakeWebMouseWheelEventFromAuraEvent(
127 ui::MouseWheelEvent* event);
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.
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.
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.
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.
152 blink::WebMouseEvent MakeWebMouseEvent(ui::MouseEvent* event) {
153 // Construct an untranslated event from the platform event data.
154 blink::WebMouseEvent webkit_event =
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);
162 MakeWebMouseEventFromAuraEvent(event);
164 // Replace the event's coordinate fields with translated position data from
166 webkit_event.windowX = webkit_event.x = event->x();
167 webkit_event.windowY = webkit_event.y = event->y();
170 if (event->native_event().message)
173 const gfx::Point root_point = event->root_location();
174 webkit_event.globalX = root_point.x();
175 webkit_event.globalY = root_point.y();
180 blink::WebMouseWheelEvent MakeWebMouseWheelEvent(ui::MouseWheelEvent* event) {
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);
187 blink::WebMouseWheelEvent webkit_event =
188 MakeWebMouseWheelEventFromAuraEvent(event);
191 // Replace the event's coordinate fields with translated position data from
193 webkit_event.windowX = webkit_event.x = event->x();
194 webkit_event.windowY = webkit_event.y = event->y();
196 const gfx::Point root_point = event->root_location();
197 webkit_event.globalX = root_point.x();
198 webkit_event.globalY = root_point.y();
203 blink::WebMouseWheelEvent MakeWebMouseWheelEvent(ui::ScrollEvent* event) {
205 // Construct an untranslated event from the platform event data.
206 blink::WebMouseWheelEvent webkit_event =
207 MakeUntranslatedWebMouseWheelEventFromNativeEvent(event->native_event());
209 blink::WebMouseWheelEvent webkit_event =
210 MakeWebMouseWheelEventFromAuraEvent(event);
213 // Replace the event's coordinate fields with translated position data from
215 webkit_event.windowX = webkit_event.x = event->x();
216 webkit_event.windowY = webkit_event.y = event->y();
218 const gfx::Point root_point = event->root_location();
219 webkit_event.globalX = root_point.x();
220 webkit_event.globalY = root_point.y();
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.
233 if (!event->HasNativeEvent())
234 return blink::WebKeyboardEvent();
236 // Key events require no translation by the aura system.
237 return MakeWebKeyboardEventFromNativeEvent(event->native_event());
239 return MakeWebKeyboardEventFromAuraEvent(event);
243 blink::WebGestureEvent MakeWebGestureEvent(ui::GestureEvent* event) {
244 blink::WebGestureEvent gesture_event;
246 if (event->HasNativeEvent())
247 gesture_event = MakeWebGestureEventFromNativeEvent(event->native_event());
249 gesture_event = MakeWebGestureEventFromUIEvent(*event);
251 gesture_event = MakeWebGestureEventFromUIEvent(*event);
254 gesture_event.x = event->x();
255 gesture_event.y = event->y();
257 const gfx::Point root_point = event->root_location();
258 gesture_event.globalX = root_point.x();
259 gesture_event.globalY = root_point.y();
261 return gesture_event;
264 blink::WebGestureEvent MakeWebGestureEvent(ui::ScrollEvent* event) {
265 blink::WebGestureEvent gesture_event;
268 gesture_event = MakeWebGestureEventFromNativeEvent(event->native_event());
270 gesture_event = MakeWebGestureEventFromAuraEvent(event);
273 gesture_event.x = event->x();
274 gesture_event.y = event->y();
276 const gfx::Point root_point = event->root_location();
277 gesture_event.globalX = root_point.x();
278 gesture_event.globalY = root_point.y();
280 return gesture_event;
283 blink::WebGestureEvent MakeWebGestureEventFlingCancel() {
284 blink::WebGestureEvent gesture_event;
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;
292 blink::WebMouseEvent MakeWebMouseEventFromAuraEvent(ui::MouseEvent* event) {
293 blink::WebMouseEvent webkit_event;
295 webkit_event.modifiers = EventFlagsToWebEventModifiers(event->flags());
296 webkit_event.timeStampSeconds = event->time_stamp().InSecondsF();
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();
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;
315 switch (event->type()) {
316 case ui::ET_MOUSE_PRESSED:
317 webkit_event.type = blink::WebInputEvent::MouseDown;
318 webkit_event.clickCount = event->GetClickCount();
320 case ui::ET_MOUSE_RELEASED:
321 webkit_event.type = blink::WebInputEvent::MouseUp;
322 webkit_event.clickCount = event->GetClickCount();
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;
331 NOTIMPLEMENTED() << "Received unexpected event: " << event->type();
338 blink::WebMouseWheelEvent MakeWebMouseWheelEventFromAuraEvent(
339 ui::MouseWheelEvent* event) {
340 blink::WebMouseWheelEvent webkit_event;
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();
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;
351 webkit_event.deltaX = event->x_offset();
352 webkit_event.deltaY = event->y_offset();
355 webkit_event.wheelTicksX = webkit_event.deltaX / kPixelsPerTick;
356 webkit_event.wheelTicksY = webkit_event.deltaY / kPixelsPerTick;
361 } // namespace content