1 /* 2 * Copyright (C) 2012 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include "config.h" 32 #include "core/inspector/InspectorInputAgent.h" 33 34 #include "core/frame/FrameView.h" 35 #include "core/frame/LocalFrame.h" 36 #include "core/inspector/InspectorClient.h" 37 #include "core/page/Chrome.h" 38 #include "core/page/EventHandler.h" 39 #include "core/page/Page.h" 40 #include "platform/JSONValues.h" 41 #include "platform/PlatformKeyboardEvent.h" 42 #include "platform/PlatformMouseEvent.h" 43 #include "platform/PlatformTouchEvent.h" 44 #include "platform/PlatformTouchPoint.h" 45 #include "platform/geometry/FloatSize.h" 46 #include "platform/geometry/IntPoint.h" 47 #include "platform/geometry/IntRect.h" 48 #include "platform/geometry/IntSize.h" 49 #include "wtf/CurrentTime.h" 50 51 namespace { 52 53 class SyntheticInspectorTouchPoint : public WebCore::PlatformTouchPoint { 54 public: 55 SyntheticInspectorTouchPoint(unsigned id, State state, const WebCore::IntPoint& screenPos, const WebCore::IntPoint& pos, int radiusX, int radiusY, double rotationAngle, double force) 56 { 57 m_id = id; 58 m_screenPos = screenPos; 59 m_pos = pos; 60 m_state = state; 61 m_radius = WebCore::FloatSize(radiusX, radiusY); 62 m_rotationAngle = rotationAngle; 63 m_force = force; 64 } 65 }; 66 67 class SyntheticInspectorTouchEvent : public WebCore::PlatformTouchEvent { 68 public: 69 SyntheticInspectorTouchEvent(const WebCore::PlatformEvent::Type type, unsigned modifiers, double timestamp) 70 { 71 m_type = type; 72 m_modifiers = modifiers; 73 m_timestamp = timestamp; 74 } 75 76 void append(const WebCore::PlatformTouchPoint& point) 77 { 78 m_touchPoints.append(point); 79 } 80 }; 81 82 void ConvertInspectorPoint(WebCore::Page* page, const WebCore::IntPoint& point, WebCore::IntPoint* convertedPoint, WebCore::IntPoint* globalPoint) 83 { 84 *convertedPoint = page->deprecatedLocalMainFrame()->view()->convertToContainingWindow(point); 85 *globalPoint = page->chrome().rootViewToScreen(WebCore::IntRect(point, WebCore::IntSize(0, 0))).location(); 86 } 87 88 } // namespace 89 90 namespace WebCore { 91 92 InspectorInputAgent::InspectorInputAgent(Page* page, InspectorClient* client) 93 : InspectorBaseAgent<InspectorInputAgent>("Input") 94 , m_page(page), m_client(client) 95 { 96 } 97 98 InspectorInputAgent::~InspectorInputAgent() 99 { 100 } 101 102 void InspectorInputAgent::dispatchKeyEvent(ErrorString* error, const String& type, const int* modifiers, const double* timestamp, const String* text, const String* unmodifiedText, const String* keyIdentifier, const int* windowsVirtualKeyCode, const int* nativeVirtualKeyCode, const bool* autoRepeat, const bool* isKeypad, const bool* isSystemKey) 103 { 104 PlatformEvent::Type convertedType; 105 if (type == "keyDown") 106 convertedType = PlatformEvent::KeyDown; 107 else if (type == "keyUp") 108 convertedType = PlatformEvent::KeyUp; 109 else if (type == "char") 110 convertedType = PlatformEvent::Char; 111 else if (type == "rawKeyDown") 112 convertedType = PlatformEvent::RawKeyDown; 113 else { 114 *error = "Unrecognized type: " + type; 115 return; 116 } 117 118 PlatformKeyboardEvent event( 119 convertedType, 120 text ? *text : "", 121 unmodifiedText ? *unmodifiedText : "", 122 keyIdentifier ? *keyIdentifier : "", 123 windowsVirtualKeyCode ? *windowsVirtualKeyCode : 0, 124 nativeVirtualKeyCode ? *nativeVirtualKeyCode : 0, 125 autoRepeat ? *autoRepeat : false, 126 isKeypad ? *isKeypad : false, 127 isSystemKey ? *isSystemKey : false, 128 static_cast<PlatformEvent::Modifiers>(modifiers ? *modifiers : 0), 129 timestamp ? *timestamp : currentTime()); 130 m_client->dispatchKeyEvent(event); 131 } 132 133 void InspectorInputAgent::dispatchMouseEvent(ErrorString* error, const String& type, int x, int y, const int* modifiers, const double* timestamp, const String* button, const int* clickCount, const bool* deviceSpace) 134 { 135 if (deviceSpace && *deviceSpace) { 136 *error = "Internal error: events with device coordinates should be processed on the embedder level."; 137 return; 138 } 139 PlatformEvent::Type convertedType; 140 if (type == "mousePressed") 141 convertedType = PlatformEvent::MousePressed; 142 else if (type == "mouseReleased") 143 convertedType = PlatformEvent::MouseReleased; 144 else if (type == "mouseMoved") 145 convertedType = PlatformEvent::MouseMoved; 146 else { 147 *error = "Unrecognized type: " + type; 148 return; 149 } 150 151 int convertedModifiers = modifiers ? *modifiers : 0; 152 153 MouseButton convertedButton = NoButton; 154 if (button) { 155 if (*button == "left") 156 convertedButton = LeftButton; 157 else if (*button == "middle") 158 convertedButton = MiddleButton; 159 else if (*button == "right") 160 convertedButton = RightButton; 161 else if (*button != "none") { 162 *error = "Unrecognized button: " + *button; 163 return; 164 } 165 } 166 167 // Some platforms may have flipped coordinate systems, but the given coordinates 168 // assume the origin is in the top-left of the window. Convert. 169 IntPoint convertedPoint, globalPoint; 170 ConvertInspectorPoint(m_page, IntPoint(x, y), &convertedPoint, &globalPoint); 171 172 PlatformMouseEvent event( 173 convertedPoint, 174 globalPoint, 175 convertedButton, 176 convertedType, 177 clickCount ? *clickCount : 0, 178 convertedModifiers & PlatformEvent::ShiftKey, 179 convertedModifiers & PlatformEvent::CtrlKey, 180 convertedModifiers & PlatformEvent::AltKey, 181 convertedModifiers & PlatformEvent::MetaKey, 182 timestamp ? *timestamp : currentTime()); 183 184 m_client->dispatchMouseEvent(event); 185 } 186 187 void InspectorInputAgent::dispatchTouchEvent(ErrorString* error, const String& type, const RefPtr<JSONArray>& touchPoints, const int* modifiers, const double* timestamp) 188 { 189 PlatformEvent::Type convertedType; 190 if (type == "touchStart") { 191 convertedType = PlatformEvent::TouchStart; 192 } else if (type == "touchEnd") { 193 convertedType = PlatformEvent::TouchEnd; 194 } else if (type == "touchMove") { 195 convertedType = PlatformEvent::TouchMove; 196 } else { 197 *error = "Unrecognized type: " + type; 198 return; 199 } 200 201 unsigned convertedModifiers = modifiers ? *modifiers : 0; 202 203 SyntheticInspectorTouchEvent event(convertedType, convertedModifiers, timestamp ? *timestamp : currentTime()); 204 205 int autoId = 0; 206 JSONArrayBase::iterator iter; 207 for (iter = touchPoints->begin(); iter != touchPoints->end(); ++iter) { 208 RefPtr<JSONObject> pointObj; 209 String state; 210 int x, y, radiusX, radiusY, id; 211 double rotationAngle, force; 212 (*iter)->asObject(&pointObj); 213 if (!pointObj->getString("state", &state)) { 214 *error = "TouchPoint missing 'state'"; 215 return; 216 } 217 if (!pointObj->getNumber("x", &x)) { 218 *error = "TouchPoint missing 'x' coordinate"; 219 return; 220 } 221 if (!pointObj->getNumber("y", &y)) { 222 *error = "TouchPoint missing 'y' coordinate"; 223 return; 224 } 225 if (!pointObj->getNumber("radiusX", &radiusX)) 226 radiusX = 1; 227 if (!pointObj->getNumber("radiusY", &radiusY)) 228 radiusY = 1; 229 if (!pointObj->getNumber("rotationAngle", &rotationAngle)) 230 rotationAngle = 0.0f; 231 if (!pointObj->getNumber("force", &force)) 232 force = 1.0f; 233 if (pointObj->getNumber("id", &id)) { 234 if (autoId > 0) 235 id = -1; 236 autoId = -1; 237 } else { 238 id = autoId++; 239 } 240 if (id < 0) { 241 *error = "All or none of the provided TouchPoints must supply positive integer ids."; 242 return; 243 } 244 245 PlatformTouchPoint::State convertedState; 246 if (state == "touchPressed") { 247 convertedState = PlatformTouchPoint::TouchPressed; 248 } else if (state == "touchReleased") { 249 convertedState = PlatformTouchPoint::TouchReleased; 250 } else if (state == "touchMoved") { 251 convertedState = PlatformTouchPoint::TouchMoved; 252 } else if (state == "touchStationary") { 253 convertedState = PlatformTouchPoint::TouchStationary; 254 } else if (state == "touchCancelled") { 255 convertedState = PlatformTouchPoint::TouchCancelled; 256 } else { 257 *error = "Unrecognized state: " + state; 258 return; 259 } 260 261 // Some platforms may have flipped coordinate systems, but the given coordinates 262 // assume the origin is in the top-left of the window. Convert. 263 IntPoint convertedPoint, globalPoint; 264 ConvertInspectorPoint(m_page, IntPoint(x, y), &convertedPoint, &globalPoint); 265 266 SyntheticInspectorTouchPoint point(id++, convertedState, globalPoint, convertedPoint, radiusX, radiusY, rotationAngle, force); 267 event.append(point); 268 } 269 270 m_page->deprecatedLocalMainFrame()->eventHandler().handleTouchEvent(event); 271 } 272 273 } // namespace WebCore 274 275