1 /* 2 * Copyright (C) 2009 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 "WebInputEventConversion.h" 33 34 #include "EventNames.h" 35 #include "KeyboardCodes.h" 36 #include "KeyboardEvent.h" 37 #include "MouseEvent.h" 38 #include "PlatformKeyboardEvent.h" 39 #include "PlatformMouseEvent.h" 40 #include "PlatformWheelEvent.h" 41 #include "ScrollView.h" 42 #include "WebInputEvent.h" 43 #include "WheelEvent.h" 44 #include "Widget.h" 45 46 using namespace WebCore; 47 48 namespace WebKit { 49 50 // MakePlatformMouseEvent ----------------------------------------------------- 51 52 PlatformMouseEventBuilder::PlatformMouseEventBuilder(Widget* widget, const WebMouseEvent& e) 53 { 54 // FIXME: widget is always toplevel, unless it's a popup. We may be able 55 // to get rid of this once we abstract popups into a WebKit API. 56 m_position = widget->convertFromContainingWindow(IntPoint(e.x, e.y)); 57 m_globalPosition = IntPoint(e.globalX, e.globalY); 58 m_button = static_cast<MouseButton>(e.button); 59 m_shiftKey = (e.modifiers & WebInputEvent::ShiftKey); 60 m_ctrlKey = (e.modifiers & WebInputEvent::ControlKey); 61 m_altKey = (e.modifiers & WebInputEvent::AltKey); 62 m_metaKey = (e.modifiers & WebInputEvent::MetaKey); 63 m_modifierFlags = e.modifiers; 64 m_timestamp = e.timeStampSeconds; 65 m_clickCount = e.clickCount; 66 67 switch (e.type) { 68 case WebInputEvent::MouseMove: 69 case WebInputEvent::MouseLeave: // synthesize a move event 70 m_eventType = MouseEventMoved; 71 break; 72 73 case WebInputEvent::MouseDown: 74 m_eventType = MouseEventPressed; 75 break; 76 77 case WebInputEvent::MouseUp: 78 m_eventType = MouseEventReleased; 79 break; 80 81 default: 82 ASSERT_NOT_REACHED(); 83 } 84 } 85 86 // PlatformWheelEventBuilder -------------------------------------------------- 87 88 PlatformWheelEventBuilder::PlatformWheelEventBuilder(Widget* widget, const WebMouseWheelEvent& e) 89 { 90 m_position = widget->convertFromContainingWindow(IntPoint(e.x, e.y)); 91 m_globalPosition = IntPoint(e.globalX, e.globalY); 92 m_deltaX = e.deltaX; 93 m_deltaY = e.deltaY; 94 m_wheelTicksX = e.wheelTicksX; 95 m_wheelTicksY = e.wheelTicksY; 96 m_isAccepted = false; 97 m_granularity = e.scrollByPage ? 98 ScrollByPageWheelEvent : ScrollByPixelWheelEvent; 99 m_shiftKey = (e.modifiers & WebInputEvent::ShiftKey); 100 m_ctrlKey = (e.modifiers & WebInputEvent::ControlKey); 101 m_altKey = (e.modifiers & WebInputEvent::AltKey); 102 m_metaKey = (e.modifiers & WebInputEvent::MetaKey); 103 } 104 105 // MakePlatformKeyboardEvent -------------------------------------------------- 106 107 static inline PlatformKeyboardEvent::Type toPlatformKeyboardEventType(WebInputEvent::Type type) 108 { 109 switch (type) { 110 case WebInputEvent::KeyUp: 111 return PlatformKeyboardEvent::KeyUp; 112 case WebInputEvent::KeyDown: 113 return PlatformKeyboardEvent::KeyDown; 114 case WebInputEvent::RawKeyDown: 115 return PlatformKeyboardEvent::RawKeyDown; 116 case WebInputEvent::Char: 117 return PlatformKeyboardEvent::Char; 118 default: 119 ASSERT_NOT_REACHED(); 120 } 121 return PlatformKeyboardEvent::KeyDown; 122 } 123 124 PlatformKeyboardEventBuilder::PlatformKeyboardEventBuilder(const WebKeyboardEvent& e) 125 { 126 m_type = toPlatformKeyboardEventType(e.type); 127 m_text = String(e.text); 128 m_unmodifiedText = String(e.unmodifiedText); 129 m_keyIdentifier = String(e.keyIdentifier); 130 m_autoRepeat = (e.modifiers & WebInputEvent::IsAutoRepeat); 131 m_windowsVirtualKeyCode = e.windowsKeyCode; 132 m_nativeVirtualKeyCode = e.nativeKeyCode; 133 m_isKeypad = (e.modifiers & WebInputEvent::IsKeyPad); 134 m_shiftKey = (e.modifiers & WebInputEvent::ShiftKey); 135 m_ctrlKey = (e.modifiers & WebInputEvent::ControlKey); 136 m_altKey = (e.modifiers & WebInputEvent::AltKey); 137 m_metaKey = (e.modifiers & WebInputEvent::MetaKey); 138 m_isSystemKey = e.isSystemKey; 139 } 140 141 void PlatformKeyboardEventBuilder::setKeyType(Type type) 142 { 143 // According to the behavior of Webkit in Windows platform, 144 // we need to convert KeyDown to RawKeydown and Char events 145 // See WebKit/WebKit/Win/WebView.cpp 146 ASSERT(m_type == KeyDown); 147 ASSERT(type == RawKeyDown || type == Char); 148 m_type = type; 149 150 if (type == RawKeyDown) { 151 m_text = String(); 152 m_unmodifiedText = String(); 153 } else { 154 m_keyIdentifier = String(); 155 m_windowsVirtualKeyCode = 0; 156 } 157 } 158 159 // Please refer to bug http://b/issue?id=961192, which talks about Webkit 160 // keyboard event handling changes. It also mentions the list of keys 161 // which don't have associated character events. 162 bool PlatformKeyboardEventBuilder::isCharacterKey() const 163 { 164 switch (windowsVirtualKeyCode()) { 165 case VKEY_BACK: 166 case VKEY_ESCAPE: 167 return false; 168 } 169 return true; 170 } 171 172 #if ENABLE(TOUCH_EVENTS) 173 static inline TouchEventType toPlatformTouchEventType(const WebInputEvent::Type type) 174 { 175 switch (type) { 176 case WebInputEvent::TouchStart: 177 return TouchStart; 178 case WebInputEvent::TouchMove: 179 return TouchMove; 180 case WebInputEvent::TouchEnd: 181 return TouchEnd; 182 case WebInputEvent::TouchCancel: 183 return TouchCancel; 184 default: 185 ASSERT_NOT_REACHED(); 186 } 187 return TouchStart; 188 } 189 190 static inline PlatformTouchPoint::State toPlatformTouchPointState(const WebTouchPoint::State state) 191 { 192 switch (state) { 193 case WebTouchPoint::StateReleased: 194 return PlatformTouchPoint::TouchReleased; 195 case WebTouchPoint::StatePressed: 196 return PlatformTouchPoint::TouchPressed; 197 case WebTouchPoint::StateMoved: 198 return PlatformTouchPoint::TouchMoved; 199 case WebTouchPoint::StateStationary: 200 return PlatformTouchPoint::TouchStationary; 201 case WebTouchPoint::StateCancelled: 202 return PlatformTouchPoint::TouchCancelled; 203 case WebTouchPoint::StateUndefined: 204 ASSERT_NOT_REACHED(); 205 } 206 return PlatformTouchPoint::TouchReleased; 207 } 208 209 PlatformTouchPointBuilder::PlatformTouchPointBuilder(Widget* widget, const WebTouchPoint& point) 210 { 211 m_id = point.id; 212 m_state = toPlatformTouchPointState(point.state); 213 m_pos = widget->convertFromContainingWindow(point.position); 214 m_screenPos = point.screenPosition; 215 } 216 217 PlatformTouchEventBuilder::PlatformTouchEventBuilder(Widget* widget, const WebTouchEvent& event) 218 { 219 m_type = toPlatformTouchEventType(event.type); 220 m_ctrlKey = event.modifiers & WebInputEvent::ControlKey; 221 m_altKey = event.modifiers & WebInputEvent::AltKey; 222 m_shiftKey = event.modifiers & WebInputEvent::ShiftKey; 223 m_metaKey = event.modifiers & WebInputEvent::MetaKey; 224 m_timestamp = event.timeStampSeconds; 225 226 for (int i = 0; i < event.touchPointsLength; ++i) 227 m_touchPoints.append(PlatformTouchPointBuilder(widget, event.touchPoints[i])); 228 } 229 #endif 230 231 static int getWebInputModifiers(const UIEventWithKeyState& event) 232 { 233 int modifiers = 0; 234 if (event.ctrlKey()) 235 modifiers |= WebInputEvent::ControlKey; 236 if (event.shiftKey()) 237 modifiers |= WebInputEvent::ShiftKey; 238 if (event.altKey()) 239 modifiers |= WebInputEvent::AltKey; 240 if (event.metaKey()) 241 modifiers |= WebInputEvent::MetaKey; 242 return modifiers; 243 } 244 245 WebMouseEventBuilder::WebMouseEventBuilder(const Widget* widget, const MouseEvent& event) 246 { 247 if (event.type() == eventNames().mousemoveEvent) 248 type = WebInputEvent::MouseMove; 249 else if (event.type() == eventNames().mouseoutEvent) 250 type = WebInputEvent::MouseLeave; 251 else if (event.type() == eventNames().mouseoverEvent) 252 type = WebInputEvent::MouseEnter; 253 else if (event.type() == eventNames().mousedownEvent) 254 type = WebInputEvent::MouseDown; 255 else if (event.type() == eventNames().mouseupEvent) 256 type = WebInputEvent::MouseUp; 257 else if (event.type() == eventNames().contextmenuEvent) 258 type = WebInputEvent::ContextMenu; 259 else 260 return; // Skip all other mouse events. 261 timeStampSeconds = event.timeStamp() * 1.0e-3; 262 switch (event.button()) { 263 case LeftButton: 264 button = WebMouseEvent::ButtonLeft; 265 break; 266 case MiddleButton: 267 button = WebMouseEvent::ButtonMiddle; 268 break; 269 case RightButton: 270 button = WebMouseEvent::ButtonRight; 271 break; 272 } 273 modifiers = getWebInputModifiers(event); 274 if (event.buttonDown()) { 275 switch (event.button()) { 276 case LeftButton: 277 modifiers |= WebInputEvent::LeftButtonDown; 278 break; 279 case MiddleButton: 280 modifiers |= WebInputEvent::MiddleButtonDown; 281 break; 282 case RightButton: 283 modifiers |= WebInputEvent::RightButtonDown; 284 break; 285 } 286 } 287 ScrollView* view = widget->parent(); 288 IntPoint p = view->contentsToWindow( 289 IntPoint(event.absoluteLocation().x(), event.absoluteLocation().y())); 290 globalX = event.screenX(); 291 globalY = event.screenY(); 292 windowX = p.x(); 293 windowY = p.y(); 294 x = event.absoluteLocation().x() - widget->pos().x(); 295 y = event.absoluteLocation().y() - widget->pos().y(); 296 clickCount = event.detail(); 297 } 298 299 WebMouseWheelEventBuilder::WebMouseWheelEventBuilder(const Widget* widget, const WheelEvent& event) 300 { 301 if (event.type() != eventNames().mousewheelEvent) 302 return; 303 type = WebInputEvent::MouseWheel; 304 timeStampSeconds = event.timeStamp() * 1.0e-3; 305 modifiers = getWebInputModifiers(event); 306 ScrollView* view = widget->parent(); 307 IntPoint p = view->contentsToWindow( 308 IntPoint(event.absoluteLocation().x(), event.absoluteLocation().y())); 309 globalX = event.screenX(); 310 globalY = event.screenY(); 311 windowX = p.x(); 312 windowY = p.y(); 313 x = event.absoluteLocation().x() - widget->pos().x(); 314 y = event.absoluteLocation().y() - widget->pos().y(); 315 deltaX = static_cast<float>(event.rawDeltaX()); 316 deltaY = static_cast<float>(event.rawDeltaY()); 317 // The 120 is from WheelEvent::initWheelEvent(). 318 wheelTicksX = static_cast<float>(event.wheelDeltaX()) / 120; 319 wheelTicksY = static_cast<float>(event.wheelDeltaY()) / 120; 320 scrollByPage = event.granularity() == WheelEvent::Page; 321 } 322 323 WebKeyboardEventBuilder::WebKeyboardEventBuilder(const KeyboardEvent& event) 324 { 325 if (event.type() == eventNames().keydownEvent) 326 type = KeyDown; 327 else if (event.type() == eventNames().keyupEvent) 328 type = WebInputEvent::KeyUp; 329 else if (event.type() == eventNames().keypressEvent) 330 type = WebInputEvent::Char; 331 else 332 return; // Skip all other keyboard events. 333 modifiers = getWebInputModifiers(event); 334 timeStampSeconds = event.timeStamp() * 1.0e-3; 335 windowsKeyCode = event.keyCode(); 336 337 // The platform keyevent does not exist if the event was created using 338 // initKeyboardEvent. 339 if (!event.keyEvent()) 340 return; 341 nativeKeyCode = event.keyEvent()->nativeVirtualKeyCode(); 342 unsigned int numChars = std::min(event.keyEvent()->text().length(), 343 static_cast<unsigned int>(WebKeyboardEvent::textLengthCap)); 344 for (unsigned int i = 0; i < numChars; i++) { 345 text[i] = event.keyEvent()->text()[i]; 346 unmodifiedText[i] = event.keyEvent()->unmodifiedText()[i]; 347 } 348 } 349 350 } // namespace WebKit 351