Upstream version 5.34.92.0
[platform/framework/web/crosswalk.git] / src / content / renderer / pepper / event_conversion.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/renderer/pepper/event_conversion.h"
6
7 #include <map>
8
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/renderer/pepper/common.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"
25
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;
37
38 namespace content {
39
40 namespace {
41
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);
84
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;
120   }
121 }
122
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;
131 }
132
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);
142 }
143
144 void AppendCharEvent(const WebInputEvent& event,
145                      std::vector<InputEventData>* result_events) {
146   const WebKeyboardEvent& key_event =
147       static_cast<const WebKeyboardEvent&>(event);
148
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.
153   //
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++;
159
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);
166
167     result_events->push_back(result);
168     iter.Advance();
169   }
170 }
171
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);
186
187   const WebMouseEvent& mouse_event =
188       static_cast<const WebMouseEvent&>(event);
189   InputEventData result = GetEventWithCommonFieldsAndType(event);
190   result.event_modifiers = mouse_event.modifiers;
191   if (mouse_event.type == WebInputEvent::MouseDown ||
192       mouse_event.type == WebInputEvent::MouseMove ||
193       mouse_event.type == WebInputEvent::MouseUp) {
194     result.mouse_button =
195         static_cast<PP_InputEvent_MouseButton>(mouse_event.button);
196   }
197   result.mouse_position.x = mouse_event.x;
198   result.mouse_position.y = mouse_event.y;
199   result.mouse_click_count = mouse_event.clickCount;
200   result.mouse_movement.x = mouse_event.movementX;
201   result.mouse_movement.y = mouse_event.movementY;
202   result_events->push_back(result);
203 }
204
205 void AppendMouseWheelEvent(const WebInputEvent& event,
206                            std::vector<InputEventData>* result_events) {
207   const WebMouseWheelEvent& mouse_wheel_event =
208       static_cast<const WebMouseWheelEvent&>(event);
209   InputEventData result = GetEventWithCommonFieldsAndType(event);
210   result.event_modifiers = mouse_wheel_event.modifiers;
211   result.wheel_delta.x = mouse_wheel_event.deltaX;
212   result.wheel_delta.y = mouse_wheel_event.deltaY;
213   result.wheel_ticks.x = mouse_wheel_event.wheelTicksX;
214   result.wheel_ticks.y = mouse_wheel_event.wheelTicksY;
215   result.wheel_scroll_by_page = !!mouse_wheel_event.scrollByPage;
216   result_events->push_back(result);
217 }
218
219 void SetPPTouchPoints(const WebTouchPoint* touches, 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);
232   }
233 }
234
235 void AppendTouchEvent(const WebInputEvent& event,
236                       std::vector<InputEventData>* result_events) {
237   const WebTouchEvent& touch_event =
238       reinterpret_cast<const WebTouchEvent&>(event);
239
240   InputEventData result = GetEventWithCommonFieldsAndType(event);
241   SetPPTouchPoints(touch_event.touches, touch_event.touchesLength,
242                    &result.touches);
243   SetPPTouchPoints(touch_event.changedTouches, touch_event.changedTouchesLength,
244                    &result.changed_touches);
245   SetPPTouchPoints(touch_event.targetTouches, touch_event.targetTouchesLength,
246                    &result.target_touches);
247
248   result_events->push_back(result);
249 }
250
251 // Structure used to map touch point id's to touch states.  Since the pepper
252 // touch event structure does not have states for individual touch points and
253 // instead relies on the event type in combination with the set of touch lists,
254 // we have to set the state for the changed touches to be the same as the event
255 // type and all others to be 'stationary.'
256 typedef std::map<uint32_t, WebTouchPoint::State> TouchStateMap;
257
258 void SetWebTouchPoints(const std::vector<PP_TouchPoint>& pp_touches,
259                        const TouchStateMap& states_map,
260                        WebTouchPoint* web_touches,
261                        uint32_t* web_touches_length) {
262
263   for (uint32_t i = 0; i < pp_touches.size() &&
264        i < WebTouchEvent::touchesLengthCap; i++) {
265     WebTouchPoint pt;
266     const PP_TouchPoint& pp_pt = pp_touches[i];
267     pt.id = pp_pt.id;
268
269     if (states_map.find(pt.id) == states_map.end())
270       pt.state = WebTouchPoint::StateStationary;
271     else
272       pt.state = states_map.find(pt.id)->second;
273
274     pt.position.x = pp_pt.position.x;
275     pt.position.y = pp_pt.position.y;
276     // TODO bug:http://code.google.com/p/chromium/issues/detail?id=93902
277     pt.screenPosition.x = 0;
278     pt.screenPosition.y = 0;
279     pt.force = pp_pt.pressure;
280     pt.radiusX = pp_pt.radius.x;
281     pt.radiusY = pp_pt.radius.y;
282     pt.rotationAngle = pp_pt.rotation_angle;
283     web_touches[i] = pt;
284     (*web_touches_length)++;
285   }
286 }
287
288 WebTouchEvent* BuildTouchEvent(const InputEventData& event) {
289   WebTouchEvent* web_event = new WebTouchEvent();
290   WebTouchPoint::State state = WebTouchPoint::StateUndefined;
291   switch (event.event_type) {
292     case PP_INPUTEVENT_TYPE_TOUCHSTART:
293       web_event->type = WebInputEvent::TouchStart;
294       state = WebTouchPoint::StatePressed;
295       break;
296     case PP_INPUTEVENT_TYPE_TOUCHMOVE:
297       web_event->type = WebInputEvent::TouchMove;
298       state = WebTouchPoint::StateMoved;
299       break;
300     case PP_INPUTEVENT_TYPE_TOUCHEND:
301       web_event->type = WebInputEvent::TouchEnd;
302       state = WebTouchPoint::StateReleased;
303       break;
304     case PP_INPUTEVENT_TYPE_TOUCHCANCEL:
305       web_event->type = WebInputEvent::TouchCancel;
306       state = WebTouchPoint::StateCancelled;
307       break;
308     default:
309       NOTREACHED();
310   }
311
312   TouchStateMap states_map;
313   for (uint32_t i = 0; i < event.changed_touches.size(); i++)
314     states_map[event.changed_touches[i].id] = state;
315
316   web_event->timeStampSeconds = PPTimeTicksToEventTime(event.event_time_stamp);
317
318   SetWebTouchPoints(event.changed_touches, states_map,
319                     web_event->changedTouches,
320                     &web_event->changedTouchesLength);
321
322   SetWebTouchPoints(event.touches, states_map, web_event->touches,
323                     &web_event->touchesLength);
324
325   SetWebTouchPoints(event.target_touches, states_map, web_event->targetTouches,
326                     &web_event->targetTouchesLength);
327
328   if (web_event->type == WebInputEvent::TouchEnd ||
329       web_event->type == WebInputEvent::TouchCancel) {
330     SetWebTouchPoints(event.changed_touches, states_map,
331                       web_event->touches, &web_event->touchesLength);
332     SetWebTouchPoints(event.changed_touches, states_map,
333                       web_event->targetTouches,
334                       &web_event->targetTouchesLength);
335   }
336
337   return web_event;
338 }
339
340 WebKeyboardEvent* BuildKeyEvent(const InputEventData& event) {
341   WebKeyboardEvent* key_event = new WebKeyboardEvent();
342   switch (event.event_type) {
343     case PP_INPUTEVENT_TYPE_RAWKEYDOWN:
344       key_event->type = WebInputEvent::RawKeyDown;
345       break;
346     case PP_INPUTEVENT_TYPE_KEYDOWN:
347       key_event->type = WebInputEvent::KeyDown;
348       break;
349     case PP_INPUTEVENT_TYPE_KEYUP:
350       key_event->type = WebInputEvent::KeyUp;
351       break;
352     default:
353       NOTREACHED();
354   }
355   key_event->timeStampSeconds = PPTimeTicksToEventTime(event.event_time_stamp);
356   key_event->modifiers = event.event_modifiers;
357   key_event->windowsKeyCode = event.key_code;
358   key_event->setKeyIdentifierFromWindowsKeyCode();
359   return key_event;
360 }
361
362 WebKeyboardEvent* BuildCharEvent(const InputEventData& event) {
363   WebKeyboardEvent* key_event = new WebKeyboardEvent();
364   key_event->type = WebInputEvent::Char;
365   key_event->timeStampSeconds = PPTimeTicksToEventTime(event.event_time_stamp);
366   key_event->modifiers = event.event_modifiers;
367
368   // Make sure to not read beyond the buffer in case some bad code doesn't
369   // NULL-terminate it (this is called from plugins).
370   size_t text_length_cap = WebKeyboardEvent::textLengthCap;
371   base::string16 text16 = base::UTF8ToUTF16(event.character_text);
372
373   memset(key_event->text, 0, text_length_cap);
374   memset(key_event->unmodifiedText, 0, text_length_cap);
375   for (size_t i = 0;
376        i < std::min(text_length_cap, text16.size());
377        ++i)
378     key_event->text[i] = text16[i];
379   return key_event;
380 }
381
382 WebMouseEvent* BuildMouseEvent(const InputEventData& event) {
383   WebMouseEvent* mouse_event = new WebMouseEvent();
384   switch (event.event_type) {
385     case PP_INPUTEVENT_TYPE_MOUSEDOWN:
386       mouse_event->type = WebInputEvent::MouseDown;
387       break;
388     case PP_INPUTEVENT_TYPE_MOUSEUP:
389       mouse_event->type = WebInputEvent::MouseUp;
390       break;
391     case PP_INPUTEVENT_TYPE_MOUSEMOVE:
392       mouse_event->type = WebInputEvent::MouseMove;
393       break;
394     case PP_INPUTEVENT_TYPE_MOUSEENTER:
395       mouse_event->type = WebInputEvent::MouseEnter;
396       break;
397     case PP_INPUTEVENT_TYPE_MOUSELEAVE:
398       mouse_event->type = WebInputEvent::MouseLeave;
399       break;
400     case PP_INPUTEVENT_TYPE_CONTEXTMENU:
401       mouse_event->type = WebInputEvent::ContextMenu;
402       break;
403     default:
404       NOTREACHED();
405   }
406   mouse_event->timeStampSeconds =
407       PPTimeTicksToEventTime(event.event_time_stamp);
408   mouse_event->modifiers = event.event_modifiers;
409   mouse_event->button =
410       static_cast<WebMouseEvent::Button>(event.mouse_button);
411   if (mouse_event->type == WebInputEvent::MouseMove) {
412     if (mouse_event->modifiers & WebInputEvent::LeftButtonDown)
413       mouse_event->button = WebMouseEvent::ButtonLeft;
414     else if (mouse_event->modifiers & WebInputEvent::MiddleButtonDown)
415       mouse_event->button = WebMouseEvent::ButtonMiddle;
416     else if (mouse_event->modifiers & WebInputEvent::RightButtonDown)
417       mouse_event->button = WebMouseEvent::ButtonRight;
418   }
419   mouse_event->x = event.mouse_position.x;
420   mouse_event->y = event.mouse_position.y;
421   mouse_event->clickCount = event.mouse_click_count;
422   mouse_event->movementX = event.mouse_movement.x;
423   mouse_event->movementY = event.mouse_movement.y;
424   return mouse_event;
425 }
426
427 WebMouseWheelEvent* BuildMouseWheelEvent(const InputEventData& event) {
428   WebMouseWheelEvent* mouse_wheel_event = new WebMouseWheelEvent();
429   mouse_wheel_event->type = WebInputEvent::MouseWheel;
430   mouse_wheel_event->timeStampSeconds =
431       PPTimeTicksToEventTime(event.event_time_stamp);
432   mouse_wheel_event->modifiers = event.event_modifiers;
433   mouse_wheel_event->deltaX = event.wheel_delta.x;
434   mouse_wheel_event->deltaY = event.wheel_delta.y;
435   mouse_wheel_event->wheelTicksX = event.wheel_ticks.x;
436   mouse_wheel_event->wheelTicksY = event.wheel_ticks.y;
437   mouse_wheel_event->scrollByPage = event.wheel_scroll_by_page;
438   return mouse_wheel_event;
439 }
440
441 #if !defined(OS_WIN)
442 #define VK_RETURN         0x0D
443
444 #define VK_PRIOR          0x21
445 #define VK_NEXT           0x22
446 #define VK_END            0x23
447 #define VK_HOME           0x24
448 #define VK_LEFT           0x25
449 #define VK_UP             0x26
450 #define VK_RIGHT          0x27
451 #define VK_DOWN           0x28
452 #define VK_SNAPSHOT       0x2C
453 #define VK_INSERT         0x2D
454 #define VK_DELETE         0x2E
455
456 #define VK_APPS           0x5D
457
458 #define VK_F1             0x70
459 #endif
460
461 // Convert a character string to a Windows virtual key code. Adapted from
462 // src/third_party/WebKit/Tools/DumpRenderTree/chromium/EventSender.cpp. This
463 // is used by CreateSimulatedWebInputEvents to convert keyboard events.
464 void GetKeyCode(const std::string& char_text,
465                 WebUChar* code,
466                 WebUChar* text,
467                 bool* needs_shift_modifier,
468                 bool* generate_char) {
469   WebUChar vk_code = 0;
470   WebUChar vk_text = 0;
471   *needs_shift_modifier = false;
472   *generate_char = false;
473   if ("\n" == char_text) {
474     vk_text = vk_code = VK_RETURN;
475     *generate_char = true;
476   } else if ("rightArrow" == char_text) {
477     vk_code = VK_RIGHT;
478   } else if ("downArrow" == char_text) {
479     vk_code = VK_DOWN;
480   } else if ("leftArrow" == char_text) {
481     vk_code = VK_LEFT;
482   } else if ("upArrow" == char_text) {
483     vk_code = VK_UP;
484   } else if ("insert" == char_text) {
485     vk_code = VK_INSERT;
486   } else if ("delete" == char_text) {
487     vk_code = VK_DELETE;
488   } else if ("pageUp" == char_text) {
489     vk_code = VK_PRIOR;
490   } else if ("pageDown" == char_text) {
491     vk_code = VK_NEXT;
492   } else if ("home" == char_text) {
493     vk_code = VK_HOME;
494   } else if ("end" == char_text) {
495     vk_code = VK_END;
496   } else if ("printScreen" == char_text) {
497     vk_code = VK_SNAPSHOT;
498   } else if ("menu" == char_text) {
499     vk_code = VK_APPS;
500   } else {
501     // Compare the input string with the function-key names defined by the
502     // DOM spec (i.e. "F1",...,"F24").
503     for (int i = 1; i <= 24; ++i) {
504       std::string functionKeyName = base::StringPrintf("F%d", i);
505       if (functionKeyName == char_text) {
506         vk_code = VK_F1 + (i - 1);
507         break;
508       }
509     }
510     if (!vk_code) {
511       WebString web_char_text =
512           WebString::fromUTF8(char_text.data(), char_text.size());
513       DCHECK_EQ(web_char_text.length(), 1U);
514       vk_text = vk_code = web_char_text.at(0);
515       *needs_shift_modifier =
516           (vk_code & 0xFF) >= 'A' && (vk_code & 0xFF) <= 'Z';
517       if ((vk_code & 0xFF) >= 'a' && (vk_code & 0xFF) <= 'z')
518           vk_code -= 'a' - 'A';
519       *generate_char = true;
520     }
521   }
522
523   *code = vk_code;
524   *text = vk_text;
525 }
526
527 }  // namespace
528
529 void CreateInputEventData(const WebInputEvent& event,
530                           std::vector<InputEventData>* result) {
531   result->clear();
532
533   switch (event.type) {
534     case WebInputEvent::MouseDown:
535     case WebInputEvent::MouseUp:
536     case WebInputEvent::MouseMove:
537     case WebInputEvent::MouseEnter:
538     case WebInputEvent::MouseLeave:
539     case WebInputEvent::ContextMenu:
540       AppendMouseEvent(event, result);
541       break;
542     case WebInputEvent::MouseWheel:
543       AppendMouseWheelEvent(event, result);
544       break;
545     case WebInputEvent::RawKeyDown:
546     case WebInputEvent::KeyDown:
547     case WebInputEvent::KeyUp:
548       AppendKeyEvent(event, result);
549       break;
550     case WebInputEvent::Char:
551       AppendCharEvent(event, result);
552       break;
553     case WebInputEvent::TouchStart:
554     case WebInputEvent::TouchMove:
555     case WebInputEvent::TouchEnd:
556     case WebInputEvent::TouchCancel:
557       AppendTouchEvent(event, result);
558       break;
559     case WebInputEvent::Undefined:
560     default:
561       break;
562   }
563 }
564
565 WebInputEvent* CreateWebInputEvent(const InputEventData& event) {
566   scoped_ptr<WebInputEvent> web_input_event;
567   switch (event.event_type) {
568     case PP_INPUTEVENT_TYPE_UNDEFINED:
569       return NULL;
570     case PP_INPUTEVENT_TYPE_MOUSEDOWN:
571     case PP_INPUTEVENT_TYPE_MOUSEUP:
572     case PP_INPUTEVENT_TYPE_MOUSEMOVE:
573     case PP_INPUTEVENT_TYPE_MOUSEENTER:
574     case PP_INPUTEVENT_TYPE_MOUSELEAVE:
575     case PP_INPUTEVENT_TYPE_CONTEXTMENU:
576       web_input_event.reset(BuildMouseEvent(event));
577       break;
578     case PP_INPUTEVENT_TYPE_WHEEL:
579       web_input_event.reset(BuildMouseWheelEvent(event));
580       break;
581     case PP_INPUTEVENT_TYPE_RAWKEYDOWN:
582     case PP_INPUTEVENT_TYPE_KEYDOWN:
583     case PP_INPUTEVENT_TYPE_KEYUP:
584       web_input_event.reset(BuildKeyEvent(event));
585       break;
586     case PP_INPUTEVENT_TYPE_CHAR:
587       web_input_event.reset(BuildCharEvent(event));
588       break;
589     case PP_INPUTEVENT_TYPE_IME_COMPOSITION_START:
590     case PP_INPUTEVENT_TYPE_IME_COMPOSITION_UPDATE:
591     case PP_INPUTEVENT_TYPE_IME_COMPOSITION_END:
592     case PP_INPUTEVENT_TYPE_IME_TEXT:
593       // TODO(kinaba) implement in WebKit an event structure to handle
594       // composition events.
595       NOTREACHED();
596       break;
597     case PP_INPUTEVENT_TYPE_TOUCHSTART:
598     case PP_INPUTEVENT_TYPE_TOUCHMOVE:
599     case PP_INPUTEVENT_TYPE_TOUCHEND:
600     case PP_INPUTEVENT_TYPE_TOUCHCANCEL:
601       web_input_event.reset(BuildTouchEvent(event));
602       break;
603   }
604
605   return web_input_event.release();
606 }
607
608 // Generate a coherent sequence of input events to simulate a user event.
609 // From src/third_party/WebKit/Tools/DumpRenderTree/chromium/EventSender.cpp.
610 std::vector<linked_ptr<WebInputEvent> > CreateSimulatedWebInputEvents(
611     const ppapi::InputEventData& event,
612     int plugin_x,
613     int plugin_y) {
614   std::vector<linked_ptr<WebInputEvent> > events;
615   linked_ptr<WebInputEvent> original_event(CreateWebInputEvent(event));
616
617   switch (event.event_type) {
618     case PP_INPUTEVENT_TYPE_MOUSEDOWN:
619     case PP_INPUTEVENT_TYPE_MOUSEUP:
620     case PP_INPUTEVENT_TYPE_MOUSEMOVE:
621     case PP_INPUTEVENT_TYPE_MOUSEENTER:
622     case PP_INPUTEVENT_TYPE_MOUSELEAVE:
623     case PP_INPUTEVENT_TYPE_TOUCHSTART:
624     case PP_INPUTEVENT_TYPE_TOUCHMOVE:
625     case PP_INPUTEVENT_TYPE_TOUCHEND:
626     case PP_INPUTEVENT_TYPE_TOUCHCANCEL:
627       events.push_back(original_event);
628       break;
629
630     case PP_INPUTEVENT_TYPE_WHEEL: {
631       WebMouseWheelEvent* web_mouse_wheel_event =
632           static_cast<WebMouseWheelEvent*>(original_event.get());
633       web_mouse_wheel_event->x = plugin_x;
634       web_mouse_wheel_event->y = plugin_y;
635       events.push_back(original_event);
636       break;
637     }
638
639     case PP_INPUTEVENT_TYPE_RAWKEYDOWN:
640     case PP_INPUTEVENT_TYPE_KEYDOWN:
641     case PP_INPUTEVENT_TYPE_KEYUP: {
642       // Windows key down events should always be "raw" to avoid an ASSERT.
643 #if defined(OS_WIN)
644       WebKeyboardEvent* web_keyboard_event =
645           static_cast<WebKeyboardEvent*>(original_event.get());
646       if (web_keyboard_event->type == WebInputEvent::KeyDown)
647         web_keyboard_event->type = WebInputEvent::RawKeyDown;
648 #endif
649       events.push_back(original_event);
650       break;
651     }
652
653     case PP_INPUTEVENT_TYPE_CHAR: {
654       WebKeyboardEvent* web_char_event =
655           static_cast<WebKeyboardEvent*>(original_event.get());
656
657       WebUChar code = 0, text = 0;
658       bool needs_shift_modifier = false, generate_char = false;
659       GetKeyCode(event.character_text,
660                  &code,
661                  &text,
662                  &needs_shift_modifier,
663                  &generate_char);
664
665       // Synthesize key down and key up events in all cases.
666       scoped_ptr<WebKeyboardEvent> key_down_event(new WebKeyboardEvent());
667       scoped_ptr<WebKeyboardEvent> key_up_event(new WebKeyboardEvent());
668
669       key_down_event->type = WebInputEvent::RawKeyDown;
670       key_down_event->windowsKeyCode = code;
671       key_down_event->nativeKeyCode = code;
672       if (needs_shift_modifier)
673         key_down_event->modifiers |= WebInputEvent::ShiftKey;
674
675       // If a char event is needed, set the text fields.
676       if (generate_char) {
677         key_down_event->text[0] = text;
678         key_down_event->unmodifiedText[0] = text;
679       }
680       // Convert the key code to a string identifier.
681       key_down_event->setKeyIdentifierFromWindowsKeyCode();
682
683       *key_up_event = *web_char_event = *key_down_event;
684
685       events.push_back(linked_ptr<WebInputEvent>(key_down_event.release()));
686
687       if (generate_char) {
688         web_char_event->type = WebInputEvent::Char;
689         web_char_event->keyIdentifier[0] = '\0';
690         events.push_back(original_event);
691       }
692
693       key_up_event->type = WebInputEvent::KeyUp;
694       events.push_back(linked_ptr<WebInputEvent>(key_up_event.release()));
695       break;
696     }
697
698     default:
699       break;
700   }
701   return events;
702 }
703
704 PP_InputEvent_Class ClassifyInputEvent(WebInputEvent::Type type) {
705   switch (type) {
706     case WebInputEvent::MouseDown:
707     case WebInputEvent::MouseUp:
708     case WebInputEvent::MouseMove:
709     case WebInputEvent::MouseEnter:
710     case WebInputEvent::MouseLeave:
711     case WebInputEvent::ContextMenu:
712       return PP_INPUTEVENT_CLASS_MOUSE;
713     case WebInputEvent::MouseWheel:
714       return PP_INPUTEVENT_CLASS_WHEEL;
715     case WebInputEvent::RawKeyDown:
716     case WebInputEvent::KeyDown:
717     case WebInputEvent::KeyUp:
718     case WebInputEvent::Char:
719       return PP_INPUTEVENT_CLASS_KEYBOARD;
720     case WebInputEvent::TouchCancel:
721     case WebInputEvent::TouchEnd:
722     case WebInputEvent::TouchMove:
723     case WebInputEvent::TouchStart:
724       return PP_INPUTEVENT_CLASS_TOUCH;
725     case WebInputEvent::Undefined:
726     default:
727       NOTREACHED();
728       return PP_InputEvent_Class(0);
729   }
730 }
731
732 }  // namespace content