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 51namespace { 52 53class SyntheticInspectorTouchPoint : public blink::PlatformTouchPoint { 54public: 55 SyntheticInspectorTouchPoint(unsigned id, State state, const blink::IntPoint& screenPos, const blink::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 = blink::FloatSize(radiusX, radiusY); 62 m_rotationAngle = rotationAngle; 63 m_force = force; 64 } 65}; 66 67class SyntheticInspectorTouchEvent : public blink::PlatformTouchEvent { 68public: 69 SyntheticInspectorTouchEvent(const blink::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 blink::PlatformTouchPoint& point) 77 { 78 m_touchPoints.append(point); 79 } 80}; 81 82void ConvertInspectorPoint(blink::Page* page, const blink::IntPoint& point, blink::IntPoint* convertedPoint, blink::IntPoint* globalPoint) 83{ 84 *convertedPoint = page->deprecatedLocalMainFrame()->view()->convertToContainingWindow(point); 85 *globalPoint = page->chrome().rootViewToScreen(blink::IntRect(point, blink::IntSize(0, 0))).location(); 86} 87 88} // namespace 89 90namespace blink { 91 92InspectorInputAgent::InspectorInputAgent(Page* page, InspectorClient* client) 93 : InspectorBaseAgent<InspectorInputAgent>("Input") 94 , m_page(page), m_client(client) 95{ 96} 97 98InspectorInputAgent::~InspectorInputAgent() 99{ 100} 101 102void 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 asBool(autoRepeat), 126 asBool(isKeypad), 127 asBool(isSystemKey), 128 static_cast<PlatformEvent::Modifiers>(modifiers ? *modifiers : 0), 129 timestamp ? *timestamp : currentTime()); 130 m_client->dispatchKeyEvent(event); 131} 132 133void InspectorInputAgent::dispatchMouseEvent(ErrorString* error, const String& type, int x, int y, const int* modifiers, const double* timestamp, const String* button, const int* clickCount) 134{ 135 PlatformEvent::Type convertedType; 136 if (type == "mousePressed") 137 convertedType = PlatformEvent::MousePressed; 138 else if (type == "mouseReleased") 139 convertedType = PlatformEvent::MouseReleased; 140 else if (type == "mouseMoved") 141 convertedType = PlatformEvent::MouseMoved; 142 else { 143 *error = "Unrecognized type: " + type; 144 return; 145 } 146 147 int convertedModifiers = modifiers ? *modifiers : 0; 148 149 MouseButton convertedButton = NoButton; 150 if (button) { 151 if (*button == "left") 152 convertedButton = LeftButton; 153 else if (*button == "middle") 154 convertedButton = MiddleButton; 155 else if (*button == "right") 156 convertedButton = RightButton; 157 else if (*button != "none") { 158 *error = "Unrecognized button: " + *button; 159 return; 160 } 161 } 162 163 // Some platforms may have flipped coordinate systems, but the given coordinates 164 // assume the origin is in the top-left of the window. Convert. 165 IntPoint convertedPoint, globalPoint; 166 ConvertInspectorPoint(m_page, IntPoint(x, y), &convertedPoint, &globalPoint); 167 168 PlatformMouseEvent event( 169 convertedPoint, 170 globalPoint, 171 convertedButton, 172 convertedType, 173 clickCount ? *clickCount : 0, 174 convertedModifiers & PlatformEvent::ShiftKey, 175 convertedModifiers & PlatformEvent::CtrlKey, 176 convertedModifiers & PlatformEvent::AltKey, 177 convertedModifiers & PlatformEvent::MetaKey, 178 PlatformMouseEvent::RealOrIndistinguishable, 179 timestamp ? *timestamp : currentTime()); 180 181 m_client->dispatchMouseEvent(event); 182} 183 184void InspectorInputAgent::dispatchTouchEvent(ErrorString* error, const String& type, const RefPtr<JSONArray>& touchPoints, const int* modifiers, const double* timestamp) 185{ 186 PlatformEvent::Type convertedType; 187 if (type == "touchStart") { 188 convertedType = PlatformEvent::TouchStart; 189 } else if (type == "touchEnd") { 190 convertedType = PlatformEvent::TouchEnd; 191 } else if (type == "touchMove") { 192 convertedType = PlatformEvent::TouchMove; 193 } else { 194 *error = "Unrecognized type: " + type; 195 return; 196 } 197 198 unsigned convertedModifiers = modifiers ? *modifiers : 0; 199 200 SyntheticInspectorTouchEvent event(convertedType, convertedModifiers, timestamp ? *timestamp : currentTime()); 201 202 int autoId = 0; 203 JSONArrayBase::iterator iter; 204 for (iter = touchPoints->begin(); iter != touchPoints->end(); ++iter) { 205 RefPtr<JSONObject> pointObj; 206 String state; 207 int x, y, radiusX, radiusY, id; 208 double rotationAngle, force; 209 (*iter)->asObject(&pointObj); 210 if (!pointObj->getString("state", &state)) { 211 *error = "TouchPoint missing 'state'"; 212 return; 213 } 214 if (!pointObj->getNumber("x", &x)) { 215 *error = "TouchPoint missing 'x' coordinate"; 216 return; 217 } 218 if (!pointObj->getNumber("y", &y)) { 219 *error = "TouchPoint missing 'y' coordinate"; 220 return; 221 } 222 if (!pointObj->getNumber("radiusX", &radiusX)) 223 radiusX = 1; 224 if (!pointObj->getNumber("radiusY", &radiusY)) 225 radiusY = 1; 226 if (!pointObj->getNumber("rotationAngle", &rotationAngle)) 227 rotationAngle = 0.0f; 228 if (!pointObj->getNumber("force", &force)) 229 force = 1.0f; 230 if (pointObj->getNumber("id", &id)) { 231 if (autoId > 0) 232 id = -1; 233 autoId = -1; 234 } else { 235 id = autoId++; 236 } 237 if (id < 0) { 238 *error = "All or none of the provided TouchPoints must supply positive integer ids."; 239 return; 240 } 241 242 PlatformTouchPoint::State convertedState; 243 if (state == "touchPressed") { 244 convertedState = PlatformTouchPoint::TouchPressed; 245 } else if (state == "touchReleased") { 246 convertedState = PlatformTouchPoint::TouchReleased; 247 } else if (state == "touchMoved") { 248 convertedState = PlatformTouchPoint::TouchMoved; 249 } else if (state == "touchStationary") { 250 convertedState = PlatformTouchPoint::TouchStationary; 251 } else if (state == "touchCancelled") { 252 convertedState = PlatformTouchPoint::TouchCancelled; 253 } else { 254 *error = "Unrecognized state: " + state; 255 return; 256 } 257 258 // Some platforms may have flipped coordinate systems, but the given coordinates 259 // assume the origin is in the top-left of the window. Convert. 260 IntPoint convertedPoint, globalPoint; 261 ConvertInspectorPoint(m_page, IntPoint(x, y), &convertedPoint, &globalPoint); 262 263 SyntheticInspectorTouchPoint point(id++, convertedState, globalPoint, convertedPoint, radiusX, radiusY, rotationAngle, force); 264 event.append(point); 265 } 266 267 m_page->deprecatedLocalMainFrame()->eventHandler().handleTouchEvent(event); 268} 269 270void InspectorInputAgent::trace(Visitor* visitor) 271{ 272 visitor->trace(m_page); 273 InspectorBaseAgent::trace(visitor); 274} 275 276} // namespace blink 277 278