Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / content / renderer / pepper / event_conversion.cc
blob1a8344ef40a2607b9bba7ec213f3f37069c2e217
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/renderer/pepper/event_conversion.h"
7 #include <map>
9 #include "base/basictypes.h"
10 #include "base/i18n/char_iterator.h"
11 #include "base/logging.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/strings/string_util.h"
14 #include "base/strings/stringprintf.h"
15 #include "base/strings/utf_string_conversion_utils.h"
16 #include "base/strings/utf_string_conversions.h"
17 #include "content/common/input/web_touch_event_traits.h"
18 #include "content/renderer/pepper/usb_key_code_conversion.h"
19 #include "ppapi/c/pp_input_event.h"
20 #include "ppapi/shared_impl/ppb_input_event_shared.h"
21 #include "ppapi/shared_impl/time_conversion.h"
22 #include "third_party/WebKit/public/platform/WebGamepads.h"
23 #include "third_party/WebKit/public/platform/WebString.h"
24 #include "third_party/WebKit/public/web/WebInputEvent.h"
26 using ppapi::EventTimeToPPTimeTicks;
27 using ppapi::InputEventData;
28 using ppapi::PPTimeTicksToEventTime;
29 using blink::WebInputEvent;
30 using blink::WebKeyboardEvent;
31 using blink::WebMouseEvent;
32 using blink::WebMouseWheelEvent;
33 using blink::WebString;
34 using blink::WebTouchEvent;
35 using blink::WebTouchPoint;
36 using blink::WebUChar;
38 namespace content {
40 namespace {
42 // Verify the modifier flags WebKit uses match the Pepper ones. If these start
43 // not matching, we'll need to write conversion code to preserve the Pepper
44 // values (since plugins will be depending on them).
45 COMPILE_ASSERT(static_cast<int>(PP_INPUTEVENT_MODIFIER_SHIFTKEY) ==
46 static_cast<int>(WebInputEvent::ShiftKey),
47 ShiftKeyMatches);
48 COMPILE_ASSERT(static_cast<int>(PP_INPUTEVENT_MODIFIER_CONTROLKEY) ==
49 static_cast<int>(WebInputEvent::ControlKey),
50 ControlKeyMatches);
51 COMPILE_ASSERT(static_cast<int>(PP_INPUTEVENT_MODIFIER_ALTKEY) ==
52 static_cast<int>(WebInputEvent::AltKey),
53 AltKeyMatches);
54 COMPILE_ASSERT(static_cast<int>(PP_INPUTEVENT_MODIFIER_METAKEY) ==
55 static_cast<int>(WebInputEvent::MetaKey),
56 MetaKeyMatches);
57 COMPILE_ASSERT(static_cast<int>(PP_INPUTEVENT_MODIFIER_ISKEYPAD) ==
58 static_cast<int>(WebInputEvent::IsKeyPad),
59 KeyPadMatches);
60 COMPILE_ASSERT(static_cast<int>(PP_INPUTEVENT_MODIFIER_ISAUTOREPEAT) ==
61 static_cast<int>(WebInputEvent::IsAutoRepeat),
62 AutoRepeatMatches);
63 COMPILE_ASSERT(static_cast<int>(PP_INPUTEVENT_MODIFIER_LEFTBUTTONDOWN) ==
64 static_cast<int>(WebInputEvent::LeftButtonDown),
65 LeftButtonMatches);
66 COMPILE_ASSERT(static_cast<int>(PP_INPUTEVENT_MODIFIER_MIDDLEBUTTONDOWN) ==
67 static_cast<int>(WebInputEvent::MiddleButtonDown),
68 MiddleButtonMatches);
69 COMPILE_ASSERT(static_cast<int>(PP_INPUTEVENT_MODIFIER_RIGHTBUTTONDOWN) ==
70 static_cast<int>(WebInputEvent::RightButtonDown),
71 RightButtonMatches);
72 COMPILE_ASSERT(static_cast<int>(PP_INPUTEVENT_MODIFIER_CAPSLOCKKEY) ==
73 static_cast<int>(WebInputEvent::CapsLockOn),
74 CapsLockMatches);
75 COMPILE_ASSERT(static_cast<int>(PP_INPUTEVENT_MODIFIER_NUMLOCKKEY) ==
76 static_cast<int>(WebInputEvent::NumLockOn),
77 NumLockMatches);
78 COMPILE_ASSERT(static_cast<int>(PP_INPUTEVENT_MODIFIER_ISLEFT) ==
79 static_cast<int>(WebInputEvent::IsLeft),
80 LeftMatches);
81 COMPILE_ASSERT(static_cast<int>(PP_INPUTEVENT_MODIFIER_ISRIGHT) ==
82 static_cast<int>(WebInputEvent::IsRight),
83 RightMatches);
85 PP_InputEvent_Type ConvertEventTypes(WebInputEvent::Type wetype) {
86 switch (wetype) {
87 case WebInputEvent::MouseDown:
88 return PP_INPUTEVENT_TYPE_MOUSEDOWN;
89 case WebInputEvent::MouseUp:
90 return PP_INPUTEVENT_TYPE_MOUSEUP;
91 case WebInputEvent::MouseMove:
92 return PP_INPUTEVENT_TYPE_MOUSEMOVE;
93 case WebInputEvent::MouseEnter:
94 return PP_INPUTEVENT_TYPE_MOUSEENTER;
95 case WebInputEvent::MouseLeave:
96 return PP_INPUTEVENT_TYPE_MOUSELEAVE;
97 case WebInputEvent::ContextMenu:
98 return PP_INPUTEVENT_TYPE_CONTEXTMENU;
99 case WebInputEvent::MouseWheel:
100 return PP_INPUTEVENT_TYPE_WHEEL;
101 case WebInputEvent::RawKeyDown:
102 return PP_INPUTEVENT_TYPE_RAWKEYDOWN;
103 case WebInputEvent::KeyDown:
104 return PP_INPUTEVENT_TYPE_KEYDOWN;
105 case WebInputEvent::KeyUp:
106 return PP_INPUTEVENT_TYPE_KEYUP;
107 case WebInputEvent::Char:
108 return PP_INPUTEVENT_TYPE_CHAR;
109 case WebInputEvent::TouchStart:
110 return PP_INPUTEVENT_TYPE_TOUCHSTART;
111 case WebInputEvent::TouchMove:
112 return PP_INPUTEVENT_TYPE_TOUCHMOVE;
113 case WebInputEvent::TouchEnd:
114 return PP_INPUTEVENT_TYPE_TOUCHEND;
115 case WebInputEvent::TouchCancel:
116 return PP_INPUTEVENT_TYPE_TOUCHCANCEL;
117 case WebInputEvent::Undefined:
118 default:
119 return PP_INPUTEVENT_TYPE_UNDEFINED;
123 // Generates a PP_InputEvent with the fields common to all events, as well as
124 // the event type from the given web event. Event-specific fields will be zero
125 // initialized.
126 InputEventData GetEventWithCommonFieldsAndType(const WebInputEvent& web_event) {
127 InputEventData result;
128 result.event_type = ConvertEventTypes(web_event.type);
129 result.event_time_stamp = EventTimeToPPTimeTicks(web_event.timeStampSeconds);
130 return result;
133 void AppendKeyEvent(const WebInputEvent& event,
134 std::vector<InputEventData>* result_events) {
135 const WebKeyboardEvent& key_event =
136 static_cast<const WebKeyboardEvent&>(event);
137 InputEventData result = GetEventWithCommonFieldsAndType(event);
138 result.event_modifiers = key_event.modifiers;
139 result.key_code = key_event.windowsKeyCode;
140 result.code = CodeForKeyboardEvent(key_event);
141 result_events->push_back(result);
144 void AppendCharEvent(const WebInputEvent& event,
145 std::vector<InputEventData>* result_events) {
146 const WebKeyboardEvent& key_event =
147 static_cast<const WebKeyboardEvent&>(event);
149 // This is a bit complex, the input event will normally just have one 16-bit
150 // character in it, but may be zero or more than one. The text array is
151 // just padded with 0 values for the unused ones, but is not necessarily
152 // null-terminated.
154 // Here we see how many UTF-16 characters we have.
155 size_t utf16_char_count = 0;
156 while (utf16_char_count < WebKeyboardEvent::textLengthCap &&
157 key_event.text[utf16_char_count])
158 utf16_char_count++;
160 // Make a separate InputEventData for each Unicode character in the input.
161 base::i18n::UTF16CharIterator iter(key_event.text, utf16_char_count);
162 while (!iter.end()) {
163 InputEventData result = GetEventWithCommonFieldsAndType(event);
164 result.event_modifiers = key_event.modifiers;
165 base::WriteUnicodeCharacter(iter.get(), &result.character_text);
167 result_events->push_back(result);
168 iter.Advance();
172 void AppendMouseEvent(const WebInputEvent& event,
173 std::vector<InputEventData>* result_events) {
174 COMPILE_ASSERT(static_cast<int>(WebMouseEvent::ButtonNone) ==
175 static_cast<int>(PP_INPUTEVENT_MOUSEBUTTON_NONE),
176 MouseNone);
177 COMPILE_ASSERT(static_cast<int>(WebMouseEvent::ButtonLeft) ==
178 static_cast<int>(PP_INPUTEVENT_MOUSEBUTTON_LEFT),
179 MouseLeft);
180 COMPILE_ASSERT(static_cast<int>(WebMouseEvent::ButtonRight) ==
181 static_cast<int>(PP_INPUTEVENT_MOUSEBUTTON_RIGHT),
182 MouseRight);
183 COMPILE_ASSERT(static_cast<int>(WebMouseEvent::ButtonMiddle) ==
184 static_cast<int>(PP_INPUTEVENT_MOUSEBUTTON_MIDDLE),
185 MouseMiddle);
187 const WebMouseEvent& mouse_event = static_cast<const WebMouseEvent&>(event);
188 InputEventData result = GetEventWithCommonFieldsAndType(event);
189 result.event_modifiers = mouse_event.modifiers;
190 if (mouse_event.type == WebInputEvent::MouseDown ||
191 mouse_event.type == WebInputEvent::MouseMove ||
192 mouse_event.type == WebInputEvent::MouseUp) {
193 result.mouse_button =
194 static_cast<PP_InputEvent_MouseButton>(mouse_event.button);
196 result.mouse_position.x = mouse_event.x;
197 result.mouse_position.y = mouse_event.y;
198 result.mouse_click_count = mouse_event.clickCount;
199 result.mouse_movement.x = mouse_event.movementX;
200 result.mouse_movement.y = mouse_event.movementY;
201 result_events->push_back(result);
204 void AppendMouseWheelEvent(const WebInputEvent& event,
205 std::vector<InputEventData>* result_events) {
206 const WebMouseWheelEvent& mouse_wheel_event =
207 static_cast<const WebMouseWheelEvent&>(event);
208 InputEventData result = GetEventWithCommonFieldsAndType(event);
209 result.event_modifiers = mouse_wheel_event.modifiers;
210 result.wheel_delta.x = mouse_wheel_event.deltaX;
211 result.wheel_delta.y = mouse_wheel_event.deltaY;
212 result.wheel_ticks.x = mouse_wheel_event.wheelTicksX;
213 result.wheel_ticks.y = mouse_wheel_event.wheelTicksY;
214 result.wheel_scroll_by_page = !!mouse_wheel_event.scrollByPage;
215 result_events->push_back(result);
218 void SetPPTouchPoints(const WebTouchPoint* touches,
219 uint32_t touches_length,
220 std::vector<PP_TouchPoint>* result) {
221 for (uint32_t i = 0; i < touches_length; i++) {
222 const WebTouchPoint& touch_point = touches[i];
223 PP_TouchPoint pp_pt;
224 pp_pt.id = touch_point.id;
225 pp_pt.position.x = touch_point.position.x;
226 pp_pt.position.y = touch_point.position.y;
227 pp_pt.radius.x = touch_point.radiusX;
228 pp_pt.radius.y = touch_point.radiusY;
229 pp_pt.rotation_angle = touch_point.rotationAngle;
230 pp_pt.pressure = touch_point.force;
231 result->push_back(pp_pt);
235 void AppendTouchEvent(const WebInputEvent& event,
236 std::vector<InputEventData>* result_events) {
237 const WebTouchEvent& touch_event =
238 reinterpret_cast<const WebTouchEvent&>(event);
240 InputEventData result = GetEventWithCommonFieldsAndType(event);
241 SetPPTouchPoints(
242 touch_event.touches, touch_event.touchesLength, &result.touches);
243 SetPPTouchPoints(touch_event.changedTouches,
244 touch_event.changedTouchesLength,
245 &result.changed_touches);
246 SetPPTouchPoints(touch_event.targetTouches,
247 touch_event.targetTouchesLength,
248 &result.target_touches);
250 result_events->push_back(result);
253 // Structure used to map touch point id's to touch states. Since the pepper
254 // touch event structure does not have states for individual touch points and
255 // instead relies on the event type in combination with the set of touch lists,
256 // we have to set the state for the changed touches to be the same as the event
257 // type and all others to be 'stationary.'
258 typedef std::map<uint32_t, WebTouchPoint::State> TouchStateMap;
260 void SetWebTouchPoints(const std::vector<PP_TouchPoint>& pp_touches,
261 const TouchStateMap& states_map,
262 WebTouchPoint* web_touches,
263 uint32_t* web_touches_length) {
265 for (uint32_t i = 0;
266 i < pp_touches.size() && i < WebTouchEvent::touchesLengthCap;
267 i++) {
268 WebTouchPoint pt;
269 const PP_TouchPoint& pp_pt = pp_touches[i];
270 pt.id = pp_pt.id;
272 if (states_map.find(pt.id) == states_map.end())
273 pt.state = WebTouchPoint::StateStationary;
274 else
275 pt.state = states_map.find(pt.id)->second;
277 pt.position.x = pp_pt.position.x;
278 pt.position.y = pp_pt.position.y;
279 // TODO bug:http://code.google.com/p/chromium/issues/detail?id=93902
280 pt.screenPosition.x = 0;
281 pt.screenPosition.y = 0;
282 pt.force = pp_pt.pressure;
283 pt.radiusX = pp_pt.radius.x;
284 pt.radiusY = pp_pt.radius.y;
285 pt.rotationAngle = pp_pt.rotation_angle;
286 web_touches[i] = pt;
287 (*web_touches_length)++;
291 WebTouchEvent* BuildTouchEvent(const InputEventData& event) {
292 WebTouchEvent* web_event = new WebTouchEvent();
293 WebTouchPoint::State state = WebTouchPoint::StateUndefined;
294 WebInputEvent::Type type = WebInputEvent::Undefined;
295 switch (event.event_type) {
296 case PP_INPUTEVENT_TYPE_TOUCHSTART:
297 type = WebInputEvent::TouchStart;
298 state = WebTouchPoint::StatePressed;
299 break;
300 case PP_INPUTEVENT_TYPE_TOUCHMOVE:
301 type = WebInputEvent::TouchMove;
302 state = WebTouchPoint::StateMoved;
303 break;
304 case PP_INPUTEVENT_TYPE_TOUCHEND:
305 type = WebInputEvent::TouchEnd;
306 state = WebTouchPoint::StateReleased;
307 break;
308 case PP_INPUTEVENT_TYPE_TOUCHCANCEL:
309 type = WebInputEvent::TouchCancel;
310 state = WebTouchPoint::StateCancelled;
311 break;
312 default:
313 NOTREACHED();
315 WebTouchEventTraits::ResetType(
316 type, PPTimeTicksToEventTime(event.event_time_stamp), web_event);
318 TouchStateMap states_map;
319 for (uint32_t i = 0; i < event.changed_touches.size(); i++)
320 states_map[event.changed_touches[i].id] = state;
322 SetWebTouchPoints(event.changed_touches,
323 states_map,
324 web_event->changedTouches,
325 &web_event->changedTouchesLength);
327 SetWebTouchPoints(
328 event.touches, states_map, web_event->touches, &web_event->touchesLength);
330 SetWebTouchPoints(event.target_touches,
331 states_map,
332 web_event->targetTouches,
333 &web_event->targetTouchesLength);
335 if (web_event->type == WebInputEvent::TouchEnd ||
336 web_event->type == WebInputEvent::TouchCancel) {
337 SetWebTouchPoints(event.changed_touches,
338 states_map,
339 web_event->touches,
340 &web_event->touchesLength);
341 SetWebTouchPoints(event.changed_touches,
342 states_map,
343 web_event->targetTouches,
344 &web_event->targetTouchesLength);
347 return web_event;
350 WebKeyboardEvent* BuildKeyEvent(const InputEventData& event) {
351 WebKeyboardEvent* key_event = new WebKeyboardEvent();
352 switch (event.event_type) {
353 case PP_INPUTEVENT_TYPE_RAWKEYDOWN:
354 key_event->type = WebInputEvent::RawKeyDown;
355 break;
356 case PP_INPUTEVENT_TYPE_KEYDOWN:
357 key_event->type = WebInputEvent::KeyDown;
358 break;
359 case PP_INPUTEVENT_TYPE_KEYUP:
360 key_event->type = WebInputEvent::KeyUp;
361 break;
362 default:
363 NOTREACHED();
365 key_event->timeStampSeconds = PPTimeTicksToEventTime(event.event_time_stamp);
366 key_event->modifiers = event.event_modifiers;
367 key_event->windowsKeyCode = event.key_code;
368 key_event->setKeyIdentifierFromWindowsKeyCode();
369 return key_event;
372 WebKeyboardEvent* BuildCharEvent(const InputEventData& event) {
373 WebKeyboardEvent* key_event = new WebKeyboardEvent();
374 key_event->type = WebInputEvent::Char;
375 key_event->timeStampSeconds = PPTimeTicksToEventTime(event.event_time_stamp);
376 key_event->modifiers = event.event_modifiers;
378 // Make sure to not read beyond the buffer in case some bad code doesn't
379 // NULL-terminate it (this is called from plugins).
380 size_t text_length_cap = WebKeyboardEvent::textLengthCap;
381 base::string16 text16 = base::UTF8ToUTF16(event.character_text);
383 memset(key_event->text, 0, text_length_cap);
384 memset(key_event->unmodifiedText, 0, text_length_cap);
385 for (size_t i = 0; i < std::min(text_length_cap, text16.size()); ++i)
386 key_event->text[i] = text16[i];
387 return key_event;
390 WebMouseEvent* BuildMouseEvent(const InputEventData& event) {
391 WebMouseEvent* mouse_event = new WebMouseEvent();
392 switch (event.event_type) {
393 case PP_INPUTEVENT_TYPE_MOUSEDOWN:
394 mouse_event->type = WebInputEvent::MouseDown;
395 break;
396 case PP_INPUTEVENT_TYPE_MOUSEUP:
397 mouse_event->type = WebInputEvent::MouseUp;
398 break;
399 case PP_INPUTEVENT_TYPE_MOUSEMOVE:
400 mouse_event->type = WebInputEvent::MouseMove;
401 break;
402 case PP_INPUTEVENT_TYPE_MOUSEENTER:
403 mouse_event->type = WebInputEvent::MouseEnter;
404 break;
405 case PP_INPUTEVENT_TYPE_MOUSELEAVE:
406 mouse_event->type = WebInputEvent::MouseLeave;
407 break;
408 case PP_INPUTEVENT_TYPE_CONTEXTMENU:
409 mouse_event->type = WebInputEvent::ContextMenu;
410 break;
411 default:
412 NOTREACHED();
414 mouse_event->timeStampSeconds =
415 PPTimeTicksToEventTime(event.event_time_stamp);
416 mouse_event->modifiers = event.event_modifiers;
417 mouse_event->button = static_cast<WebMouseEvent::Button>(event.mouse_button);
418 if (mouse_event->type == WebInputEvent::MouseMove) {
419 if (mouse_event->modifiers & WebInputEvent::LeftButtonDown)
420 mouse_event->button = WebMouseEvent::ButtonLeft;
421 else if (mouse_event->modifiers & WebInputEvent::MiddleButtonDown)
422 mouse_event->button = WebMouseEvent::ButtonMiddle;
423 else if (mouse_event->modifiers & WebInputEvent::RightButtonDown)
424 mouse_event->button = WebMouseEvent::ButtonRight;
426 mouse_event->x = event.mouse_position.x;
427 mouse_event->y = event.mouse_position.y;
428 mouse_event->clickCount = event.mouse_click_count;
429 mouse_event->movementX = event.mouse_movement.x;
430 mouse_event->movementY = event.mouse_movement.y;
431 return mouse_event;
434 WebMouseWheelEvent* BuildMouseWheelEvent(const InputEventData& event) {
435 WebMouseWheelEvent* mouse_wheel_event = new WebMouseWheelEvent();
436 mouse_wheel_event->type = WebInputEvent::MouseWheel;
437 mouse_wheel_event->timeStampSeconds =
438 PPTimeTicksToEventTime(event.event_time_stamp);
439 mouse_wheel_event->modifiers = event.event_modifiers;
440 mouse_wheel_event->deltaX = event.wheel_delta.x;
441 mouse_wheel_event->deltaY = event.wheel_delta.y;
442 mouse_wheel_event->wheelTicksX = event.wheel_ticks.x;
443 mouse_wheel_event->wheelTicksY = event.wheel_ticks.y;
444 mouse_wheel_event->scrollByPage = event.wheel_scroll_by_page;
445 return mouse_wheel_event;
448 #if !defined(OS_WIN)
449 #define VK_RETURN 0x0D
451 #define VK_PRIOR 0x21
452 #define VK_NEXT 0x22
453 #define VK_END 0x23
454 #define VK_HOME 0x24
455 #define VK_LEFT 0x25
456 #define VK_UP 0x26
457 #define VK_RIGHT 0x27
458 #define VK_DOWN 0x28
459 #define VK_SNAPSHOT 0x2C
460 #define VK_INSERT 0x2D
461 #define VK_DELETE 0x2E
463 #define VK_APPS 0x5D
465 #define VK_F1 0x70
466 #endif
468 // Convert a character string to a Windows virtual key code. Adapted from
469 // src/content/shell/renderer/test_runner/event_sender.cc. This
470 // is used by CreateSimulatedWebInputEvents to convert keyboard events.
471 void GetKeyCode(const std::string& char_text,
472 WebUChar* code,
473 WebUChar* text,
474 bool* needs_shift_modifier,
475 bool* generate_char) {
476 WebUChar vk_code = 0;
477 WebUChar vk_text = 0;
478 *needs_shift_modifier = false;
479 *generate_char = false;
480 if ("\n" == char_text) {
481 vk_text = vk_code = VK_RETURN;
482 *generate_char = true;
483 } else if ("rightArrow" == char_text) {
484 vk_code = VK_RIGHT;
485 } else if ("downArrow" == char_text) {
486 vk_code = VK_DOWN;
487 } else if ("leftArrow" == char_text) {
488 vk_code = VK_LEFT;
489 } else if ("upArrow" == char_text) {
490 vk_code = VK_UP;
491 } else if ("insert" == char_text) {
492 vk_code = VK_INSERT;
493 } else if ("delete" == char_text) {
494 vk_code = VK_DELETE;
495 } else if ("pageUp" == char_text) {
496 vk_code = VK_PRIOR;
497 } else if ("pageDown" == char_text) {
498 vk_code = VK_NEXT;
499 } else if ("home" == char_text) {
500 vk_code = VK_HOME;
501 } else if ("end" == char_text) {
502 vk_code = VK_END;
503 } else if ("printScreen" == char_text) {
504 vk_code = VK_SNAPSHOT;
505 } else if ("menu" == char_text) {
506 vk_code = VK_APPS;
507 } else {
508 // Compare the input string with the function-key names defined by the
509 // DOM spec (i.e. "F1",...,"F24").
510 for (int i = 1; i <= 24; ++i) {
511 std::string functionKeyName = base::StringPrintf("F%d", i);
512 if (functionKeyName == char_text) {
513 vk_code = VK_F1 + (i - 1);
514 break;
517 if (!vk_code) {
518 WebString web_char_text =
519 WebString::fromUTF8(char_text.data(), char_text.size());
520 DCHECK_EQ(web_char_text.length(), 1U);
521 vk_text = vk_code = web_char_text.at(0);
522 *needs_shift_modifier =
523 (vk_code & 0xFF) >= 'A' && (vk_code & 0xFF) <= 'Z';
524 if ((vk_code & 0xFF) >= 'a' && (vk_code & 0xFF) <= 'z')
525 vk_code -= 'a' - 'A';
526 *generate_char = true;
530 *code = vk_code;
531 *text = vk_text;
534 } // namespace
536 void CreateInputEventData(const WebInputEvent& event,
537 std::vector<InputEventData>* result) {
538 result->clear();
540 switch (event.type) {
541 case WebInputEvent::MouseDown:
542 case WebInputEvent::MouseUp:
543 case WebInputEvent::MouseMove:
544 case WebInputEvent::MouseEnter:
545 case WebInputEvent::MouseLeave:
546 case WebInputEvent::ContextMenu:
547 AppendMouseEvent(event, result);
548 break;
549 case WebInputEvent::MouseWheel:
550 AppendMouseWheelEvent(event, result);
551 break;
552 case WebInputEvent::RawKeyDown:
553 case WebInputEvent::KeyDown:
554 case WebInputEvent::KeyUp:
555 AppendKeyEvent(event, result);
556 break;
557 case WebInputEvent::Char:
558 AppendCharEvent(event, result);
559 break;
560 case WebInputEvent::TouchStart:
561 case WebInputEvent::TouchMove:
562 case WebInputEvent::TouchEnd:
563 case WebInputEvent::TouchCancel:
564 AppendTouchEvent(event, result);
565 break;
566 case WebInputEvent::Undefined:
567 default:
568 break;
572 WebInputEvent* CreateWebInputEvent(const InputEventData& event) {
573 scoped_ptr<WebInputEvent> web_input_event;
574 switch (event.event_type) {
575 case PP_INPUTEVENT_TYPE_UNDEFINED:
576 return NULL;
577 case PP_INPUTEVENT_TYPE_MOUSEDOWN:
578 case PP_INPUTEVENT_TYPE_MOUSEUP:
579 case PP_INPUTEVENT_TYPE_MOUSEMOVE:
580 case PP_INPUTEVENT_TYPE_MOUSEENTER:
581 case PP_INPUTEVENT_TYPE_MOUSELEAVE:
582 case PP_INPUTEVENT_TYPE_CONTEXTMENU:
583 web_input_event.reset(BuildMouseEvent(event));
584 break;
585 case PP_INPUTEVENT_TYPE_WHEEL:
586 web_input_event.reset(BuildMouseWheelEvent(event));
587 break;
588 case PP_INPUTEVENT_TYPE_RAWKEYDOWN:
589 case PP_INPUTEVENT_TYPE_KEYDOWN:
590 case PP_INPUTEVENT_TYPE_KEYUP:
591 web_input_event.reset(BuildKeyEvent(event));
592 break;
593 case PP_INPUTEVENT_TYPE_CHAR:
594 web_input_event.reset(BuildCharEvent(event));
595 break;
596 case PP_INPUTEVENT_TYPE_IME_COMPOSITION_START:
597 case PP_INPUTEVENT_TYPE_IME_COMPOSITION_UPDATE:
598 case PP_INPUTEVENT_TYPE_IME_COMPOSITION_END:
599 case PP_INPUTEVENT_TYPE_IME_TEXT:
600 // TODO(kinaba) implement in WebKit an event structure to handle
601 // composition events.
602 NOTREACHED();
603 break;
604 case PP_INPUTEVENT_TYPE_TOUCHSTART:
605 case PP_INPUTEVENT_TYPE_TOUCHMOVE:
606 case PP_INPUTEVENT_TYPE_TOUCHEND:
607 case PP_INPUTEVENT_TYPE_TOUCHCANCEL:
608 web_input_event.reset(BuildTouchEvent(event));
609 break;
612 return web_input_event.release();
615 // Generate a coherent sequence of input events to simulate a user event.
616 // From src/content/shell/renderer/test_runner/event_sender.cc.
617 std::vector<linked_ptr<WebInputEvent> > CreateSimulatedWebInputEvents(
618 const ppapi::InputEventData& event,
619 int plugin_x,
620 int plugin_y) {
621 std::vector<linked_ptr<WebInputEvent> > events;
622 linked_ptr<WebInputEvent> original_event(CreateWebInputEvent(event));
624 switch (event.event_type) {
625 case PP_INPUTEVENT_TYPE_MOUSEDOWN:
626 case PP_INPUTEVENT_TYPE_MOUSEUP:
627 case PP_INPUTEVENT_TYPE_MOUSEMOVE:
628 case PP_INPUTEVENT_TYPE_MOUSEENTER:
629 case PP_INPUTEVENT_TYPE_MOUSELEAVE:
630 case PP_INPUTEVENT_TYPE_TOUCHSTART:
631 case PP_INPUTEVENT_TYPE_TOUCHMOVE:
632 case PP_INPUTEVENT_TYPE_TOUCHEND:
633 case PP_INPUTEVENT_TYPE_TOUCHCANCEL:
634 events.push_back(original_event);
635 break;
637 case PP_INPUTEVENT_TYPE_WHEEL: {
638 WebMouseWheelEvent* web_mouse_wheel_event =
639 static_cast<WebMouseWheelEvent*>(original_event.get());
640 web_mouse_wheel_event->x = plugin_x;
641 web_mouse_wheel_event->y = plugin_y;
642 events.push_back(original_event);
643 break;
646 case PP_INPUTEVENT_TYPE_RAWKEYDOWN:
647 case PP_INPUTEVENT_TYPE_KEYDOWN:
648 case PP_INPUTEVENT_TYPE_KEYUP: {
649 // Windows key down events should always be "raw" to avoid an ASSERT.
650 #if defined(OS_WIN)
651 WebKeyboardEvent* web_keyboard_event =
652 static_cast<WebKeyboardEvent*>(original_event.get());
653 if (web_keyboard_event->type == WebInputEvent::KeyDown)
654 web_keyboard_event->type = WebInputEvent::RawKeyDown;
655 #endif
656 events.push_back(original_event);
657 break;
660 case PP_INPUTEVENT_TYPE_CHAR: {
661 WebKeyboardEvent* web_char_event =
662 static_cast<WebKeyboardEvent*>(original_event.get());
664 WebUChar code = 0, text = 0;
665 bool needs_shift_modifier = false, generate_char = false;
666 GetKeyCode(event.character_text,
667 &code,
668 &text,
669 &needs_shift_modifier,
670 &generate_char);
672 // Synthesize key down and key up events in all cases.
673 scoped_ptr<WebKeyboardEvent> key_down_event(new WebKeyboardEvent());
674 scoped_ptr<WebKeyboardEvent> key_up_event(new WebKeyboardEvent());
676 key_down_event->type = WebInputEvent::RawKeyDown;
677 key_down_event->windowsKeyCode = code;
678 key_down_event->nativeKeyCode = code;
679 if (needs_shift_modifier)
680 key_down_event->modifiers |= WebInputEvent::ShiftKey;
682 // If a char event is needed, set the text fields.
683 if (generate_char) {
684 key_down_event->text[0] = text;
685 key_down_event->unmodifiedText[0] = text;
687 // Convert the key code to a string identifier.
688 key_down_event->setKeyIdentifierFromWindowsKeyCode();
690 *key_up_event = *web_char_event = *key_down_event;
692 events.push_back(linked_ptr<WebInputEvent>(key_down_event.release()));
694 if (generate_char) {
695 web_char_event->type = WebInputEvent::Char;
696 web_char_event->keyIdentifier[0] = '\0';
697 events.push_back(original_event);
700 key_up_event->type = WebInputEvent::KeyUp;
701 events.push_back(linked_ptr<WebInputEvent>(key_up_event.release()));
702 break;
705 default:
706 break;
708 return events;
711 PP_InputEvent_Class ClassifyInputEvent(WebInputEvent::Type type) {
712 switch (type) {
713 case WebInputEvent::MouseDown:
714 case WebInputEvent::MouseUp:
715 case WebInputEvent::MouseMove:
716 case WebInputEvent::MouseEnter:
717 case WebInputEvent::MouseLeave:
718 case WebInputEvent::ContextMenu:
719 return PP_INPUTEVENT_CLASS_MOUSE;
720 case WebInputEvent::MouseWheel:
721 return PP_INPUTEVENT_CLASS_WHEEL;
722 case WebInputEvent::RawKeyDown:
723 case WebInputEvent::KeyDown:
724 case WebInputEvent::KeyUp:
725 case WebInputEvent::Char:
726 return PP_INPUTEVENT_CLASS_KEYBOARD;
727 case WebInputEvent::TouchCancel:
728 case WebInputEvent::TouchEnd:
729 case WebInputEvent::TouchMove:
730 case WebInputEvent::TouchStart:
731 return PP_INPUTEVENT_CLASS_TOUCH;
732 case WebInputEvent::Undefined:
733 default:
734 CHECK(WebInputEvent::isGestureEventType(type));
735 return PP_InputEvent_Class(0);
739 } // namespace content