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"
18 #if defined(USE_X11) || defined(USE_OZONE)
19 // From third_party/WebKit/Source/web/gtk/WebInputEventFactory.cpp:
20 blink::WebUChar
GetControlCharacter(int windows_key_code
, bool shift
) {
21 if (windows_key_code
>= ui::VKEY_A
&&
22 windows_key_code
<= ui::VKEY_Z
) {
23 // ctrl-A ~ ctrl-Z map to \x01 ~ \x1A
24 return windows_key_code
- ui::VKEY_A
+ 1;
27 // following graphics chars require shift key to input.
28 switch (windows_key_code
) {
29 // ctrl-@ maps to \x00 (Null byte)
32 // ctrl-^ maps to \x1E (Record separator, Information separator two)
35 // ctrl-_ maps to \x1F (Unit separator, Information separator one)
36 case ui::VKEY_OEM_MINUS
:
38 // Returns 0 for all other keys to avoid inputting unexpected chars.
43 switch (windows_key_code
) {
44 // ctrl-[ maps to \x1B (Escape)
47 // ctrl-\ maps to \x1C (File separator, Information separator four)
50 // ctrl-] maps to \x1D (Group separator, Information separator three)
53 // ctrl-Enter maps to \x0A (Line feed)
56 // Returns 0 for all other keys to avoid inputting unexpected chars.
65 blink::WebMouseEvent
MakeUntranslatedWebMouseEventFromNativeEvent(
66 const base::NativeEvent
& native_event
);
67 blink::WebMouseWheelEvent
MakeUntranslatedWebMouseWheelEventFromNativeEvent(
68 const base::NativeEvent
& native_event
);
69 blink::WebKeyboardEvent
MakeWebKeyboardEventFromNativeEvent(
70 const base::NativeEvent
& native_event
);
71 blink::WebGestureEvent
MakeWebGestureEventFromNativeEvent(
72 const base::NativeEvent
& native_event
);
73 #elif defined(USE_X11)
74 blink::WebKeyboardEvent
MakeWebKeyboardEventFromAuraEvent(
76 #elif defined(USE_OZONE)
77 blink::WebKeyboardEvent
MakeWebKeyboardEventFromAuraEvent(
78 ui::KeyEvent
* event
) {
79 const base::NativeEvent
& native_event
= event
->native_event();
80 ui::EventType type
= ui::EventTypeFromNative(native_event
);
81 blink::WebKeyboardEvent webkit_event
;
83 webkit_event
.timeStampSeconds
= event
->time_stamp().InSecondsF();
84 webkit_event
.modifiers
= EventFlagsToWebEventModifiers(event
->flags());
87 case ui::ET_KEY_PRESSED
:
88 webkit_event
.type
= event
->is_char() ? blink::WebInputEvent::Char
:
89 blink::WebInputEvent::RawKeyDown
;
91 case ui::ET_KEY_RELEASED
:
92 webkit_event
.type
= blink::WebInputEvent::KeyUp
;
98 if (webkit_event
.modifiers
& blink::WebInputEvent::AltKey
)
99 webkit_event
.isSystemKey
= true;
101 wchar_t character
= ui::KeyboardCodeFromNative(native_event
);
102 webkit_event
.windowsKeyCode
= character
;
103 webkit_event
.nativeKeyCode
= character
;
105 if (webkit_event
.windowsKeyCode
== ui::VKEY_RETURN
)
106 webkit_event
.unmodifiedText
[0] = '\r';
108 webkit_event
.unmodifiedText
[0] = ui::GetCharacterFromKeyCode(
109 ui::KeyboardCodeFromNative(native_event
),
110 ui::EventFlagsFromNative(native_event
));
112 if (webkit_event
.modifiers
& blink::WebInputEvent::ControlKey
) {
113 webkit_event
.text
[0] =
115 webkit_event
.windowsKeyCode
,
116 webkit_event
.modifiers
& blink::WebInputEvent::ShiftKey
);
118 webkit_event
.text
[0] = webkit_event
.unmodifiedText
[0];
121 webkit_event
.setKeyIdentifierFromWindowsKeyCode();
126 #if defined(USE_X11) || defined(USE_OZONE)
127 blink::WebMouseWheelEvent
MakeWebMouseWheelEventFromAuraEvent(
128 ui::ScrollEvent
* event
) {
129 blink::WebMouseWheelEvent webkit_event
;
131 webkit_event
.type
= blink::WebInputEvent::MouseWheel
;
132 webkit_event
.button
= blink::WebMouseEvent::ButtonNone
;
133 webkit_event
.modifiers
= EventFlagsToWebEventModifiers(event
->flags());
134 webkit_event
.timeStampSeconds
= event
->time_stamp().InSecondsF();
135 webkit_event
.hasPreciseScrollingDeltas
= true;
137 float offset_ordinal_x
= 0.f
;
138 float offset_ordinal_y
= 0.f
;
139 if ((event
->flags() & ui::EF_SHIFT_DOWN
) != 0 && event
->x_offset() == 0) {
140 webkit_event
.deltaX
= event
->y_offset();
141 webkit_event
.deltaY
= 0;
142 offset_ordinal_x
= event
->y_offset_ordinal();
143 offset_ordinal_y
= event
->x_offset_ordinal();
145 webkit_event
.deltaX
= event
->x_offset();
146 webkit_event
.deltaY
= event
->y_offset();
147 offset_ordinal_x
= event
->x_offset_ordinal();
148 offset_ordinal_y
= event
->y_offset_ordinal();
151 if (offset_ordinal_x
!= 0.f
&& webkit_event
.deltaX
!= 0.f
)
152 webkit_event
.accelerationRatioX
= offset_ordinal_x
/ webkit_event
.deltaX
;
153 webkit_event
.wheelTicksX
= webkit_event
.deltaX
/ kPixelsPerTick
;
154 webkit_event
.wheelTicksY
= webkit_event
.deltaY
/ kPixelsPerTick
;
155 if (offset_ordinal_y
!= 0.f
&& webkit_event
.deltaY
!= 0.f
)
156 webkit_event
.accelerationRatioY
= offset_ordinal_y
/ webkit_event
.deltaY
;
160 blink::WebGestureEvent
MakeWebGestureEventFromAuraEvent(
161 ui::ScrollEvent
* event
) {
162 blink::WebGestureEvent webkit_event
;
164 switch (event
->type()) {
165 case ui::ET_SCROLL_FLING_START
:
166 webkit_event
.type
= blink::WebInputEvent::GestureFlingStart
;
167 webkit_event
.data
.flingStart
.velocityX
= event
->x_offset();
168 webkit_event
.data
.flingStart
.velocityY
= event
->y_offset();
170 case ui::ET_SCROLL_FLING_CANCEL
:
171 webkit_event
.type
= blink::WebInputEvent::GestureFlingCancel
;
174 NOTREACHED() << "Invalid gesture type: " << event
->type();
177 NOTREACHED() << "Unknown gesture type: " << event
->type();
180 webkit_event
.sourceDevice
= blink::WebGestureEvent::Touchpad
;
181 webkit_event
.modifiers
= EventFlagsToWebEventModifiers(event
->flags());
182 webkit_event
.timeStampSeconds
= event
->time_stamp().InSecondsF();
188 blink::WebMouseEvent
MakeWebMouseEventFromAuraEvent(
189 ui::MouseEvent
* event
);
190 blink::WebMouseWheelEvent
MakeWebMouseWheelEventFromAuraEvent(
191 ui::MouseWheelEvent
* event
);
195 // ui::Event only carries a subset of possible event data provided to Aura by
196 // the host platform. WebKit utilizes a larger subset of that information than
197 // Aura itself. WebKit includes some built in cracking functionality that we
198 // rely on to obtain this information cleanly and consistently.
200 // The only place where an ui::Event's data differs from what the underlying
201 // base::NativeEvent would provide is position data, since we would like to
202 // provide coordinates relative to the aura::Window that is hosting the
203 // renderer, not the top level platform window.
205 // The approach is to fully construct a blink::WebInputEvent from the
206 // ui::Event's base::NativeEvent, and then replace the coordinate fields with
207 // the translated values from the ui::Event.
209 // The exception is mouse events on linux. The ui::MouseEvent contains enough
210 // necessary information to construct a WebMouseEvent. So instead of extracting
211 // the information from the XEvent, which can be tricky when supporting both
212 // XInput2 and XInput, the WebMouseEvent is constructed from the
213 // ui::MouseEvent. This will not be necessary once only XInput2 is supported.
216 blink::WebMouseEvent
MakeWebMouseEvent(ui::MouseEvent
* event
) {
217 // Construct an untranslated event from the platform event data.
218 blink::WebMouseEvent webkit_event
=
220 // On Windows we have WM_ events comming from desktop and pure aura
221 // events comming from metro mode.
222 event
->native_event().message
?
223 MakeUntranslatedWebMouseEventFromNativeEvent(event
->native_event()) :
224 MakeWebMouseEventFromAuraEvent(event
);
226 MakeWebMouseEventFromAuraEvent(event
);
228 // Replace the event's coordinate fields with translated position data from
230 webkit_event
.windowX
= webkit_event
.x
= event
->x();
231 webkit_event
.windowY
= webkit_event
.y
= event
->y();
234 if (event
->native_event().message
)
237 const gfx::Point root_point
= event
->root_location();
238 webkit_event
.globalX
= root_point
.x();
239 webkit_event
.globalY
= root_point
.y();
244 blink::WebMouseWheelEvent
MakeWebMouseWheelEvent(ui::MouseWheelEvent
* event
) {
246 // Construct an untranslated event from the platform event data.
247 blink::WebMouseWheelEvent webkit_event
= event
->native_event().message
?
248 MakeUntranslatedWebMouseWheelEventFromNativeEvent(event
->native_event()) :
249 MakeWebMouseWheelEventFromAuraEvent(event
);
251 blink::WebMouseWheelEvent webkit_event
=
252 MakeWebMouseWheelEventFromAuraEvent(event
);
255 // Replace the event's coordinate fields with translated position data from
257 webkit_event
.windowX
= webkit_event
.x
= event
->x();
258 webkit_event
.windowY
= webkit_event
.y
= event
->y();
260 const gfx::Point root_point
= event
->root_location();
261 webkit_event
.globalX
= root_point
.x();
262 webkit_event
.globalY
= root_point
.y();
267 blink::WebMouseWheelEvent
MakeWebMouseWheelEvent(ui::ScrollEvent
* event
) {
269 // Construct an untranslated event from the platform event data.
270 blink::WebMouseWheelEvent webkit_event
=
271 MakeUntranslatedWebMouseWheelEventFromNativeEvent(event
->native_event());
273 blink::WebMouseWheelEvent webkit_event
=
274 MakeWebMouseWheelEventFromAuraEvent(event
);
277 // Replace the event's coordinate fields with translated position data from
279 webkit_event
.windowX
= webkit_event
.x
= event
->x();
280 webkit_event
.windowY
= webkit_event
.y
= event
->y();
282 const gfx::Point root_point
= event
->root_location();
283 webkit_event
.globalX
= root_point
.x();
284 webkit_event
.globalY
= root_point
.y();
289 blink::WebKeyboardEvent
MakeWebKeyboardEvent(ui::KeyEvent
* event
) {
290 if (!event
->HasNativeEvent())
291 return blink::WebKeyboardEvent();
293 // Windows can figure out whether or not to construct a RawKeyDown or a Char
294 // WebInputEvent based on the type of message carried in
295 // event->native_event(). X11 is not so fortunate, there is no separate
296 // translated event type, so DesktopHostLinux sends an extra KeyEvent with
297 // is_char() == true. We need to pass the ui::KeyEvent to the X11 function
298 // to detect this case so the right event type can be constructed.
300 // Key events require no translation by the aura system.
301 return MakeWebKeyboardEventFromNativeEvent(event
->native_event());
303 return MakeWebKeyboardEventFromAuraEvent(event
);
307 blink::WebGestureEvent
MakeWebGestureEvent(ui::GestureEvent
* event
) {
308 blink::WebGestureEvent gesture_event
;
310 if (event
->HasNativeEvent())
311 gesture_event
= MakeWebGestureEventFromNativeEvent(event
->native_event());
313 gesture_event
= MakeWebGestureEventFromUIEvent(*event
);
315 gesture_event
= MakeWebGestureEventFromUIEvent(*event
);
318 gesture_event
.x
= event
->x();
319 gesture_event
.y
= event
->y();
321 const gfx::Point root_point
= event
->root_location();
322 gesture_event
.globalX
= root_point
.x();
323 gesture_event
.globalY
= root_point
.y();
325 return gesture_event
;
328 blink::WebGestureEvent
MakeWebGestureEvent(ui::ScrollEvent
* event
) {
329 blink::WebGestureEvent gesture_event
;
332 gesture_event
= MakeWebGestureEventFromNativeEvent(event
->native_event());
334 gesture_event
= MakeWebGestureEventFromAuraEvent(event
);
337 gesture_event
.x
= event
->x();
338 gesture_event
.y
= event
->y();
340 const gfx::Point root_point
= event
->root_location();
341 gesture_event
.globalX
= root_point
.x();
342 gesture_event
.globalY
= root_point
.y();
344 return gesture_event
;
347 blink::WebGestureEvent
MakeWebGestureEventFlingCancel() {
348 blink::WebGestureEvent gesture_event
;
350 // All other fields are ignored on a GestureFlingCancel event.
351 gesture_event
.type
= blink::WebInputEvent::GestureFlingCancel
;
352 gesture_event
.sourceDevice
= blink::WebGestureEvent::Touchpad
;
353 return gesture_event
;
356 blink::WebMouseEvent
MakeWebMouseEventFromAuraEvent(ui::MouseEvent
* event
) {
357 blink::WebMouseEvent webkit_event
;
359 webkit_event
.modifiers
= EventFlagsToWebEventModifiers(event
->flags());
360 webkit_event
.timeStampSeconds
= event
->time_stamp().InSecondsF();
362 webkit_event
.button
= blink::WebMouseEvent::ButtonNone
;
363 if (event
->flags() & ui::EF_LEFT_MOUSE_BUTTON
)
364 webkit_event
.button
= blink::WebMouseEvent::ButtonLeft
;
365 if (event
->flags() & ui::EF_MIDDLE_MOUSE_BUTTON
)
366 webkit_event
.button
= blink::WebMouseEvent::ButtonMiddle
;
367 if (event
->flags() & ui::EF_RIGHT_MOUSE_BUTTON
)
368 webkit_event
.button
= blink::WebMouseEvent::ButtonRight
;
370 switch (event
->type()) {
371 case ui::ET_MOUSE_PRESSED
:
372 webkit_event
.type
= blink::WebInputEvent::MouseDown
;
373 webkit_event
.clickCount
= event
->GetClickCount();
375 case ui::ET_MOUSE_RELEASED
:
376 webkit_event
.type
= blink::WebInputEvent::MouseUp
;
377 webkit_event
.clickCount
= event
->GetClickCount();
379 case ui::ET_MOUSE_ENTERED
:
380 case ui::ET_MOUSE_EXITED
:
381 case ui::ET_MOUSE_MOVED
:
382 case ui::ET_MOUSE_DRAGGED
:
383 webkit_event
.type
= blink::WebInputEvent::MouseMove
;
386 NOTIMPLEMENTED() << "Received unexpected event: " << event
->type();
393 blink::WebMouseWheelEvent
MakeWebMouseWheelEventFromAuraEvent(
394 ui::MouseWheelEvent
* event
) {
395 blink::WebMouseWheelEvent webkit_event
;
397 webkit_event
.type
= blink::WebInputEvent::MouseWheel
;
398 webkit_event
.button
= blink::WebMouseEvent::ButtonNone
;
399 webkit_event
.modifiers
= EventFlagsToWebEventModifiers(event
->flags());
400 webkit_event
.timeStampSeconds
= event
->time_stamp().InSecondsF();
402 if ((event
->flags() & ui::EF_SHIFT_DOWN
) != 0 && event
->x_offset() == 0) {
403 webkit_event
.deltaX
= event
->y_offset();
404 webkit_event
.deltaY
= 0;
406 webkit_event
.deltaX
= event
->x_offset();
407 webkit_event
.deltaY
= event
->y_offset();
410 webkit_event
.wheelTicksX
= webkit_event
.deltaX
/ kPixelsPerTick
;
411 webkit_event
.wheelTicksY
= webkit_event
.deltaY
/ kPixelsPerTick
;
416 } // namespace content