15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2004, 2006, 2007 Apple Inc. All rights reserved.
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2006-2009 Google Inc.
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * are met:
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 1. Redistributions of source code must retain the above copyright
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    notice, this list of conditions and the following disclaimer.
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 2. Redistributions in binary form must reproduce the above copyright
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    notice, this list of conditions and the following disclaimer in the
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    documentation and/or other materials provided with the distribution.
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h"
28f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu#include "public/web/mac/WebInputEventFactory.h"
295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include <ApplicationServices/ApplicationServices.h>
31591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#import <AvailabilityMacros.h>
325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#import <Cocoa/Cocoa.h>
335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)#include "platform/WindowsKeyboardCodes.h"
35f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu#include "public/web/WebInputEvent.h"
36591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#include "wtf/ASCIICType.h"
375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
38591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#if __MAC_OS_X_VERSION_MAX_ALLOWED == 1060
395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Additional Lion APIs.
415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)enum {
425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    NSEventPhaseNone        = 0,
435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    NSEventPhaseBegan       = 0x1 << 0,
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    NSEventPhaseStationary  = 0x1 << 1,
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    NSEventPhaseChanged     = 0x1 << 2,
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    NSEventPhaseEnded       = 0x1 << 3,
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    NSEventPhaseCancelled   = 0x1 << 4
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)typedef NSUInteger NSEventPhase;
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)@interface NSEvent (LionSDKDeclarations)
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)- (NSEventPhase)phase;
535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)- (NSEventPhase)momentumPhase;
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)@end
555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
56591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#endif  // __MAC_OS_X_VERSION_MAX_ALLOWED == 1060
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#if __MAC_OS_X_VERSION_MAX_ALLOWED < 1080
595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Additional Mountain Lion APIs.
615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)enum {
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    NSEventPhaseMayBegin    = 0x1 << 5
635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif  // __MAC_OS_X_VERSION_MAX_ALLOWED < 1080
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)namespace blink {
685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
691e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)static int windowsKeyCodeForKeyCode(uint16_t keyCode)
701e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles){
711e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    static const int windowsKeyCode[] = {
721e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0 */ VK_A,
731e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 1 */ VK_S,
741e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 2 */ VK_D,
751e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 3 */ VK_F,
761e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 4 */ VK_H,
771e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 5 */ VK_G,
781e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 6 */ VK_Z,
791e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 7 */ VK_X,
801e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 8 */ VK_C,
811e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 9 */ VK_V,
821e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x0A */ VK_OEM_3, // "Section" - key to the left from 1 (ISO Keyboard Only)
831e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x0B */ VK_B,
841e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x0C */ VK_Q,
851e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x0D */ VK_W,
861e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x0E */ VK_E,
871e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x0F */ VK_R,
881e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x10 */ VK_Y,
891e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x11 */ VK_T,
901e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x12 */ VK_1,
911e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x13 */ VK_2,
921e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x14 */ VK_3,
931e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x15 */ VK_4,
941e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x16 */ VK_6,
951e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x17 */ VK_5,
961e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x18 */ VK_OEM_PLUS, // =+
971e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x19 */ VK_9,
981e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x1A */ VK_7,
991e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x1B */ VK_OEM_MINUS, // -_
1001e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x1C */ VK_8,
1011e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x1D */ VK_0,
1021e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x1E */ VK_OEM_6, // ]}
1031e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x1F */ VK_O,
1041e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x20 */ VK_U,
1051e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x21 */ VK_OEM_4, // {[
1061e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x22 */ VK_I,
1071e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x23 */ VK_P,
1081e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x24 */ VK_RETURN, // Return
1091e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x25 */ VK_L,
1101e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x26 */ VK_J,
1111e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x27 */ VK_OEM_7, // '"
1121e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x28 */ VK_K,
1131e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x29 */ VK_OEM_1, // ;:
1141e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x2A */ VK_OEM_5, // \|
1151e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x2B */ VK_OEM_COMMA, // ,<
1161e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x2C */ VK_OEM_2, // /?
1171e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x2D */ VK_N,
1181e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x2E */ VK_M,
1191e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x2F */ VK_OEM_PERIOD, // .>
1201e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x30 */ VK_TAB,
1211e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x31 */ VK_SPACE,
1221e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x32 */ VK_OEM_3, // `~
1231e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x33 */ VK_BACK, // Backspace
1241e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x34 */ 0, // n/a
1251e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x35 */ VK_ESCAPE,
1261e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x36 */ VK_APPS, // Right Command
1271e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x37 */ VK_LWIN, // Left Command
1281e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x38 */ VK_LSHIFT, // Left Shift
1291e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x39 */ VK_CAPITAL, // Caps Lock
1301e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x3A */ VK_LMENU, // Left Option
1311e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x3B */ VK_LCONTROL, // Left Ctrl
1321e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x3C */ VK_RSHIFT, // Right Shift
1331e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x3D */ VK_RMENU, // Right Option
1341e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x3E */ VK_RCONTROL, // Right Ctrl
1351e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x3F */ 0, // fn
1361e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x40 */ VK_F17,
1371e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x41 */ VK_DECIMAL, // Num Pad .
1381e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x42 */ 0, // n/a
1391e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x43 */ VK_MULTIPLY, // Num Pad *
1401e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x44 */ 0, // n/a
1411e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x45 */ VK_ADD, // Num Pad +
1421e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x46 */ 0, // n/a
1431e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x47 */ VK_CLEAR, // Num Pad Clear
1441e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x48 */ VK_VOLUME_UP,
1451e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x49 */ VK_VOLUME_DOWN,
1461e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x4A */ VK_VOLUME_MUTE,
1471e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x4B */ VK_DIVIDE, // Num Pad /
1481e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x4C */ VK_RETURN, // Num Pad Enter
1491e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x4D */ 0, // n/a
1501e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x4E */ VK_SUBTRACT, // Num Pad -
1511e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x4F */ VK_F18,
1521e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x50 */ VK_F19,
1531e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x51 */ VK_OEM_PLUS, // Num Pad =. There is no such key on common PC keyboards, mapping to normal "+=".
1541e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x52 */ VK_NUMPAD0,
1551e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x53 */ VK_NUMPAD1,
1561e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x54 */ VK_NUMPAD2,
1571e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x55 */ VK_NUMPAD3,
1581e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x56 */ VK_NUMPAD4,
1591e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x57 */ VK_NUMPAD5,
1601e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x58 */ VK_NUMPAD6,
1611e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x59 */ VK_NUMPAD7,
1621e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x5A */ VK_F20,
1631e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x5B */ VK_NUMPAD8,
1641e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x5C */ VK_NUMPAD9,
1651e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x5D */ 0, // Yen (JIS Keyboard Only)
1661e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x5E */ 0, // Underscore (JIS Keyboard Only)
1671e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x5F */ 0, // KeypadComma (JIS Keyboard Only)
1681e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x60 */ VK_F5,
1691e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x61 */ VK_F6,
1701e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x62 */ VK_F7,
1711e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x63 */ VK_F3,
1721e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x64 */ VK_F8,
1731e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x65 */ VK_F9,
1741e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x66 */ 0, // Eisu (JIS Keyboard Only)
1751e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x67 */ VK_F11,
1761e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x68 */ 0, // Kana (JIS Keyboard Only)
1771e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x69 */ VK_F13,
1781e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x6A */ VK_F16,
1791e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x6B */ VK_F14,
1801e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x6C */ 0, // n/a
1811e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x6D */ VK_F10,
1821e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x6E */ 0, // n/a (Windows95 key?)
1831e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x6F */ VK_F12,
1841e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x70 */ 0, // n/a
1851e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x71 */ VK_F15,
1861e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x72 */ VK_INSERT, // Help
1871e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x73 */ VK_HOME, // Home
1881e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x74 */ VK_PRIOR, // Page Up
1891e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x75 */ VK_DELETE, // Forward Delete
1901e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x76 */ VK_F4,
1911e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x77 */ VK_END, // End
1921e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x78 */ VK_F2,
1931e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x79 */ VK_NEXT, // Page Down
1941e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x7A */ VK_F1,
1951e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x7B */ VK_LEFT, // Left Arrow
1961e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x7C */ VK_RIGHT, // Right Arrow
1971e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x7D */ VK_DOWN, // Down Arrow
1981e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x7E */ VK_UP, // Up Arrow
1991e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        /* 0x7F */ 0 // n/a
2001e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    };
2011e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)
2021e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    if (keyCode >= 0x80)
2031e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        return 0;
2041e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)
2051e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)     return windowsKeyCode[keyCode];
2061e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)}
2071e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)
2081e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)static int windowsKeyCodeForCharCode(unichar charCode)
2091e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles){
2101e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    switch (charCode) {
2111e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)
2121e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        case 'a': case 'A': return VK_A;
2131e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        case 'b': case 'B': return VK_B;
2141e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        case 'c': case 'C': return VK_C;
2151e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        case 'd': case 'D': return VK_D;
2161e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        case 'e': case 'E': return VK_E;
2171e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        case 'f': case 'F': return VK_F;
2181e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        case 'g': case 'G': return VK_G;
2191e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        case 'h': case 'H': return VK_H;
2201e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        case 'i': case 'I': return VK_I;
2211e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        case 'j': case 'J': return VK_J;
2221e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        case 'k': case 'K': return VK_K;
2231e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        case 'l': case 'L': return VK_L;
2241e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        case 'm': case 'M': return VK_M;
2251e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        case 'n': case 'N': return VK_N;
2261e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        case 'o': case 'O': return VK_O;
2271e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        case 'p': case 'P': return VK_P;
2281e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        case 'q': case 'Q': return VK_Q;
2291e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        case 'r': case 'R': return VK_R;
2301e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        case 's': case 'S': return VK_S;
2311e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        case 't': case 'T': return VK_T;
2321e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        case 'u': case 'U': return VK_U;
2331e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        case 'v': case 'V': return VK_V;
2341e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        case 'w': case 'W': return VK_W;
2351e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        case 'x': case 'X': return VK_X;
2361e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        case 'y': case 'Y': return VK_Y;
2371e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        case 'z': case 'Z': return VK_Z;
2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2391e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        // AppKit generates Unicode PUA character codes for some function keys; using these when key code is not known.
2401e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        case NSPauseFunctionKey: return VK_PAUSE;
2411e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        case NSSelectFunctionKey: return VK_SELECT;
2421e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        case NSPrintFunctionKey: return VK_PRINT;
2431e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        case NSExecuteFunctionKey: return VK_EXECUTE;
2441e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        case NSPrintScreenFunctionKey: return VK_SNAPSHOT;
2451e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        case NSInsertFunctionKey: return VK_INSERT;
2461e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)
2471e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        case NSF21FunctionKey: return VK_F21;
2481e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        case NSF22FunctionKey: return VK_F22;
2491e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        case NSF23FunctionKey: return VK_F23;
2501e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        case NSF24FunctionKey: return VK_F24;
2511e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        case NSScrollLockFunctionKey: return VK_SCROLL;
2521e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)
2531e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        // This is for U.S. keyboard mapping, and doesn't necessarily make sense for different keyboard layouts.
2541e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        // For example, '"' on Windows Russian layout is VK_2, not VK_OEM_7.
2551e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        case ';': case ':': return VK_OEM_1;
2561e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        case '=': case '+': return VK_OEM_PLUS;
2571e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        case ',': case '<': return VK_OEM_COMMA;
2581e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        case '-': case '_': return VK_OEM_MINUS;
2591e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        case '.': case '>': return VK_OEM_PERIOD;
2601e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        case '/': case '?': return VK_OEM_2;
2611e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        case '`': case '~': return VK_OEM_3;
2621e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        case '[': case '{': return VK_OEM_4;
2631e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        case '\\': case '|': return VK_OEM_5;
2641e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        case ']': case '}': return VK_OEM_6;
2651e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        case '\'': case '"': return VK_OEM_7;
2661e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)
2671e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    }
2681e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)
2691e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    return 0;
2701e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)}
2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static inline bool isKeyUpEvent(NSEvent* event)
2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if ([event type] != NSFlagsChanged)
2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return [event type] == NSKeyUp;
2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // FIXME: This logic fails if the user presses both Shift keys at once, for example:
2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // we treat releasing one of them as keyDown.
2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    switch ([event keyCode]) {
2795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case 54: // Right Command
2805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case 55: // Left Command
2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return ([event modifierFlags] & NSCommandKeyMask) == 0;
2825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case 57: // Capslock
2845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return ([event modifierFlags] & NSAlphaShiftKeyMask) == 0;
2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case 56: // Left Shift
2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case 60: // Right Shift
2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return ([event modifierFlags] & NSShiftKeyMask) == 0;
2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case 58: // Left Alt
2915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case 61: // Right Alt
2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return ([event modifierFlags] & NSAlternateKeyMask) == 0;
2935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case 59: // Left Ctrl
2955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case 62: // Right Ctrl
2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return ([event modifierFlags] & NSControlKeyMask) == 0;
2975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case 63: // Function
2995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return ([event modifierFlags] & NSFunctionKeyMask) == 0;
3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return false;
3025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static bool isKeypadEvent(NSEvent* event)
3055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Check that this is the type of event that has a keyCode.
3075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    switch ([event type]) {
3085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSKeyDown:
3095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSKeyUp:
3105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSFlagsChanged:
3115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        break;
3125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    default:
3135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
3145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    switch ([event keyCode]) {
3175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case 71: // Clear
3185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case 81: // =
3195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case 75: // /
3205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case 67: // *
3215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case 78: // -
3225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case 69: // +
3235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case 76: // Enter
3245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case 65: // .
3255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case 82: // 0
3265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case 83: // 1
3275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case 84: // 2
3285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case 85: // 3
3295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case 86: // 4
3305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case 87: // 5
3315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case 88: // 6
3325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case 89: // 7
3335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case 91: // 8
3345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case 92: // 9
3355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
3365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return false;
3395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static int windowsKeyCodeForKeyEvent(NSEvent* event)
3425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int code = 0;
3445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // There are several kinds of characters for which we produce key code from char code:
3455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // 1. Roman letters. Windows keyboard layouts affect both virtual key codes and character codes for these,
3465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //    so e.g. 'A' gets the same keyCode on QWERTY, AZERTY or Dvorak layouts.
3475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // 2. Keys for which there is no known Mac virtual key codes, like PrintScreen.
3485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // 3. Certain punctuation keys. On Windows, these are also remapped depending on current keyboard layout,
3495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //    but see comment in windowsKeyCodeForCharCode().
3505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!isKeypadEvent(event) && ([event type] == NSKeyDown || [event type] == NSKeyUp)) {
3515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Cmd switches Roman letters for Dvorak-QWERTY layout, so try modified characters first.
3525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        NSString* s = [event characters];
3531e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        code = [s length] > 0 ? windowsKeyCodeForCharCode([s characterAtIndex:0]) : 0;
3545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (code)
3555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return code;
3565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Ctrl+A on an AZERTY keyboard would get VK_Q keyCode if we relied on -[NSEvent keyCode] below.
3585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        s = [event charactersIgnoringModifiers];
3591e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        code = [s length] > 0 ? windowsKeyCodeForCharCode([s characterAtIndex:0]) : 0;
3605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (code)
3615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return code;
3625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Map Mac virtual key code directly to Windows one for any keys not handled above.
3655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // E.g. the key next to Caps Lock has the same Event.keyCode on U.S. keyboard ('A') and on Russian keyboard (CYRILLIC LETTER EF).
3661e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    return windowsKeyCodeForKeyCode([event keyCode]);
3675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static inline NSString* textFromEvent(NSEvent* event)
3705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if ([event type] == NSFlagsChanged)
3725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"";
3735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return [event characters];
3745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static inline NSString* unmodifiedTextFromEvent(NSEvent* event)
3775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if ([event type] == NSFlagsChanged)
3795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"";
3805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return [event charactersIgnoringModifiers];
3815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static NSString* keyIdentifierForKeyEvent(NSEvent* event)
3845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if ([event type] == NSFlagsChanged) {
3865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        switch ([event keyCode]) {
3875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case 54: // Right Command
3885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case 55: // Left Command
3895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return @"Meta";
3905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case 57: // Capslock
3925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return @"CapsLock";
3935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case 56: // Left Shift
3955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case 60: // Right Shift
3965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return @"Shift";
3975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case 58: // Left Alt
3995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case 61: // Right Alt
4005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return @"Alt";
4015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case 59: // Left Ctrl
4035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case 62: // Right Ctrl
4045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return @"Control";
4055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Begin non-Apple addition/modification --------------------------------------
4075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case 63: // Function
4085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return @"Function";
4095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        default: // Unknown, but this may be a strange/new keyboard.
4115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return @"Unidentified";
4125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// End non-Apple addition/modification ----------------------------------------
4135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
4145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    NSString* s = [event charactersIgnoringModifiers];
4175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if ([s length] != 1)
4185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"Unidentified";
4195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unichar c = [s characterAtIndex:0];
4215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    switch (c) {
4225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Each identifier listed in the DOM spec is listed here.
4235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Many are simply commented out since they do not appear on standard Macintosh keyboards
4245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // or are on a key that doesn't have a corresponding character.
4255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "Accept"
4275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "AllCandidates"
4285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "Alt"
4305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSMenuFunctionKey:
4315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"Alt";
4325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "Apps"
4345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "BrowserBack"
4355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "BrowserForward"
4365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "BrowserHome"
4375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "BrowserRefresh"
4385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "BrowserSearch"
4395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "BrowserStop"
4405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "CapsLock"
4415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "Clear"
4435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSClearLineFunctionKey:
4445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"Clear";
4455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "CodeInput"
4475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "Compose"
4485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "Control"
4495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "Crsel"
4505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "Convert"
4515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "Copy"
4525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "Cut"
4535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "Down"
4555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSDownArrowFunctionKey:
4565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"Down";
4575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "End"
4585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSEndFunctionKey:
4595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"End";
4605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "Enter"
4615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case 0x3: case 0xA: case 0xD: // Macintosh calls the one on the main keyboard Return, but Windows calls it Enter, so we'll do the same for the DOM
4625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"Enter";
4635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "EraseEof"
4655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "Execute"
4675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSExecuteFunctionKey:
4685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"Execute";
4695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "Exsel"
4715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "F1"
4735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSF1FunctionKey:
4745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"F1";
4755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "F2"
4765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSF2FunctionKey:
4775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"F2";
4785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "F3"
4795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSF3FunctionKey:
4805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"F3";
4815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "F4"
4825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSF4FunctionKey:
4835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"F4";
4845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "F5"
4855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSF5FunctionKey:
4865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"F5";
4875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "F6"
4885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSF6FunctionKey:
4895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"F6";
4905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "F7"
4915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSF7FunctionKey:
4925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"F7";
4935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "F8"
4945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSF8FunctionKey:
4955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"F8";
4965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "F9"
4975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSF9FunctionKey:
4985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"F9";
4995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "F10"
5005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSF10FunctionKey:
5015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"F10";
5025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "F11"
5035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSF11FunctionKey:
5045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"F11";
5055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "F12"
5065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSF12FunctionKey:
5075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"F12";
5085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "F13"
5095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSF13FunctionKey:
5105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"F13";
5115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "F14"
5125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSF14FunctionKey:
5135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"F14";
5145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "F15"
5155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSF15FunctionKey:
5165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"F15";
5175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "F16"
5185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSF16FunctionKey:
5195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"F16";
5205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "F17"
5215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSF17FunctionKey:
5225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"F17";
5235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "F18"
5245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSF18FunctionKey:
5255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"F18";
5265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "F19"
5275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSF19FunctionKey:
5285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"F19";
5295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "F20"
5305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSF20FunctionKey:
5315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"F20";
5325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "F21"
5335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSF21FunctionKey:
5345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"F21";
5355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "F22"
5365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSF22FunctionKey:
5375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"F22";
5385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "F23"
5395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSF23FunctionKey:
5405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"F23";
5415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "F24"
5425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSF24FunctionKey:
5435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"F24";
5445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "FinalMode"
5465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "Find"
5485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSFindFunctionKey:
5495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"Find";
5505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "FullWidth"
5525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "HalfWidth"
5535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "HangulMode"
5545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "HanjaMode"
5555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "Help"
5575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSHelpFunctionKey:
5585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"Help";
5595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "Hiragana"
5615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "Home"
5635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSHomeFunctionKey:
5645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"Home";
5655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "Insert"
5665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSInsertFunctionKey:
5675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"Insert";
5685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "JapaneseHiragana"
5705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "JapaneseKatakana"
5715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "JapaneseRomaji"
5725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "JunjaMode"
5735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "KanaMode"
5745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "KanjiMode"
5755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "Katakana"
5765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "LaunchApplication1"
5775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "LaunchApplication2"
5785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "LaunchMail"
5795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "Left"
5815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSLeftArrowFunctionKey:
5825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"Left";
5835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "Meta"
5855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "MediaNextTrack"
5865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "MediaPlayPause"
5875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "MediaPreviousTrack"
5885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "MediaStop"
5895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "ModeChange"
5915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSModeSwitchFunctionKey:
5925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"ModeChange";
5935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "Nonconvert"
5955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "NumLock"
5965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "PageDown"
5985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSPageDownFunctionKey:
5995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"PageDown";
6005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "PageUp"
6015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSPageUpFunctionKey:
6025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"PageUp";
6035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "Paste"
6055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "Pause"
6075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSPauseFunctionKey:
6085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"Pause";
6095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "Play"
6115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "PreviousCandidate"
6125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "PrintScreen"
6145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSPrintScreenFunctionKey:
6155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"PrintScreen";
6165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "Process"
6185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "Props"
6195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "Right"
6215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSRightArrowFunctionKey:
6225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"Right";
6235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "RomanCharacters"
6255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "Scroll"
6275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSScrollLockFunctionKey:
6285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"Scroll";
6295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "Select"
6305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSSelectFunctionKey:
6315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"Select";
6325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "SelectMedia"
6345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "Shift"
6355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "Stop"
6375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSStopFunctionKey:
6385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"Stop";
6395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "Up"
6405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSUpArrowFunctionKey:
6415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"Up";
6425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "Undo"
6435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSUndoFunctionKey:
6445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"Undo";
6455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "VolumeDown"
6475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "VolumeMute"
6485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "VolumeUp"
6495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "Win"
6505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "Zoom"
6515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // More function keys, not in the key identifier specification.
6535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSF25FunctionKey:
6545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"F25";
6555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSF26FunctionKey:
6565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"F26";
6575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSF27FunctionKey:
6585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"F27";
6595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSF28FunctionKey:
6605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"F28";
6615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSF29FunctionKey:
6625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"F29";
6635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSF30FunctionKey:
6645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"F30";
6655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSF31FunctionKey:
6665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"F31";
6675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSF32FunctionKey:
6685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"F32";
6695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSF33FunctionKey:
6705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"F33";
6715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSF34FunctionKey:
6725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"F34";
6735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSF35FunctionKey:
6745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"F35";
6755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Turn 0x7F into 0x08, because backspace needs to always be 0x08.
6775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case 0x7F:
6785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"U+0008";
6795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Standard says that DEL becomes U+007F.
6805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSDeleteFunctionKey:
6815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"U+007F";
6825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Always use 0x09 for tab instead of AppKit's backtab character.
6845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSBackTabCharacter:
6855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return @"U+0009";
6865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSBeginFunctionKey:
6885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSBreakFunctionKey:
6895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSClearDisplayFunctionKey:
6905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSDeleteCharFunctionKey:
6915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSDeleteLineFunctionKey:
6925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSInsertCharFunctionKey:
6935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSInsertLineFunctionKey:
6945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSNextFunctionKey:
6955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSPrevFunctionKey:
6965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSPrintFunctionKey:
6975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSRedoFunctionKey:
6985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSResetFunctionKey:
6995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSSysReqFunctionKey:
7005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSSystemFunctionKey:
7015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSUserFunctionKey:
7025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // FIXME: We should use something other than the vendor-area Unicode values for the above keys.
7035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // For now, just fall through to the default.
7045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    default:
7055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return [NSString stringWithFormat:@"U+%04X", WTF::toASCIIUpper(c)];
7065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
7075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
7085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// End Apple code.
7105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// ----------------------------------------------------------------------------
7115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static inline int modifiersFromEvent(NSEvent* event) {
7135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int modifiers = 0;
7145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if ([event modifierFlags] & NSControlKeyMask)
7165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        modifiers |= WebInputEvent::ControlKey;
7175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if ([event modifierFlags] & NSShiftKeyMask)
7185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        modifiers |= WebInputEvent::ShiftKey;
7195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if ([event modifierFlags] & NSAlternateKeyMask)
7205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        modifiers |= WebInputEvent::AltKey;
7215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if ([event modifierFlags] & NSCommandKeyMask)
7225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        modifiers |= WebInputEvent::MetaKey;
7235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if ([event modifierFlags] & NSAlphaShiftKeyMask)
7245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        modifiers |= WebInputEvent::CapsLockOn;
7255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // TODO(port): Set mouse button states
7265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return modifiers;
7285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
7295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static inline void setWebEventLocationFromEventInView(WebMouseEvent* result,
7315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                                      NSEvent* event,
7325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                                      NSView* view) {
7335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    NSPoint windowLocal = [event locationInWindow];
7345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    NSPoint screenLocal = [[view window] convertBaseToScreen:windowLocal];
7365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    result->globalX = screenLocal.x;
7375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Flip y.
7385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    NSScreen* primaryScreen = ([[NSScreen screens] count] > 0) ?
7395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        [[NSScreen screens] objectAtIndex:0] : nil;
7405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (primaryScreen)
7415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result->globalY = [primaryScreen frame].size.height - screenLocal.y;
7425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else
7435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result->globalY = screenLocal.y;
7445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    NSPoint contentLocal = [view convertPoint:windowLocal fromView:nil];
7465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    result->x = contentLocal.x;
7475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    result->y = [view frame].size.height - contentLocal.y;  // Flip y.
7485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    result->windowX = result->x;
7505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    result->windowY = result->y;
7515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    result->movementX = [event deltaX];
7535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    result->movementY = [event deltaY];
7545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
7555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
75651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)bool WebInputEventFactory::isSystemKeyEvent(const WebKeyboardEvent& event)
75751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles){
75851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    // Windows and Linux set |isSystemKey| if alt is down. Blink looks at this
75951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    // flag to decide if it should handle a key or not. E.g. alt-left/right
76051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    // shouldn't be used by Blink to scroll the current page, because we want
76151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    // to get that key back for it to do history navigation. Hence, the
76251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    // corresponding situation on OS X is to set this for cmd key presses.
76351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    // cmd-b and and cmd-i are system wide key bindings that OS X doesn't
76451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    // handle for us, so the editor handles them.
76551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    return event.modifiers & WebInputEvent::MetaKey
76651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)           && event.windowsKeyCode != VK_B
76751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)           && event.windowsKeyCode != VK_I;
76851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)}
76951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
7705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)WebKeyboardEvent WebInputEventFactory::keyboardEvent(NSEvent* event)
7715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
7725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    WebKeyboardEvent result;
7735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    result.type =
7755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        isKeyUpEvent(event) ? WebInputEvent::KeyUp : WebInputEvent::RawKeyDown;
7765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    result.modifiers = modifiersFromEvent(event);
7785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (isKeypadEvent(event))
7805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result.modifiers |= WebInputEvent::IsKeyPad;
7815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (([event type] != NSFlagsChanged) && [event isARepeat])
7835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result.modifiers |= WebInputEvent::IsAutoRepeat;
7845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int windowsKeyCode = windowsKeyCodeForKeyEvent(event);
7865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    result.windowsKeyCode = WebKeyboardEvent::windowsKeyCodeWithoutLocation(windowsKeyCode);
7875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    result.modifiers |= WebKeyboardEvent::locationModifiersFromWindowsKeyCode(windowsKeyCode);
7885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    result.nativeKeyCode = [event keyCode];
7895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    NSString* textStr = textFromEvent(event);
7915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    NSString* unmodifiedStr = unmodifiedTextFromEvent(event);
7925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    NSString* identifierStr = keyIdentifierForKeyEvent(event);
7935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Begin Apple code, copied from KeyEventMac.mm
7955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Always use 13 for Enter/Return -- we don't want to use AppKit's
7975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // different character for Enter.
7985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (result.windowsKeyCode == '\r') {
7995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        textStr = @"\r";
8005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        unmodifiedStr = @"\r";
8015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
8025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // The adjustments below are only needed in backward compatibility mode,
8045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // but we cannot tell what mode we are in from here.
8055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Turn 0x7F into 8, because backspace needs to always be 8.
8075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if ([textStr isEqualToString:@"\x7F"])
8085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        textStr = @"\x8";
8095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if ([unmodifiedStr isEqualToString:@"\x7F"])
8105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        unmodifiedStr = @"\x8";
8115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Always use 9 for tab -- we don't want to use AppKit's different character
8125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // for shift-tab.
8135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (result.windowsKeyCode == 9) {
8145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        textStr = @"\x9";
8155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        unmodifiedStr = @"\x9";
8165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
8175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // End Apple code.
8195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if ([textStr length] < WebKeyboardEvent::textLengthCap &&
8215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        [unmodifiedStr length] < WebKeyboardEvent::textLengthCap) {
8225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        [textStr getCharacters:&result.text[0]];
8235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        [unmodifiedStr getCharacters:&result.unmodifiedText[0]];
8245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else
8255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT_NOT_REACHED();
8265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    [identifierStr getCString:&result.keyIdentifier[0]
8285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    maxLength:sizeof(result.keyIdentifier)
8295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                     encoding:NSASCIIStringEncoding];
8305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    result.timeStampSeconds = [event timestamp];
83251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    result.isSystemKey = isSystemKeyEvent(result);
8335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return result;
8355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
8365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)WebKeyboardEvent WebInputEventFactory::keyboardEvent(wchar_t character,
8385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                                     int modifiers,
8395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                                     double timeStampSeconds)
8405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
8415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // keyboardEvent(NSEvent*) depends on the NSEvent object and
8425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // it is hard to use it from methods of the NSTextInput protocol. For
8435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // such methods, this function creates a WebInputEvent::Char event without
8445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // using a NSEvent object.
8455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    WebKeyboardEvent result;
84651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    result.type = blink::WebInputEvent::Char;
8475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    result.timeStampSeconds = timeStampSeconds;
8485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    result.modifiers = modifiers;
8495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    result.windowsKeyCode = character;
8505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    result.nativeKeyCode = character;
8515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    result.text[0] = character;
8525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    result.unmodifiedText[0] = character;
85351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    result.isSystemKey = isSystemKeyEvent(result);
8545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return result;
8565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
8575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// WebMouseEvent --------------------------------------------------------------
8595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)WebMouseEvent WebInputEventFactory::mouseEvent(NSEvent* event, NSView* view)
8615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
8625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    WebMouseEvent result;
8635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    result.clickCount = 0;
8655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    switch ([event type]) {
8675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSMouseExited:
8685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result.type = WebInputEvent::MouseLeave;
8695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result.button = WebMouseEvent::ButtonNone;
8705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        break;
8715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSLeftMouseDown:
8725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result.type = WebInputEvent::MouseDown;
8735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result.clickCount = [event clickCount];
8745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result.button = WebMouseEvent::ButtonLeft;
8755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        break;
8765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSOtherMouseDown:
8775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result.type = WebInputEvent::MouseDown;
8785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result.clickCount = [event clickCount];
8795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result.button = WebMouseEvent::ButtonMiddle;
8805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        break;
8815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSRightMouseDown:
8825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result.type = WebInputEvent::MouseDown;
8835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result.clickCount = [event clickCount];
8845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result.button = WebMouseEvent::ButtonRight;
8855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        break;
8865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSLeftMouseUp:
8875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result.type = WebInputEvent::MouseUp;
8885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result.clickCount = [event clickCount];
8895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result.button = WebMouseEvent::ButtonLeft;
8905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        break;
8915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSOtherMouseUp:
8925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result.type = WebInputEvent::MouseUp;
8935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result.clickCount = [event clickCount];
8945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result.button = WebMouseEvent::ButtonMiddle;
8955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        break;
8965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSRightMouseUp:
8975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result.type = WebInputEvent::MouseUp;
8985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result.clickCount = [event clickCount];
8995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result.button = WebMouseEvent::ButtonRight;
9005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        break;
9015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSMouseMoved:
9025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSMouseEntered:
9035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result.type = WebInputEvent::MouseMove;
9045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        break;
9055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSLeftMouseDragged:
9065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result.type = WebInputEvent::MouseMove;
9075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result.button = WebMouseEvent::ButtonLeft;
9085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        break;
9095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSOtherMouseDragged:
9105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result.type = WebInputEvent::MouseMove;
9115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result.button = WebMouseEvent::ButtonMiddle;
9125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        break;
9135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NSRightMouseDragged:
9145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result.type = WebInputEvent::MouseMove;
9155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result.button = WebMouseEvent::ButtonRight;
9165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        break;
9175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    default:
9185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT_NOT_REACHED();
9195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
9205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    setWebEventLocationFromEventInView(&result, event, view);
9225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    result.modifiers = modifiersFromEvent(event);
9245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    result.timeStampSeconds = [event timestamp];
9265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return result;
9285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
9295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// WebMouseWheelEvent ---------------------------------------------------------
9315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static WebMouseWheelEvent::Phase phaseForNSEventPhase(NSEventPhase eventPhase)
9335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
9345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    uint32_t phase = WebMouseWheelEvent::PhaseNone;
9355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (eventPhase & NSEventPhaseBegan)
9365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        phase |= WebMouseWheelEvent::PhaseBegan;
9375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (eventPhase & NSEventPhaseStationary)
9385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        phase |= WebMouseWheelEvent::PhaseStationary;
9395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (eventPhase & NSEventPhaseChanged)
9405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        phase |= WebMouseWheelEvent::PhaseChanged;
9415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (eventPhase & NSEventPhaseEnded)
9425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        phase |= WebMouseWheelEvent::PhaseEnded;
9435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (eventPhase & NSEventPhaseCancelled)
9445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        phase |= WebMouseWheelEvent::PhaseCancelled;
9455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (eventPhase & NSEventPhaseMayBegin)
9465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        phase |= WebMouseWheelEvent::PhaseMayBegin;
9475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return static_cast<WebMouseWheelEvent::Phase>(phase);
9485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
9495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static WebMouseWheelEvent::Phase phaseForEvent(NSEvent *event)
9515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
9525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (![event respondsToSelector:@selector(phase)])
9535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return WebMouseWheelEvent::PhaseNone;
9545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    NSEventPhase eventPhase = [event phase];
9565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return phaseForNSEventPhase(eventPhase);
9575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
9585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static WebMouseWheelEvent::Phase momentumPhaseForEvent(NSEvent *event)
9605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
9615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (![event respondsToSelector:@selector(momentumPhase)])
9625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return WebMouseWheelEvent::PhaseNone;
9635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    NSEventPhase eventMomentumPhase = [event momentumPhase];
9655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return phaseForNSEventPhase(eventMomentumPhase);
9665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
9675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
96807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben MurdochWebMouseWheelEvent WebInputEventFactory::mouseWheelEvent(NSEvent* event, NSView* view, bool canRubberbandLeft, bool canRubberbandRight)
96907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch{
9705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    WebMouseWheelEvent result;
9715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    result.type = WebInputEvent::MouseWheel;
9735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    result.button = WebMouseEvent::ButtonNone;
9745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    result.modifiers = modifiersFromEvent(event);
9765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    setWebEventLocationFromEventInView(&result, event, view);
9785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
97907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    result.canRubberbandLeft = canRubberbandLeft;
98007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    result.canRubberbandRight = canRubberbandRight;
98107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
9825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Of Mice and Men
9835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // ---------------
9845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //
9855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // There are three types of scroll data available on a scroll wheel CGEvent.
9865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Apple's documentation ([1]) is rather vague in their differences, and not
9875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // terribly helpful in deciding which to use. This is what's really going on.
9885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //
9895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // First, these events behave very differently depending on whether a standard
9905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // wheel mouse is used (one that scrolls in discrete units) or a
9915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // trackpad/Mighty Mouse is used (which both provide continuous scrolling).
9925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // You must check to see which was used for the event by testing the
9935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // kCGScrollWheelEventIsContinuous field.
9945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //
9955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Second, these events refer to "axes". Axis 1 is the y-axis, and axis 2 is
9965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // the x-axis.
9975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //
9985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Third, there is a concept of mouse acceleration. Scrolling the same amount
9995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // of physical distance will give you different results logically depending on
10005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // whether you scrolled a little at a time or in one continuous motion. Some
10015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // fields account for this while others do not.
10025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //
10035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Fourth, for trackpads there is a concept of chunkiness. When scrolling
10045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // continuously, events can be delivered in chunks. That is to say, lots of
10055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // scroll events with delta 0 will be delivered, and every so often an event
10065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // with a non-zero delta will be delivered, containing the accumulated deltas
10075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // from all the intermediate moves. [2]
10085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //
10095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // For notchy wheel mice (kCGScrollWheelEventIsContinuous == 0)
10105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // ------------------------------------------------------------
10115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //
10125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // kCGScrollWheelEventDeltaAxis*
10135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //   This is the rawest of raw events. For each mouse notch you get a value of
10145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //   +1/-1. This does not take acceleration into account and thus is less
10155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //   useful for building UIs.
10165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //
10175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // kCGScrollWheelEventPointDeltaAxis*
10185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //   This is smarter. In general, for each mouse notch you get a value of
10195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //   +1/-1, but this _does_ take acceleration into account, so you will get
10205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //   larger values on longer scrolls. This field would be ideal for building
10215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //   UIs except for one nasty bug: when the shift key is pressed, this set of
10225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //   fields fails to move the value into the axis2 field (the other two types
10235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //   of data do). This wouldn't be so bad except for the fact that while the
10245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //   number of axes is used in the creation of a CGScrollWheelEvent, there is
10255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //   no way to get that information out of the event once created.
10265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //
10275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // kCGScrollWheelEventFixedPtDeltaAxis*
10285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //   This is a fixed value, and for each mouse notch you get a value of
10295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //   +0.1/-0.1 (but, like above, scaled appropriately for acceleration). This
10305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //   value takes acceleration into account, and in fact is identical to the
10315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //   results you get from -[NSEvent delta*]. (That is, if you linked on Tiger
10325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //   or greater; see [2] for details.)
10335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //
10345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // A note about continuous devices
10355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // -------------------------------
10365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //
10375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // There are two devices that provide continuous scrolling events (trackpads
10385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // and Mighty Mouses) and they behave rather differently. The Mighty Mouse
10395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // behaves a lot like a regular mouse. There is no chunking, and the
10405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // FixedPtDelta values are the PointDelta values multiplied by 0.1. With the
10415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // trackpad, though, there is chunking. While the FixedPtDelta values are
10425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // reasonable (they occur about every fifth event but have values five times
10435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // larger than usual) the Delta values are unreasonable. They don't appear to
10445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // accumulate properly.
10455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //
10465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // For continuous devices (kCGScrollWheelEventIsContinuous != 0)
10475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // -------------------------------------------------------------
10485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //
10495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // kCGScrollWheelEventDeltaAxis*
10505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //   This provides values with no acceleration. With a trackpad, these values
10515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //   are chunked but each non-zero value does not appear to be cumulative.
10525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //   This seems to be a bug.
10535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //
10545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // kCGScrollWheelEventPointDeltaAxis*
10555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //   This provides values with acceleration. With a trackpad, these values are
10565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //   not chunked and are highly accurate.
10575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //
10585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // kCGScrollWheelEventFixedPtDeltaAxis*
10595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //   This provides values with acceleration. With a trackpad, these values are
10605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //   chunked but unlike Delta events are properly cumulative.
10615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //
10625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Summary
10635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // -------
10645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //
10655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // In general the best approach to take is: determine if the event is
10665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // continuous. If it is not, then use the FixedPtDelta events (or just stick
10675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // with Cocoa events). They provide both acceleration and proper horizontal
10685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // scrolling. If the event is continuous, then doing pixel scrolling with the
10695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // PointDelta is the way to go. In general, avoid the Delta events. They're
10705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // the oldest (dating back to 10.4, before CGEvents were public) but they lack
10715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // acceleration and precision, making them useful only in specific edge cases.
10725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //
10735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // References
10745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // ----------
10755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //
10765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // [1] <http://developer.apple.com/documentation/Carbon/Reference/QuartzEventServicesRef/Reference/reference.html>
10775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // [2] <http://developer.apple.com/releasenotes/Cocoa/AppKitOlderNotes.html>
10785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //     Scroll to the section headed "NSScrollWheel events".
10795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //
10805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // P.S. The "smooth scrolling" option in the system preferences is utterly
10815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // unrelated to any of this.
10825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    CGEventRef cgEvent = [event CGEvent];
10845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(cgEvent);
10855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Wheel ticks are supposed to be raw, unaccelerated values, one per physical
10875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // mouse wheel notch. The delta event is perfect for this (being a good
10885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "specific edge case" as mentioned above). Trackpads, unfortunately, do
10895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // event chunking, and sending mousewheel events with 0 ticks causes some
10905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // websites to malfunction. Therefore, for all continuous input devices we use
10915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // the point delta data instead, since we cannot distinguish trackpad data
10925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // from data from any other continuous device.
10935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Conversion between wheel delta amounts and number of pixels to scroll.
10955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    static const double scrollbarPixelsPerCocoaTick = 40.0;
10965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEventIsContinuous)) {
10985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result.deltaX = CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEventPointDeltaAxis2);
10995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result.deltaY = CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEventPointDeltaAxis1);
11005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result.wheelTicksX = result.deltaX / scrollbarPixelsPerCocoaTick;
11015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result.wheelTicksY = result.deltaY / scrollbarPixelsPerCocoaTick;
11025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result.hasPreciseScrollingDeltas = true;
11035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else {
11045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result.deltaX = [event deltaX] * scrollbarPixelsPerCocoaTick;
11055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result.deltaY = [event deltaY] * scrollbarPixelsPerCocoaTick;
11065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result.wheelTicksY = CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEventDeltaAxis1);
11075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result.wheelTicksX = CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEventDeltaAxis2);
11085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
11095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    result.timeStampSeconds = [event timestamp];
11115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    result.phase              = phaseForEvent(event);
11135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    result.momentumPhase      = momentumPhaseForEvent(event);
11145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return result;
11165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
11175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)WebGestureEvent WebInputEventFactory::gestureEvent(NSEvent *event, NSView *view)
11195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
11205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    WebGestureEvent result;
11215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Use a temporary WebMouseEvent to get the location.
11235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    WebMouseEvent temp;
11245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    setWebEventLocationFromEventInView(&temp, event, view);
11265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    result.x = temp.x;
11275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    result.y = temp.y;
11285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    result.globalX = temp.globalX;
11295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    result.globalY = temp.globalY;
11305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    result.modifiers = modifiersFromEvent(event);
11325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    result.timeStampSeconds = [event timestamp];
11335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1134d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // MacOS X gestures are used only for pinch support.
1135f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    result.sourceDevice = WebGestureDeviceTouchpad;
1136d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    switch ([event type]) {
1137d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    case NSEventTypeMagnify:
1138d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        result.type = WebInputEvent::GesturePinchUpdate;
1139f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        result.data.pinchUpdate.scale = [event magnification] + 1.0;
1140d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        break;
1141d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    default:
1142d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        ASSERT_NOT_REACHED();
1143d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        result.type = WebInputEvent::Undefined;
1144d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    }
1145d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
11465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return result;
11475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
11485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
114951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)} // namespace blink
1150