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 #ifndef WebInputEvent_h 32 #define WebInputEvent_h 33 34 #include "../platform/WebCommon.h" 35 #include "../platform/WebRect.h" 36 #include "WebTouchPoint.h" 37 38 #include <string.h> 39 40 namespace blink { 41 42 // The classes defined in this file are intended to be used with 43 // WebWidget's handleInputEvent method. These event types are cross- 44 // platform and correspond closely to WebCore's Platform*Event classes. 45 // 46 // WARNING! These classes must remain PODs (plain old data). They are 47 // intended to be "serializable" by copying their raw bytes, so they must 48 // not contain any non-bit-copyable member variables! 49 // 50 // Furthermore, the class members need to be packed so they are aligned 51 // properly and don't have paddings/gaps, otherwise memory check tools 52 // like Valgrind will complain about uninitialized memory usage when 53 // transferring these classes over the wire. 54 55 #pragma pack(push, 4) 56 57 // WebInputEvent -------------------------------------------------------------- 58 59 class WebInputEvent { 60 public: 61 WebInputEvent(unsigned sizeParam = sizeof(WebInputEvent)) 62 { 63 memset(this, 0, sizeParam); 64 timeStampSeconds = 0.0; 65 size = sizeParam; 66 type = Undefined; 67 modifiers = 0; 68 } 69 70 // When we use an input method (or an input method editor), we receive 71 // two events for a keypress. The former event is a keydown, which 72 // provides a keycode, and the latter is a textinput, which provides 73 // a character processed by an input method. (The mapping from a 74 // keycode to a character code is not trivial for non-English 75 // keyboards.) 76 // To support input methods, Safari sends keydown events to WebKit for 77 // filtering. WebKit sends filtered keydown events back to Safari, 78 // which sends them to input methods. 79 // Unfortunately, it is hard to apply this design to Chrome because of 80 // our multiprocess architecture. An input method is running in a 81 // browser process. On the other hand, WebKit is running in a renderer 82 // process. So, this design results in increasing IPC messages. 83 // To support input methods without increasing IPC messages, Chrome 84 // handles keyboard events in a browser process and send asynchronous 85 // input events (to be translated to DOM events) to a renderer 86 // process. 87 // This design is mostly the same as the one of Windows and Mac Carbon. 88 // So, for what it's worth, our Linux and Mac front-ends emulate our 89 // Windows front-end. To emulate our Windows front-end, we can share 90 // our back-end code among Windows, Linux, and Mac. 91 // TODO(hbono): Issue 18064: remove the KeyDown type since it isn't 92 // used in Chrome any longer. 93 94 enum Type { 95 Undefined = -1, 96 97 // WebMouseEvent 98 MouseDown, 99 MouseUp, 100 MouseMove, 101 MouseEnter, 102 MouseLeave, 103 ContextMenu, 104 105 // WebMouseWheelEvent 106 MouseWheel, 107 108 // WebKeyboardEvent 109 RawKeyDown, 110 KeyDown, 111 KeyUp, 112 Char, 113 114 // WebGestureEvent 115 GestureScrollBegin, 116 GestureScrollEnd, 117 GestureScrollUpdate, 118 GestureScrollUpdateWithoutPropagation, 119 GestureFlingStart, 120 GestureFlingCancel, 121 GestureShowPress, 122 GestureTap, 123 GestureTapUnconfirmed, 124 GestureTapDown, 125 GestureTapCancel, 126 GestureDoubleTap, 127 GestureTwoFingerTap, 128 GestureLongPress, 129 GestureLongTap, 130 GesturePinchBegin, 131 GesturePinchEnd, 132 GesturePinchUpdate, 133 134 // WebTouchEvent 135 TouchStart, 136 TouchMove, 137 TouchEnd, 138 TouchCancel, 139 }; 140 141 enum Modifiers { 142 // modifiers for all events: 143 ShiftKey = 1 << 0, 144 ControlKey = 1 << 1, 145 AltKey = 1 << 2, 146 MetaKey = 1 << 3, 147 148 // modifiers for keyboard events: 149 IsKeyPad = 1 << 4, 150 IsAutoRepeat = 1 << 5, 151 152 // modifiers for mouse events: 153 LeftButtonDown = 1 << 6, 154 MiddleButtonDown = 1 << 7, 155 RightButtonDown = 1 << 8, 156 157 // Toggle modifiers for all events. Danger: these are not reflected 158 // into WebCore, so round-tripping from WebInputEvent to a WebCore 159 // event and back will not preserve these flags. 160 CapsLockOn = 1 << 9, 161 NumLockOn = 1 << 10, 162 163 // Left/right modifiers for keyboard events. 164 IsLeft = 1 << 11, 165 IsRight = 1 << 12, 166 167 // Last input event to be sent for the current vsync interval. If this 168 // flag is set, the sender guarantees that no more input events will be 169 // delivered until the next vsync and the receiver can schedule 170 // rendering accordingly. If it isn't set, the receiver should not make 171 // any assumptions about the delivery times of future input events 172 // w.r.t. vsync. 173 IsLastInputEventForCurrentVSync = 1 << 13, 174 }; 175 176 static const int InputModifiers = ShiftKey | ControlKey | AltKey | MetaKey; 177 178 double timeStampSeconds; // Seconds since epoch. 179 unsigned size; // The size of this structure, for serialization. 180 Type type; 181 int modifiers; 182 183 // Returns true if the WebInputEvent |type| is a mouse event. isMouseEventType(int type)184 static bool isMouseEventType(int type) 185 { 186 return type == MouseDown 187 || type == MouseUp 188 || type == MouseMove 189 || type == MouseEnter 190 || type == MouseLeave 191 || type == ContextMenu; 192 } 193 194 // Returns true if the WebInputEvent |type| is a keyboard event. isKeyboardEventType(int type)195 static bool isKeyboardEventType(int type) 196 { 197 return type == RawKeyDown 198 || type == KeyDown 199 || type == KeyUp 200 || type == Char; 201 } 202 203 // Returns true if the WebInputEvent |type| is a touch event. isTouchEventType(int type)204 static bool isTouchEventType(int type) 205 { 206 return type == TouchStart 207 || type == TouchMove 208 || type == TouchEnd 209 || type == TouchCancel; 210 } 211 212 // Returns true if the WebInputEvent |type| should be handled as user gesture. isUserGestureEventType(int type)213 static bool isUserGestureEventType(int type) 214 { 215 return isKeyboardEventType(type) 216 || type == MouseDown 217 || type == MouseUp 218 || type == TouchStart 219 || type == TouchEnd; 220 } 221 222 // Returns true if the WebInputEvent is a gesture event. isGestureEventType(int type)223 static bool isGestureEventType(int type) 224 { 225 return type == GestureScrollBegin 226 || type == GestureScrollEnd 227 || type == GestureScrollUpdate 228 || type == GestureScrollUpdateWithoutPropagation 229 || type == GestureFlingStart 230 || type == GestureFlingCancel 231 || type == GesturePinchBegin 232 || type == GesturePinchEnd 233 || type == GesturePinchUpdate 234 || type == GestureTap 235 || type == GestureTapUnconfirmed 236 || type == GestureTapDown 237 || type == GestureTapCancel 238 || type == GestureShowPress 239 || type == GestureDoubleTap 240 || type == GestureTwoFingerTap 241 || type == GestureLongPress 242 || type == GestureLongTap; 243 } 244 }; 245 246 // WebKeyboardEvent ----------------------------------------------------------- 247 248 class WebKeyboardEvent : public WebInputEvent { 249 public: 250 // Caps on string lengths so we can make them static arrays and keep 251 // them PODs. 252 static const size_t textLengthCap = 4; 253 254 // http://www.w3.org/TR/DOM-Level-3-Events/keyset.html lists the 255 // identifiers. The longest is 18 characters, so we round up to the 256 // next multiple of 4. 257 static const size_t keyIdentifierLengthCap = 20; 258 259 // |windowsKeyCode| is the Windows key code associated with this key 260 // event. Sometimes it's direct from the event (i.e. on Windows), 261 // sometimes it's via a mapping function. If you want a list, see 262 // WebCore/platform/chromium/KeyboardCodes* . Note that this should 263 // ALWAYS store the non-locational version of a keycode as this is 264 // what is returned by the Windows API. For example, it should 265 // store VK_SHIFT instead of VK_RSHIFT. The location information 266 // should be stored in |modifiers|. 267 int windowsKeyCode; 268 269 // The actual key code genenerated by the platform. The DOM spec runs 270 // on Windows-equivalent codes (thus |windowsKeyCode| above) but it 271 // doesn't hurt to have this one around. 272 int nativeKeyCode; 273 274 // This identifies whether this event was tagged by the system as being 275 // a "system key" event (see 276 // http://msdn.microsoft.com/en-us/library/ms646286(VS.85).aspx for 277 // details). Other platforms don't have this concept, but it's just 278 // easier to leave it always false than ifdef. 279 // See comment at the top of the file for why an int is used here. 280 bool isSystemKey; 281 282 // |text| is the text generated by this keystroke. |unmodifiedText| is 283 // |text|, but unmodified by an concurrently-held modifiers (except 284 // shift). This is useful for working out shortcut keys. Linux and 285 // Windows guarantee one character per event. The Mac does not, but in 286 // reality that's all it ever gives. We're generous, and cap it a bit 287 // longer. 288 WebUChar text[textLengthCap]; 289 WebUChar unmodifiedText[textLengthCap]; 290 291 // This is a string identifying the key pressed. 292 char keyIdentifier[keyIdentifierLengthCap]; 293 294 WebKeyboardEvent(unsigned sizeParam = sizeof(WebKeyboardEvent)) WebInputEvent(sizeParam)295 : WebInputEvent(sizeParam) 296 , windowsKeyCode(0) 297 , nativeKeyCode(0) 298 , isSystemKey(false) 299 { 300 memset(&text, 0, sizeof(text)); 301 memset(&unmodifiedText, 0, sizeof(unmodifiedText)); 302 memset(&keyIdentifier, 0, sizeof(keyIdentifier)); 303 } 304 305 // Sets keyIdentifier based on the value of windowsKeyCode. This is 306 // handy for generating synthetic keyboard events. 307 BLINK_EXPORT void setKeyIdentifierFromWindowsKeyCode(); 308 309 static int windowsKeyCodeWithoutLocation(int keycode); 310 static int locationModifiersFromWindowsKeyCode(int keycode); 311 }; 312 313 // WebMouseEvent -------------------------------------------------------------- 314 315 class WebMouseEvent : public WebInputEvent { 316 public: 317 // These values defined for WebCore::MouseButton 318 enum Button { 319 ButtonNone = -1, 320 ButtonLeft, 321 ButtonMiddle, 322 ButtonRight 323 }; 324 325 Button button; 326 int x; 327 int y; 328 int windowX; 329 int windowY; 330 int globalX; 331 int globalY; 332 int movementX; 333 int movementY; 334 int clickCount; 335 336 WebMouseEvent(unsigned sizeParam = sizeof(WebMouseEvent)) WebInputEvent(sizeParam)337 : WebInputEvent(sizeParam) 338 , button(ButtonNone) 339 , x(0) 340 , y(0) 341 , windowX(0) 342 , windowY(0) 343 , globalX(0) 344 , globalY(0) 345 , movementX(0) 346 , movementY(0) 347 , clickCount(0) 348 { 349 } 350 }; 351 352 // WebMouseWheelEvent --------------------------------------------------------- 353 354 class WebMouseWheelEvent : public WebMouseEvent { 355 public: 356 enum Phase { 357 PhaseNone = 0, 358 PhaseBegan = 1 << 0, 359 PhaseStationary = 1 << 1, 360 PhaseChanged = 1 << 2, 361 PhaseEnded = 1 << 3, 362 PhaseCancelled = 1 << 4, 363 PhaseMayBegin = 1 << 5, 364 }; 365 366 float deltaX; 367 float deltaY; 368 float wheelTicksX; 369 float wheelTicksY; 370 371 float accelerationRatioX; 372 float accelerationRatioY; 373 374 // See comment at the top of the file for why an int is used here. 375 int scrollByPage; 376 377 // See comment at the top of the file for why an int is used here. 378 int hasPreciseScrollingDeltas; 379 Phase phase; 380 Phase momentumPhase; 381 382 WebMouseWheelEvent(unsigned sizeParam = sizeof(WebMouseWheelEvent)) WebMouseEvent(sizeParam)383 : WebMouseEvent(sizeParam) 384 , deltaX(0.0f) 385 , deltaY(0.0f) 386 , wheelTicksX(0.0f) 387 , wheelTicksY(0.0f) 388 , accelerationRatioX(1.0f) 389 , accelerationRatioY(1.0f) 390 , scrollByPage(false) 391 , hasPreciseScrollingDeltas(false) 392 , phase(PhaseNone) 393 , momentumPhase(PhaseNone) 394 { 395 } 396 }; 397 398 // WebGestureEvent -------------------------------------------------------------- 399 400 class WebGestureEvent : public WebInputEvent { 401 public: 402 enum SourceDevice { 403 Touchpad, 404 Touchscreen, 405 }; 406 407 int x; 408 int y; 409 int globalX; 410 int globalY; 411 SourceDevice sourceDevice; 412 413 union { 414 struct { 415 int tapCount; 416 float width; 417 float height; 418 } tap; 419 420 struct { 421 float width; 422 float height; 423 } tapDown; 424 425 struct { 426 float width; 427 float height; 428 } showPress; 429 430 struct { 431 float width; 432 float height; 433 } longPress; 434 435 struct { 436 float firstFingerWidth; 437 float firstFingerHeight; 438 } twoFingerTap; 439 440 struct { 441 float deltaX; 442 float deltaY; 443 float velocityX; 444 float velocityY; 445 } scrollUpdate; 446 447 struct { 448 float velocityX; 449 float velocityY; 450 } flingStart; 451 452 struct { 453 float scale; 454 } pinchUpdate; 455 } data; 456 457 WebGestureEvent(unsigned sizeParam = sizeof(WebGestureEvent)) WebInputEvent(sizeParam)458 : WebInputEvent(sizeParam) 459 , x(0) 460 , y(0) 461 , globalX(0) 462 , globalY(0) 463 { 464 memset(&data, 0, sizeof(data)); 465 } 466 }; 467 468 // WebTouchEvent -------------------------------------------------------------- 469 470 class WebTouchEvent : public WebInputEvent { 471 public: 472 // Maximum number of simultaneous touches supported on 473 // Ash/Aura. 474 enum { touchesLengthCap = 12 }; 475 476 unsigned touchesLength; 477 // List of all touches which are currently down. 478 WebTouchPoint touches[touchesLengthCap]; 479 480 unsigned changedTouchesLength; 481 // List of all touches whose state has changed since the last WebTouchEvent 482 WebTouchPoint changedTouches[touchesLengthCap]; 483 484 unsigned targetTouchesLength; 485 // List of all touches which are currently down and are targeting the event recipient. 486 WebTouchPoint targetTouches[touchesLengthCap]; 487 488 WebTouchEvent(unsigned sizeParam = sizeof(WebTouchEvent)) WebInputEvent(sizeParam)489 : WebInputEvent(sizeParam) 490 , touchesLength(0) 491 , changedTouchesLength(0) 492 , targetTouchesLength(0) 493 { 494 } 495 }; 496 497 #pragma pack(pop) 498 499 } // namespace blink 500 501 #endif 502