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/ui_events_helper.h"
8 #include "ui/aura/window.h"
9 #include "ui/events/event.h"
10 #include "ui/events/event_utils.h"
12 #if defined(USE_OZONE)
13 #include "ui/events/keycodes/keyboard_code_conversion.h"
19 blink::WebMouseEvent
MakeUntranslatedWebMouseEventFromNativeEvent(
20 const base::NativeEvent
& native_event
);
21 blink::WebMouseWheelEvent
MakeUntranslatedWebMouseWheelEventFromNativeEvent(
22 const base::NativeEvent
& native_event
);
23 blink::WebKeyboardEvent
MakeWebKeyboardEventFromNativeEvent(
24 const base::NativeEvent
& native_event
);
25 blink::WebGestureEvent
MakeWebGestureEventFromNativeEvent(
26 const base::NativeEvent
& native_event
);
27 #elif defined(USE_X11)
28 blink::WebKeyboardEvent
MakeWebKeyboardEventFromAuraEvent(
30 #elif defined(USE_OZONE)
31 blink::WebKeyboardEvent
MakeWebKeyboardEventFromAuraEvent(
32 ui::KeyEvent
* event
) {
33 const base::NativeEvent
& native_event
= event
->native_event();
34 ui::EventType type
= ui::EventTypeFromNative(native_event
);
35 blink::WebKeyboardEvent webkit_event
;
37 webkit_event
.timeStampSeconds
= event
->time_stamp().InSecondsF();
38 webkit_event
.modifiers
= EventFlagsToWebEventModifiers(event
->flags());
41 case ui::ET_KEY_PRESSED
:
42 webkit_event
.type
= event
->is_char() ? blink::WebInputEvent::Char
:
43 blink::WebInputEvent::RawKeyDown
;
45 case ui::ET_KEY_RELEASED
:
46 webkit_event
.type
= blink::WebInputEvent::KeyUp
;
52 if (webkit_event
.modifiers
& blink::WebInputEvent::AltKey
)
53 webkit_event
.isSystemKey
= true;
55 wchar_t character
= ui::KeyboardCodeFromNative(native_event
);
56 webkit_event
.windowsKeyCode
= character
;
57 webkit_event
.nativeKeyCode
= character
;
59 if (webkit_event
.windowsKeyCode
== ui::VKEY_RETURN
)
60 webkit_event
.unmodifiedText
[0] = '\r';
62 webkit_event
.unmodifiedText
[0] = ui::GetCharacterFromKeyCode(
63 ui::KeyboardCodeFromNative(native_event
),
64 ui::EventFlagsFromNative(native_event
));
66 if (webkit_event
.modifiers
& blink::WebInputEvent::ControlKey
) {
67 webkit_event
.text
[0] = ui::GetControlCharacterForKeycode(
68 webkit_event
.windowsKeyCode
,
69 webkit_event
.modifiers
& blink::WebInputEvent::ShiftKey
);
71 webkit_event
.text
[0] = webkit_event
.unmodifiedText
[0];
74 webkit_event
.setKeyIdentifierFromWindowsKeyCode();
79 #if defined(USE_X11) || defined(USE_OZONE)
80 blink::WebMouseWheelEvent
MakeWebMouseWheelEventFromAuraEvent(
81 ui::ScrollEvent
* event
) {
82 blink::WebMouseWheelEvent webkit_event
;
84 webkit_event
.type
= blink::WebInputEvent::MouseWheel
;
85 webkit_event
.button
= blink::WebMouseEvent::ButtonNone
;
86 webkit_event
.modifiers
= EventFlagsToWebEventModifiers(event
->flags());
87 webkit_event
.timeStampSeconds
= event
->time_stamp().InSecondsF();
88 webkit_event
.hasPreciseScrollingDeltas
= true;
90 float offset_ordinal_x
= 0.f
;
91 float offset_ordinal_y
= 0.f
;
92 if ((event
->flags() & ui::EF_SHIFT_DOWN
) != 0 && event
->x_offset() == 0) {
93 webkit_event
.deltaX
= event
->y_offset();
94 webkit_event
.deltaY
= 0;
95 offset_ordinal_x
= event
->y_offset_ordinal();
96 offset_ordinal_y
= event
->x_offset_ordinal();
98 webkit_event
.deltaX
= event
->x_offset();
99 webkit_event
.deltaY
= event
->y_offset();
100 offset_ordinal_x
= event
->x_offset_ordinal();
101 offset_ordinal_y
= event
->y_offset_ordinal();
104 if (offset_ordinal_x
!= 0.f
&& webkit_event
.deltaX
!= 0.f
)
105 webkit_event
.accelerationRatioX
= offset_ordinal_x
/ webkit_event
.deltaX
;
106 webkit_event
.wheelTicksX
= webkit_event
.deltaX
/ kPixelsPerTick
;
107 webkit_event
.wheelTicksY
= webkit_event
.deltaY
/ kPixelsPerTick
;
108 if (offset_ordinal_y
!= 0.f
&& webkit_event
.deltaY
!= 0.f
)
109 webkit_event
.accelerationRatioY
= offset_ordinal_y
/ webkit_event
.deltaY
;
113 blink::WebGestureEvent
MakeWebGestureEventFromAuraEvent(
114 ui::ScrollEvent
* event
) {
115 blink::WebGestureEvent webkit_event
;
117 switch (event
->type()) {
118 case ui::ET_SCROLL_FLING_START
:
119 webkit_event
.type
= blink::WebInputEvent::GestureFlingStart
;
120 webkit_event
.data
.flingStart
.velocityX
= event
->x_offset();
121 webkit_event
.data
.flingStart
.velocityY
= event
->y_offset();
123 case ui::ET_SCROLL_FLING_CANCEL
:
124 webkit_event
.type
= blink::WebInputEvent::GestureFlingCancel
;
127 NOTREACHED() << "Invalid gesture type: " << event
->type();
130 NOTREACHED() << "Unknown gesture type: " << event
->type();
133 webkit_event
.sourceDevice
= blink::WebGestureDeviceTouchpad
;
134 webkit_event
.modifiers
= EventFlagsToWebEventModifiers(event
->flags());
135 webkit_event
.timeStampSeconds
= event
->time_stamp().InSecondsF();
141 blink::WebMouseEvent
MakeWebMouseEventFromAuraEvent(
142 ui::MouseEvent
* event
);
143 blink::WebMouseWheelEvent
MakeWebMouseWheelEventFromAuraEvent(
144 ui::MouseWheelEvent
* event
);
148 // ui::Event only carries a subset of possible event data provided to Aura by
149 // the host platform. WebKit utilizes a larger subset of that information than
150 // Aura itself. WebKit includes some built in cracking functionality that we
151 // rely on to obtain this information cleanly and consistently.
153 // The only place where an ui::Event's data differs from what the underlying
154 // base::NativeEvent would provide is position data, since we would like to
155 // provide coordinates relative to the aura::Window that is hosting the
156 // renderer, not the top level platform window.
158 // The approach is to fully construct a blink::WebInputEvent from the
159 // ui::Event's base::NativeEvent, and then replace the coordinate fields with
160 // the translated values from the ui::Event.
162 // The exception is mouse events on linux. The ui::MouseEvent contains enough
163 // necessary information to construct a WebMouseEvent. So instead of extracting
164 // the information from the XEvent, which can be tricky when supporting both
165 // XInput2 and XInput, the WebMouseEvent is constructed from the
166 // ui::MouseEvent. This will not be necessary once only XInput2 is supported.
169 blink::WebMouseEvent
MakeWebMouseEvent(ui::MouseEvent
* event
) {
170 // Construct an untranslated event from the platform event data.
171 blink::WebMouseEvent webkit_event
=
173 // On Windows we have WM_ events comming from desktop and pure aura
174 // events comming from metro mode.
175 event
->native_event().message
?
176 MakeUntranslatedWebMouseEventFromNativeEvent(event
->native_event()) :
177 MakeWebMouseEventFromAuraEvent(event
);
179 MakeWebMouseEventFromAuraEvent(event
);
181 // Replace the event's coordinate fields with translated position data from
183 webkit_event
.windowX
= webkit_event
.x
= event
->x();
184 webkit_event
.windowY
= webkit_event
.y
= event
->y();
187 if (event
->native_event().message
)
190 const gfx::Point root_point
= event
->root_location();
191 webkit_event
.globalX
= root_point
.x();
192 webkit_event
.globalY
= root_point
.y();
197 blink::WebMouseWheelEvent
MakeWebMouseWheelEvent(ui::MouseWheelEvent
* event
) {
199 // Construct an untranslated event from the platform event data.
200 blink::WebMouseWheelEvent webkit_event
= event
->native_event().message
?
201 MakeUntranslatedWebMouseWheelEventFromNativeEvent(event
->native_event()) :
202 MakeWebMouseWheelEventFromAuraEvent(event
);
204 blink::WebMouseWheelEvent webkit_event
=
205 MakeWebMouseWheelEventFromAuraEvent(event
);
208 // Replace the event's coordinate fields with translated position data from
210 webkit_event
.windowX
= webkit_event
.x
= event
->x();
211 webkit_event
.windowY
= webkit_event
.y
= event
->y();
213 const gfx::Point root_point
= event
->root_location();
214 webkit_event
.globalX
= root_point
.x();
215 webkit_event
.globalY
= root_point
.y();
220 blink::WebMouseWheelEvent
MakeWebMouseWheelEvent(ui::ScrollEvent
* event
) {
222 // Construct an untranslated event from the platform event data.
223 blink::WebMouseWheelEvent webkit_event
=
224 MakeUntranslatedWebMouseWheelEventFromNativeEvent(event
->native_event());
226 blink::WebMouseWheelEvent webkit_event
=
227 MakeWebMouseWheelEventFromAuraEvent(event
);
230 // Replace the event's coordinate fields with translated position data from
232 webkit_event
.windowX
= webkit_event
.x
= event
->x();
233 webkit_event
.windowY
= webkit_event
.y
= event
->y();
235 const gfx::Point root_point
= event
->root_location();
236 webkit_event
.globalX
= root_point
.x();
237 webkit_event
.globalY
= root_point
.y();
242 blink::WebKeyboardEvent
MakeWebKeyboardEvent(ui::KeyEvent
* event
) {
243 if (!event
->HasNativeEvent())
244 return blink::WebKeyboardEvent();
246 // Windows can figure out whether or not to construct a RawKeyDown or a Char
247 // WebInputEvent based on the type of message carried in
248 // event->native_event(). X11 is not so fortunate, there is no separate
249 // translated event type, so DesktopHostLinux sends an extra KeyEvent with
250 // is_char() == true. We need to pass the ui::KeyEvent to the X11 function
251 // to detect this case so the right event type can be constructed.
253 // Key events require no translation by the aura system.
254 return MakeWebKeyboardEventFromNativeEvent(event
->native_event());
256 return MakeWebKeyboardEventFromAuraEvent(event
);
260 blink::WebGestureEvent
MakeWebGestureEvent(ui::GestureEvent
* event
) {
261 blink::WebGestureEvent gesture_event
;
263 if (event
->HasNativeEvent())
264 gesture_event
= MakeWebGestureEventFromNativeEvent(event
->native_event());
266 gesture_event
= MakeWebGestureEventFromUIEvent(*event
);
268 gesture_event
= MakeWebGestureEventFromUIEvent(*event
);
271 gesture_event
.x
= event
->x();
272 gesture_event
.y
= event
->y();
274 const gfx::Point root_point
= event
->root_location();
275 gesture_event
.globalX
= root_point
.x();
276 gesture_event
.globalY
= root_point
.y();
278 return gesture_event
;
281 blink::WebGestureEvent
MakeWebGestureEvent(ui::ScrollEvent
* event
) {
282 blink::WebGestureEvent gesture_event
;
285 gesture_event
= MakeWebGestureEventFromNativeEvent(event
->native_event());
287 gesture_event
= MakeWebGestureEventFromAuraEvent(event
);
290 gesture_event
.x
= event
->x();
291 gesture_event
.y
= event
->y();
293 const gfx::Point root_point
= event
->root_location();
294 gesture_event
.globalX
= root_point
.x();
295 gesture_event
.globalY
= root_point
.y();
297 return gesture_event
;
300 blink::WebGestureEvent
MakeWebGestureEventFlingCancel() {
301 blink::WebGestureEvent gesture_event
;
303 // All other fields are ignored on a GestureFlingCancel event.
304 gesture_event
.type
= blink::WebInputEvent::GestureFlingCancel
;
305 gesture_event
.sourceDevice
= blink::WebGestureDeviceTouchpad
;
306 return gesture_event
;
309 blink::WebMouseEvent
MakeWebMouseEventFromAuraEvent(ui::MouseEvent
* event
) {
310 blink::WebMouseEvent webkit_event
;
312 webkit_event
.modifiers
= EventFlagsToWebEventModifiers(event
->flags());
313 webkit_event
.timeStampSeconds
= event
->time_stamp().InSecondsF();
315 webkit_event
.button
= blink::WebMouseEvent::ButtonNone
;
316 if (event
->flags() & ui::EF_LEFT_MOUSE_BUTTON
)
317 webkit_event
.button
= blink::WebMouseEvent::ButtonLeft
;
318 if (event
->flags() & ui::EF_MIDDLE_MOUSE_BUTTON
)
319 webkit_event
.button
= blink::WebMouseEvent::ButtonMiddle
;
320 if (event
->flags() & ui::EF_RIGHT_MOUSE_BUTTON
)
321 webkit_event
.button
= blink::WebMouseEvent::ButtonRight
;
323 switch (event
->type()) {
324 case ui::ET_MOUSE_PRESSED
:
325 webkit_event
.type
= blink::WebInputEvent::MouseDown
;
326 webkit_event
.clickCount
= event
->GetClickCount();
328 case ui::ET_MOUSE_RELEASED
:
329 webkit_event
.type
= blink::WebInputEvent::MouseUp
;
330 webkit_event
.clickCount
= event
->GetClickCount();
332 case ui::ET_MOUSE_ENTERED
:
333 case ui::ET_MOUSE_EXITED
:
334 case ui::ET_MOUSE_MOVED
:
335 case ui::ET_MOUSE_DRAGGED
:
336 webkit_event
.type
= blink::WebInputEvent::MouseMove
;
339 NOTIMPLEMENTED() << "Received unexpected event: " << event
->type();
346 blink::WebMouseWheelEvent
MakeWebMouseWheelEventFromAuraEvent(
347 ui::MouseWheelEvent
* event
) {
348 blink::WebMouseWheelEvent webkit_event
;
350 webkit_event
.type
= blink::WebInputEvent::MouseWheel
;
351 webkit_event
.button
= blink::WebMouseEvent::ButtonNone
;
352 webkit_event
.modifiers
= EventFlagsToWebEventModifiers(event
->flags());
353 webkit_event
.timeStampSeconds
= event
->time_stamp().InSecondsF();
355 if ((event
->flags() & ui::EF_SHIFT_DOWN
) != 0 && event
->x_offset() == 0) {
356 webkit_event
.deltaX
= event
->y_offset();
357 webkit_event
.deltaY
= 0;
359 webkit_event
.deltaX
= event
->x_offset();
360 webkit_event
.deltaY
= event
->y_offset();
363 webkit_event
.wheelTicksX
= webkit_event
.deltaX
/ kPixelsPerTick
;
364 webkit_event
.wheelTicksY
= webkit_event
.deltaY
/ kPixelsPerTick
;
369 } // namespace content