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 // C headers 6 #include <stdio.h> 7 8 // C++ headers 9 #include <sstream> 10 #include <string> 11 12 // PPAPI headers 13 #include "ppapi/cpp/completion_callback.h" 14 #include "ppapi/cpp/input_event.h" 15 #include "ppapi/cpp/instance.h" 16 #include "ppapi/cpp/module.h" 17 #include "ppapi/cpp/point.h" 18 #include "ppapi/cpp/var.h" 19 #include "ppapi/utility/completion_callback_factory.h" 20 21 #ifdef PostMessage 22 #undef PostMessage 23 #endif 24 25 namespace { 26 27 std::string ModifierToString(uint32_t modifier) { 28 std::string s; 29 if (modifier & PP_INPUTEVENT_MODIFIER_SHIFTKEY) { 30 s += "shift "; 31 } 32 if (modifier & PP_INPUTEVENT_MODIFIER_CONTROLKEY) { 33 s += "ctrl "; 34 } 35 if (modifier & PP_INPUTEVENT_MODIFIER_ALTKEY) { 36 s += "alt "; 37 } 38 if (modifier & PP_INPUTEVENT_MODIFIER_METAKEY) { 39 s += "meta "; 40 } 41 if (modifier & PP_INPUTEVENT_MODIFIER_ISKEYPAD) { 42 s += "keypad "; 43 } 44 if (modifier & PP_INPUTEVENT_MODIFIER_ISAUTOREPEAT) { 45 s += "autorepeat "; 46 } 47 if (modifier & PP_INPUTEVENT_MODIFIER_LEFTBUTTONDOWN) { 48 s += "left-button-down "; 49 } 50 if (modifier & PP_INPUTEVENT_MODIFIER_MIDDLEBUTTONDOWN) { 51 s += "middle-button-down "; 52 } 53 if (modifier & PP_INPUTEVENT_MODIFIER_RIGHTBUTTONDOWN) { 54 s += "right-button-down "; 55 } 56 if (modifier & PP_INPUTEVENT_MODIFIER_CAPSLOCKKEY) { 57 s += "caps-lock "; 58 } 59 if (modifier & PP_INPUTEVENT_MODIFIER_NUMLOCKKEY) { 60 s += "num-lock "; 61 } 62 return s; 63 } 64 65 std::string MouseButtonToString(PP_InputEvent_MouseButton button) { 66 switch (button) { 67 case PP_INPUTEVENT_MOUSEBUTTON_NONE: 68 return "None"; 69 case PP_INPUTEVENT_MOUSEBUTTON_LEFT: 70 return "Left"; 71 case PP_INPUTEVENT_MOUSEBUTTON_MIDDLE: 72 return "Middle"; 73 case PP_INPUTEVENT_MOUSEBUTTON_RIGHT: 74 return "Right"; 75 default: 76 std::ostringstream stream; 77 stream << "Unrecognized (" << static_cast<int32_t>(button) << ")"; 78 return stream.str(); 79 } 80 } 81 82 std::string TouchKindToString(PP_InputEvent_Type kind) { 83 switch (kind) { 84 case PP_INPUTEVENT_TYPE_TOUCHSTART: 85 return "Start"; 86 case PP_INPUTEVENT_TYPE_TOUCHMOVE: 87 return "Move"; 88 case PP_INPUTEVENT_TYPE_TOUCHEND: 89 return "End"; 90 case PP_INPUTEVENT_TYPE_TOUCHCANCEL: 91 return "Cancel"; 92 default: 93 std::ostringstream stream; 94 stream << "Unrecognized (" << static_cast<int32_t>(kind) << ")"; 95 return stream.str(); 96 } 97 } 98 99 } // namespace 100 101 class InputEventInstance : public pp::Instance { 102 public: 103 explicit InputEventInstance(PP_Instance instance) 104 : pp::Instance(instance) { 105 RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE | PP_INPUTEVENT_CLASS_WHEEL | 106 PP_INPUTEVENT_CLASS_TOUCH); 107 RequestFilteringInputEvents(PP_INPUTEVENT_CLASS_KEYBOARD); 108 } 109 110 bool Init(uint32_t argc, const char* argn[], const char* argv[]) { 111 return true; 112 } 113 114 /// Clicking outside of the instance's bounding box 115 /// will create a DidChangeFocus event (the NaCl instance is 116 /// out of focus). Clicking back inside the instance's 117 /// bounding box will create another DidChangeFocus event 118 /// (the NaCl instance is back in focus). The default is 119 /// that the instance is out of focus. 120 void DidChangeFocus(bool focus) { 121 std::ostringstream stream; 122 stream << "DidChangeFocus:" << " focus:" << focus; 123 PostMessage(stream.str()); 124 } 125 126 /// Scrolling the mouse wheel causes a DidChangeView event. 127 void DidChangeView(const pp::View& view) { 128 std::ostringstream stream; 129 stream << "DidChangeView:" 130 << " x:" << view.GetRect().x() 131 << " y:" << view.GetRect().y() 132 << " width:" << view.GetRect().width() 133 << " height:" << view.GetRect().height() 134 << "\n" 135 << " IsFullscreen:" << view.IsFullscreen() 136 << " IsVisible:" << view.IsVisible() 137 << " IsPageVisible:" << view.IsPageVisible() 138 << " GetDeviceScale:" << view.GetDeviceScale() 139 << " GetCSSScale:" << view.GetCSSScale(); 140 PostMessage(stream.str()); 141 } 142 143 virtual bool HandleInputEvent(const pp::InputEvent& event) { 144 switch (event.GetType()) { 145 case PP_INPUTEVENT_TYPE_IME_COMPOSITION_START: 146 case PP_INPUTEVENT_TYPE_IME_COMPOSITION_UPDATE: 147 case PP_INPUTEVENT_TYPE_IME_COMPOSITION_END: 148 case PP_INPUTEVENT_TYPE_IME_TEXT: 149 case PP_INPUTEVENT_TYPE_UNDEFINED: 150 // these cases are not handled. 151 break; 152 case PP_INPUTEVENT_TYPE_MOUSEDOWN: 153 case PP_INPUTEVENT_TYPE_MOUSEUP: 154 case PP_INPUTEVENT_TYPE_MOUSEMOVE: 155 case PP_INPUTEVENT_TYPE_MOUSEENTER: 156 case PP_INPUTEVENT_TYPE_MOUSELEAVE: 157 case PP_INPUTEVENT_TYPE_CONTEXTMENU: { 158 pp::MouseInputEvent mouse_event(event); 159 std::ostringstream stream; 160 stream << "Mouse event:" 161 << " modifier:" << ModifierToString(mouse_event.GetModifiers()) 162 << " button:" << MouseButtonToString(mouse_event.GetButton()) 163 << " x:" << mouse_event.GetPosition().x() 164 << " y:" << mouse_event.GetPosition().y() 165 << " click_count:" << mouse_event.GetClickCount() 166 << " time:" << mouse_event.GetTimeStamp() 167 << " is_context_menu: " 168 << (event.GetType() == PP_INPUTEVENT_TYPE_CONTEXTMENU); 169 PostMessage(stream.str()); 170 break; 171 } 172 173 case PP_INPUTEVENT_TYPE_WHEEL: { 174 pp::WheelInputEvent wheel_event(event); 175 std::ostringstream stream; 176 stream << "Wheel event:" 177 << " modifier:" << ModifierToString(wheel_event.GetModifiers()) 178 << " deltax:" << wheel_event.GetDelta().x() 179 << " deltay:" << wheel_event.GetDelta().y() 180 << " wheel_ticks_x:" << wheel_event.GetTicks().x() 181 << " wheel_ticks_y:" << wheel_event.GetTicks().y() 182 << " scroll_by_page: " << wheel_event.GetScrollByPage() 183 << " time:" << wheel_event.GetTimeStamp(); 184 PostMessage(stream.str()); 185 break; 186 } 187 188 case PP_INPUTEVENT_TYPE_RAWKEYDOWN: 189 case PP_INPUTEVENT_TYPE_KEYDOWN: 190 case PP_INPUTEVENT_TYPE_KEYUP: 191 case PP_INPUTEVENT_TYPE_CHAR: { 192 pp::KeyboardInputEvent key_event(event); 193 std::ostringstream stream; 194 stream << "Key event:" 195 << " modifier:" << ModifierToString(key_event.GetModifiers()) 196 << " key_code:" << key_event.GetKeyCode() 197 << " time:" << key_event.GetTimeStamp() 198 << " text:" << key_event.GetCharacterText().DebugString(); 199 PostMessage(stream.str()); 200 break; 201 } 202 203 case PP_INPUTEVENT_TYPE_TOUCHSTART: 204 case PP_INPUTEVENT_TYPE_TOUCHMOVE: 205 case PP_INPUTEVENT_TYPE_TOUCHEND: 206 case PP_INPUTEVENT_TYPE_TOUCHCANCEL: { 207 pp::TouchInputEvent touch_event(event); 208 std::ostringstream stream; 209 stream << "Touch event:" << TouchKindToString(event.GetType()) 210 << " modifier:" << ModifierToString(touch_event.GetModifiers()); 211 212 uint32_t touch_count = 213 touch_event.GetTouchCount(PP_TOUCHLIST_TYPE_CHANGEDTOUCHES); 214 for (uint32_t i = 0; i < touch_count; ++i) { 215 pp::TouchPoint point = 216 touch_event.GetTouchByIndex(PP_TOUCHLIST_TYPE_CHANGEDTOUCHES, i); 217 stream << " x[" << point.id() << "]:" << point.position().x() 218 << " y[" << point.id() << "]:" << point.position().y() 219 << " radii_x[" << point.id() << "]:" << point.radii().x() 220 << " radii_y[" << point.id() << "]:" << point.radii().y() 221 << " angle[" << point.id() << "]:" << point.rotation_angle() 222 << " pressure[" << point.id() << "]:" << point.pressure(); 223 } 224 stream << " time:" << touch_event.GetTimeStamp(); 225 PostMessage(stream.str()); 226 break; 227 } 228 229 default: { 230 // For any unhandled events, send a message to the browser 231 // so that the user is aware of these and can investigate. 232 std::stringstream oss; 233 oss << "Default (unhandled) event, type=" << event.GetType(); 234 PostMessage(oss.str()); 235 } break; 236 } 237 238 return true; 239 } 240 }; 241 242 class InputEventModule : public pp::Module { 243 public: 244 InputEventModule() : pp::Module() {} 245 virtual ~InputEventModule() {} 246 247 virtual pp::Instance* CreateInstance(PP_Instance instance) { 248 return new InputEventInstance(instance); 249 } 250 }; 251 252 namespace pp { 253 Module* CreateModule() { return new InputEventModule(); } 254 } 255