1643ca7872b450ea4efacab6188849e5aac2ba161Steve Block/*
2643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * Copyright (C) 2004, 2006, 2007 Apple Inc. All rights reserved.
3643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * Copyright (C) 2006-2009 Google Inc.
4643ca7872b450ea4efacab6188849e5aac2ba161Steve Block *
5643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * Redistribution and use in source and binary forms, with or without
6643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * modification, are permitted provided that the following conditions
7643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * are met:
8643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * 1. Redistributions of source code must retain the above copyright
9643ca7872b450ea4efacab6188849e5aac2ba161Steve Block *    notice, this list of conditions and the following disclaimer.
10643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * 2. Redistributions in binary form must reproduce the above copyright
11643ca7872b450ea4efacab6188849e5aac2ba161Steve Block *    notice, this list of conditions and the following disclaimer in the
12643ca7872b450ea4efacab6188849e5aac2ba161Steve Block *    documentation and/or other materials provided with the distribution.
13643ca7872b450ea4efacab6188849e5aac2ba161Steve Block *
14643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25643ca7872b450ea4efacab6188849e5aac2ba161Steve Block */
26643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
27643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#include "config.h"
28643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#include "WebInputEventFactory.h"
29643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
30643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#include <ApplicationServices/ApplicationServices.h>
31643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#import <Cocoa/Cocoa.h>
32643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
33643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#include "WebInputEvent.h"
34643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#include <wtf/ASCIICType.h>
35643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
36643ca7872b450ea4efacab6188849e5aac2ba161Steve Blocknamespace WebKit {
37643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
38643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// WebKeyboardEvent -----------------------------------------------------------
39643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
40643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// ----------------------------------------------------------------------------
41643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// Begin Apple code, copied from KeyEventMac.mm
42643ca7872b450ea4efacab6188849e5aac2ba161Steve Block//
43643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// We can share some of this code if we factored it out of KeyEventMac, but
44643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// the main problem is that it relies on the NSString ctor on String for
45643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// conversions, and since we're building without PLATFORM(MAC), we don't have
46643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// that. As a result we have to use NSString here exclusively and thus tweak
47643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// the code so it's not re-usable as-is. One possiblity would be to make the
48643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// upstream code only use NSString, but I'm not certain how far that change
49643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// would propagate.
50643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
51643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockstatic inline bool isKeyUpEvent(NSEvent* event)
52643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{
53643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if ([event type] != NSFlagsChanged)
54643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return [event type] == NSKeyUp;
55643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // FIXME: This logic fails if the user presses both Shift keys at once, for example:
56643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // we treat releasing one of them as keyDown.
57643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    switch ([event keyCode]) {
58643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 54: // Right Command
59643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 55: // Left Command
60643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return ([event modifierFlags] & NSCommandKeyMask) == 0;
61643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
62643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 57: // Capslock
63643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return ([event modifierFlags] & NSAlphaShiftKeyMask) == 0;
64643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
65643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 56: // Left Shift
66643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 60: // Right Shift
67643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return ([event modifierFlags] & NSShiftKeyMask) == 0;
68643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
69643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 58: // Left Alt
70643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 61: // Right Alt
71643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return ([event modifierFlags] & NSAlternateKeyMask) == 0;
72643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
73643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 59: // Left Ctrl
74643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 62: // Right Ctrl
75643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return ([event modifierFlags] & NSControlKeyMask) == 0;
76643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
77643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 63: // Function
78643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return ([event modifierFlags] & NSFunctionKeyMask) == 0;
79643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    }
80643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    return false;
81643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}
82643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
83643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockstatic bool isKeypadEvent(NSEvent* event)
84643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{
85643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // Check that this is the type of event that has a keyCode.
86643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    switch ([event type]) {
87643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSKeyDown:
88643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSKeyUp:
89643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSFlagsChanged:
90643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        break;
91643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    default:
92643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return false;
93643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    }
94643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
95d0825bca7fe65beaee391d30da42e937db621564Steve Block    if ([event modifierFlags] & NSNumericPadKeyMask)
96d0825bca7fe65beaee391d30da42e937db621564Steve Block        return true;
97d0825bca7fe65beaee391d30da42e937db621564Steve Block
98643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    switch ([event keyCode]) {
99643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 71: // Clear
100643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 81: // =
101643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 75: // /
102643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 67: // *
103643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 78: // -
104643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 69: // +
105643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 76: // Enter
106643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 65: // .
107643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 82: // 0
108643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 83: // 1
109643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 84: // 2
110643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 85: // 3
111643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 86: // 4
112643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 87: // 5
113643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 88: // 6
114643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 89: // 7
115643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 91: // 8
116643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 92: // 9
117643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return true;
118643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    }
119643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
120643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    return false;
121643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}
122643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
123643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockstatic int windowsKeyCodeForKeyEvent(NSEvent* event)
124643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{
125643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    switch ([event keyCode]) {
126643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_TAB (09) TAB key
127643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 48:
128643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return 0x09;
129643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
130643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_APPS (5D) Right windows/meta key
131643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 54: // Right Command
132643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return 0x5D;
133643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
134643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_LWIN (5B) Left windows/meta key
135643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 55: // Left Command
136643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return 0x5B;
137643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
138643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_CAPITAL (14) caps locks key
139643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 57: // Capslock
140643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return 0x14;
141643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
142643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_SHIFT (10) either shift key
143643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 56: // Left Shift
144643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 60: // Right Shift
145643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return 0x10;
146643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
147643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_MENU (12) either alt key
148643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 58: // Left Alt
149643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 61: // Right Alt
150643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return 0x12;
151643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
152643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_CONTROL (11) either ctrl key
153643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 59: // Left Ctrl
154643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 62: // Right Ctrl
155643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return 0x11;
156643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
157643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// Begin non-Apple addition ---------------------------------------------------
158643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 63: // Function (no Windows key code)
159643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return 0;
160643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// End non-Apple addition -----------------------------------------------------
161643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
162643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_CLEAR (0C) CLEAR key
163643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 71: return 0x0C;
164643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
165643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_NUMPAD0 (60) Numeric keypad 0 key
166643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 82: return 0x60;
167643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_NUMPAD1 (61) Numeric keypad 1 key
168643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 83: return 0x61;
169643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_NUMPAD2 (62) Numeric keypad 2 key
170643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 84: return 0x62;
171643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_NUMPAD3 (63) Numeric keypad 3 key
172643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 85: return 0x63;
173643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_NUMPAD4 (64) Numeric keypad 4 key
174643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 86: return 0x64;
175643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_NUMPAD5 (65) Numeric keypad 5 key
176643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 87: return 0x65;
177643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_NUMPAD6 (66) Numeric keypad 6 key
178643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 88: return 0x66;
179643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_NUMPAD7 (67) Numeric keypad 7 key
180643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 89: return 0x67;
181643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_NUMPAD8 (68) Numeric keypad 8 key
182643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 91: return 0x68;
183643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_NUMPAD9 (69) Numeric keypad 9 key
184643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 92: return 0x69;
185643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_MULTIPLY (6A) Multiply key
186643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 67: return 0x6A;
187643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_ADD (6B) Add key
188643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 69: return 0x6B;
189643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
190643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_SUBTRACT (6D) Subtract key
191643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 78: return 0x6D;
192643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_DECIMAL (6E) Decimal key
193643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 65: return 0x6E;
194643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_DIVIDE (6F) Divide key
195643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 75: return 0x6F;
196643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    }
197643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
198643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// Begin non-Apple addition ---------------------------------------------------
199643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // |-[NSEvent charactersIgnoringModifiers]| isn't allowed for
200643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // NSFlagsChanged, and conceivably we may not have caught everything
201643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // which causes an NSFlagsChanged above.
202643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if ([event type] == NSFlagsChanged)
203643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return 0;
204643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// End non-Apple addition -----------------------------------------------------
205643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
206643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    NSString* s = [event charactersIgnoringModifiers];
207643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if ([s length] != 1)
208643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return 0;
209643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
210643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    switch ([s characterAtIndex:0]) {
211643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_LBUTTON (01) Left mouse button
212643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_RBUTTON (02) Right mouse button
213643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_CANCEL (03) Control-break processing
214643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_MBUTTON (04) Middle mouse button (three-button mouse)
215643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_XBUTTON1 (05)
216643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_XBUTTON2 (06)
217643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
218643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_BACK (08) BACKSPACE key
219643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 8: case 0x7F: return 0x08;
220643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_TAB (09) TAB key
221643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 9: return 0x09;
222643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
223643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_CLEAR (0C) CLEAR key
224643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // handled by key code above
225643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
226643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_RETURN (0D)
227643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 0xD: case 3: return 0x0D;
228643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
229643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_SHIFT (10) SHIFT key
230643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_CONTROL (11) CTRL key
231643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_MENU (12) ALT key
232643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
233643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_PAUSE (13) PAUSE key
234643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSPauseFunctionKey: return 0x13;
235643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
236643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_CAPITAL (14) CAPS LOCK key
237643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_KANA (15) Input Method Editor (IME) Kana mode
238643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_HANGUEL (15) IME Hanguel mode (maintained for compatibility; use VK_HANGUL)
239643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_HANGUL (15) IME Hangul mode
240643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_JUNJA (17) IME Junja mode
241643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_FINAL (18) IME final mode
242643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_HANJA (19) IME Hanja mode
243643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_KANJI (19) IME Kanji mode
244643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
245643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_ESCAPE (1B) ESC key
246643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 0x1B: return 0x1B;
247643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
248643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_CONVERT (1C) IME convert
249643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_NONCONVERT (1D) IME nonconvert
250643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_ACCEPT (1E) IME accept
251643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_MODECHANGE (1F) IME mode change request
252643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
253643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_SPACE (20) SPACEBAR
254643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case ' ': return 0x20;
255643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_PRIOR (21) PAGE UP key
256643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSPageUpFunctionKey: return 0x21;
257643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_NEXT (22) PAGE DOWN key
258643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSPageDownFunctionKey: return 0x22;
259643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_END (23) END key
260643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSEndFunctionKey: return 0x23;
261643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_HOME (24) HOME key
262643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSHomeFunctionKey: return 0x24;
263643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_LEFT (25) LEFT ARROW key
264643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSLeftArrowFunctionKey: return 0x25;
265643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_UP (26) UP ARROW key
266643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSUpArrowFunctionKey: return 0x26;
267643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_RIGHT (27) RIGHT ARROW key
268643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSRightArrowFunctionKey: return 0x27;
269643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_DOWN (28) DOWN ARROW key
270643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSDownArrowFunctionKey: return 0x28;
271643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_SELECT (29) SELECT key
272643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSSelectFunctionKey: return 0x29;
273643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_PRINT (2A) PRINT key
274643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSPrintFunctionKey: return 0x2A;
275643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_EXECUTE (2B) EXECUTE key
276643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSExecuteFunctionKey: return 0x2B;
277643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_SNAPSHOT (2C) PRINT SCREEN key
278643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSPrintScreenFunctionKey: return 0x2C;
279643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_INSERT (2D) INS key
280643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSInsertFunctionKey: case NSHelpFunctionKey: return 0x2D;
281643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_DELETE (2E) DEL key
282643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSDeleteFunctionKey: return 0x2E;
283643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
284643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_HELP (2F) HELP key
285643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
286643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //  (30) 0 key
287643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case '0': case ')': return 0x30;
288643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //  (31) 1 key
289643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case '1': case '!': return 0x31;
290643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //  (32) 2 key
291643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case '2': case '@': return 0x32;
292643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //  (33) 3 key
293643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case '3': case '#': return 0x33;
294643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //  (34) 4 key
295643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case '4': case '$': return 0x34;
296643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //  (35) 5 key
297643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case '5': case '%': return 0x35;
298643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //  (36) 6 key
299643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case '6': case '^': return 0x36;
300643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //  (37) 7 key
301643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case '7': case '&': return 0x37;
302643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //  (38) 8 key
303643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case '8': case '*': return 0x38;
304643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //  (39) 9 key
305643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case '9': case '(': return 0x39;
306643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //  (41) A key
307643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 'a': case 'A': return 0x41;
308643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //  (42) B key
309643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 'b': case 'B': return 0x42;
310643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //  (43) C key
311643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 'c': case 'C': return 0x43;
312643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //  (44) D key
313643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 'd': case 'D': return 0x44;
314643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //  (45) E key
315643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 'e': case 'E': return 0x45;
316643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //  (46) F key
317643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 'f': case 'F': return 0x46;
318643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //  (47) G key
319643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 'g': case 'G': return 0x47;
320643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //  (48) H key
321643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 'h': case 'H': return 0x48;
322643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //  (49) I key
323643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 'i': case 'I': return 0x49;
324643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //  (4A) J key
325643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 'j': case 'J': return 0x4A;
326643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //  (4B) K key
327643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 'k': case 'K': return 0x4B;
328643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //  (4C) L key
329643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 'l': case 'L': return 0x4C;
330643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //  (4D) M key
331643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 'm': case 'M': return 0x4D;
332643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //  (4E) N key
333643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 'n': case 'N': return 0x4E;
334643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //  (4F) O key
335643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 'o': case 'O': return 0x4F;
336643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //  (50) P key
337643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 'p': case 'P': return 0x50;
338643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //  (51) Q key
339643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 'q': case 'Q': return 0x51;
340643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //  (52) R key
341643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 'r': case 'R': return 0x52;
342643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //  (53) S key
343643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 's': case 'S': return 0x53;
344643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //  (54) T key
345643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 't': case 'T': return 0x54;
346643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //  (55) U key
347643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 'u': case 'U': return 0x55;
348643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //  (56) V key
349643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 'v': case 'V': return 0x56;
350643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //  (57) W key
351643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 'w': case 'W': return 0x57;
352643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //  (58) X key
353643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 'x': case 'X': return 0x58;
354643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //  (59) Y key
355643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 'y': case 'Y': return 0x59;
356643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //  (5A) Z key
357643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 'z': case 'Z': return 0x5A;
358643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
359643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_LWIN (5B) Left Windows key (Microsoft Natural keyboard)
360643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_RWIN (5C) Right Windows key (Natural keyboard)
361643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_APPS (5D) Applications key (Natural keyboard)
362643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_SLEEP (5F) Computer Sleep key
363643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
364643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_NUMPAD0 (60) Numeric keypad 0 key
365643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_NUMPAD1 (61) Numeric keypad 1 key
366643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_NUMPAD2 (62) Numeric keypad 2 key
367643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_NUMPAD3 (63) Numeric keypad 3 key
368643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_NUMPAD4 (64) Numeric keypad 4 key
369643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_NUMPAD5 (65) Numeric keypad 5 key
370643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_NUMPAD6 (66) Numeric keypad 6 key
371643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_NUMPAD7 (67) Numeric keypad 7 key
372643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_NUMPAD8 (68) Numeric keypad 8 key
373643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_NUMPAD9 (69) Numeric keypad 9 key
374643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_MULTIPLY (6A) Multiply key
375643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_ADD (6B) Add key
376643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // handled by key code above
377643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
378643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_SEPARATOR (6C) Separator key
379643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
380643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_SUBTRACT (6D) Subtract key
381643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_DECIMAL (6E) Decimal key
382643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_DIVIDE (6F) Divide key
383643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // handled by key code above
384643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
385643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_F1 (70) F1 key
386643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF1FunctionKey: return 0x70;
387643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_F2 (71) F2 key
388643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF2FunctionKey: return 0x71;
389643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_F3 (72) F3 key
390643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF3FunctionKey: return 0x72;
391643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_F4 (73) F4 key
392643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF4FunctionKey: return 0x73;
393643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_F5 (74) F5 key
394643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF5FunctionKey: return 0x74;
395643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_F6 (75) F6 key
396643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF6FunctionKey: return 0x75;
397643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_F7 (76) F7 key
398643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF7FunctionKey: return 0x76;
399643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_F8 (77) F8 key
400643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF8FunctionKey: return 0x77;
401643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_F9 (78) F9 key
402643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF9FunctionKey: return 0x78;
403643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_F10 (79) F10 key
404643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF10FunctionKey: return 0x79;
405643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_F11 (7A) F11 key
406643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF11FunctionKey: return 0x7A;
407643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_F12 (7B) F12 key
408643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF12FunctionKey: return 0x7B;
409643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_F13 (7C) F13 key
410643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF13FunctionKey: return 0x7C;
411643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_F14 (7D) F14 key
412643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF14FunctionKey: return 0x7D;
413643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_F15 (7E) F15 key
414643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF15FunctionKey: return 0x7E;
415643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_F16 (7F) F16 key
416643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF16FunctionKey: return 0x7F;
417643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_F17 (80H) F17 key
418643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF17FunctionKey: return 0x80;
419643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_F18 (81H) F18 key
420643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF18FunctionKey: return 0x81;
421643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_F19 (82H) F19 key
422643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF19FunctionKey: return 0x82;
423643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_F20 (83H) F20 key
424643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF20FunctionKey: return 0x83;
425643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_F21 (84H) F21 key
426643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF21FunctionKey: return 0x84;
427643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_F22 (85H) F22 key
428643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF22FunctionKey: return 0x85;
429643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_F23 (86H) F23 key
430643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF23FunctionKey: return 0x86;
431643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_F24 (87H) F24 key
432643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF24FunctionKey: return 0x87;
433643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
434643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_NUMLOCK (90) NUM LOCK key
435643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
436643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_SCROLL (91) SCROLL LOCK key
437643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSScrollLockFunctionKey: return 0x91;
438643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
439643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_LSHIFT (A0) Left SHIFT key
440643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_RSHIFT (A1) Right SHIFT key
441643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_LCONTROL (A2) Left CONTROL key
442643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_RCONTROL (A3) Right CONTROL key
443643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_LMENU (A4) Left MENU key
444643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_RMENU (A5) Right MENU key
445643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_BROWSER_BACK (A6) Windows 2000/XP: Browser Back key
446643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_BROWSER_FORWARD (A7) Windows 2000/XP: Browser Forward key
447643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_BROWSER_REFRESH (A8) Windows 2000/XP: Browser Refresh key
448643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_BROWSER_STOP (A9) Windows 2000/XP: Browser Stop key
449643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_BROWSER_SEARCH (AA) Windows 2000/XP: Browser Search key
450643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_BROWSER_FAVORITES (AB) Windows 2000/XP: Browser Favorites key
451643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_BROWSER_HOME (AC) Windows 2000/XP: Browser Start and Home key
452643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_VOLUME_MUTE (AD) Windows 2000/XP: Volume Mute key
453643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_VOLUME_DOWN (AE) Windows 2000/XP: Volume Down key
454643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_VOLUME_UP (AF) Windows 2000/XP: Volume Up key
455643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_MEDIA_NEXT_TRACK (B0) Windows 2000/XP: Next Track key
456643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_MEDIA_PREV_TRACK (B1) Windows 2000/XP: Previous Track key
457643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_MEDIA_STOP (B2) Windows 2000/XP: Stop Media key
458643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_MEDIA_PLAY_PAUSE (B3) Windows 2000/XP: Play/Pause Media key
459643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_LAUNCH_MAIL (B4) Windows 2000/XP: Start Mail key
460643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_LAUNCH_MEDIA_SELECT (B5) Windows 2000/XP: Select Media key
461643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_LAUNCH_APP1 (B6) Windows 2000/XP: Start Application 1 key
462643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_LAUNCH_APP2 (B7) Windows 2000/XP: Start Application 2 key
463643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
464643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_OEM_1 (BA) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the ';:' key
465643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case ';': case ':': return 0xBA;
466643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_OEM_PLUS (BB) Windows 2000/XP: For any country/region, the '+' key
467643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case '=': case '+': return 0xBB;
468643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_OEM_COMMA (BC) Windows 2000/XP: For any country/region, the ',' key
469643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case ',': case '<': return 0xBC;
470643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_OEM_MINUS (BD) Windows 2000/XP: For any country/region, the '-' key
471643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case '-': case '_': return 0xBD;
472643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_OEM_PERIOD (BE) Windows 2000/XP: For any country/region, the '.' key
473643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case '.': case '>': return 0xBE;
474643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_OEM_2 (BF) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '/?' key
475643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case '/': case '?': return 0xBF;
476643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_OEM_3 (C0) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '`~' key
477643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case '`': case '~': return 0xC0;
478643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_OEM_4 (DB) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '[{' key
479643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case '[': case '{': return 0xDB;
480643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_OEM_5 (DC) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '\|' key
481643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case '\\': case '|': return 0xDC;
482643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_OEM_6 (DD) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the ']}' key
483643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case ']': case '}': return 0xDD;
484643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_OEM_7 (DE) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the 'single-quote/double-quote' key
485643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case '\'': case '"': return 0xDE;
486643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
487643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_OEM_8 (DF) Used for miscellaneous characters; it can vary by keyboard.
488643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_OEM_102 (E2) Windows 2000/XP: Either the angle bracket key or the backslash key on the RT 102-key keyboard
489643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_PROCESSKEY (E5) Windows 95/98/Me, Windows NT 4.0, Windows 2000/XP: IME PROCESS key
490643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_PACKET (E7) Windows 2000/XP: Used to pass Unicode characters as if they were keystrokes. The VK_PACKET key is the low word of a 32-bit Virtual Key value used for non-keyboard input methods. For more information, see Remark in KEYBDINPUT,SendInput, WM_KEYDOWN, and WM_KEYUP
491643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_ATTN (F6) Attn key
492643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_CRSEL (F7) CrSel key
493643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_EXSEL (F8) ExSel key
494643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_EREOF (F9) Erase EOF key
495643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_PLAY (FA) Play key
496643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_ZOOM (FB) Zoom key
497643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_NONAME (FC) Reserved for future use
498643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_PA1 (FD) PA1 key
499643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // VK_OEM_CLEAR (FE) Clear key
500643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    }
501643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
502643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    return 0;
503643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}
504643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
505643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockstatic inline NSString* textFromEvent(NSEvent* event)
506643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{
507643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if ([event type] == NSFlagsChanged)
508643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"";
509643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    return [event characters];
510643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}
511643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
512643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockstatic inline NSString* unmodifiedTextFromEvent(NSEvent* event)
513643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{
514643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if ([event type] == NSFlagsChanged)
515643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"";
516643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    return [event charactersIgnoringModifiers];
517643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}
518643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
519643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockstatic NSString* keyIdentifierForKeyEvent(NSEvent* event)
520643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{
521643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if ([event type] == NSFlagsChanged) {
522643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        switch ([event keyCode]) {
523643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        case 54: // Right Command
524643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        case 55: // Left Command
525643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            return @"Meta";
526643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
527643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        case 57: // Capslock
528643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            return @"CapsLock";
529643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
530643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        case 56: // Left Shift
531643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        case 60: // Right Shift
532643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            return @"Shift";
533643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
534643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        case 58: // Left Alt
535643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        case 61: // Right Alt
536643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            return @"Alt";
537643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
538643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        case 59: // Left Ctrl
539643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        case 62: // Right Ctrl
540643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            return @"Control";
541643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
542643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// Begin non-Apple addition/modification --------------------------------------
543643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        case 63: // Function
544643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            return @"Function";
545643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
546643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        default: // Unknown, but this may be a strange/new keyboard.
547643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            return @"Unidentified";
548643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// End non-Apple addition/modification ----------------------------------------
549643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        }
550643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    }
551643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
552643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    NSString* s = [event charactersIgnoringModifiers];
553643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if ([s length] != 1)
554643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"Unidentified";
555643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
556643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    unichar c = [s characterAtIndex:0];
557643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    switch (c) {
558643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // Each identifier listed in the DOM spec is listed here.
559643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // Many are simply commented out since they do not appear on standard Macintosh keyboards
560643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // or are on a key that doesn't have a corresponding character.
561643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
562643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "Accept"
563643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "AllCandidates"
564643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
565643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "Alt"
566643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSMenuFunctionKey:
567643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"Alt";
568643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
569643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "Apps"
570643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "BrowserBack"
571643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "BrowserForward"
572643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "BrowserHome"
573643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "BrowserRefresh"
574643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "BrowserSearch"
575643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "BrowserStop"
576643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "CapsLock"
577643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
578643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "Clear"
579643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSClearLineFunctionKey:
580643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"Clear";
581643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
582643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "CodeInput"
583643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "Compose"
584643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "Control"
585643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "Crsel"
586643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "Convert"
587643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "Copy"
588643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "Cut"
589643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
590643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "Down"
591643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSDownArrowFunctionKey:
592643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"Down";
593643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "End"
594643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSEndFunctionKey:
595643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"End";
596643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "Enter"
597643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    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
598643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"Enter";
599643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
600643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "EraseEof"
601643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
602643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "Execute"
603643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSExecuteFunctionKey:
604643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"Execute";
605643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
606643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "Exsel"
607643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
608643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "F1"
609643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF1FunctionKey:
610643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"F1";
611643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "F2"
612643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF2FunctionKey:
613643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"F2";
614643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "F3"
615643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF3FunctionKey:
616643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"F3";
617643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "F4"
618643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF4FunctionKey:
619643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"F4";
620643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "F5"
621643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF5FunctionKey:
622643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"F5";
623643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "F6"
624643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF6FunctionKey:
625643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"F6";
626643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "F7"
627643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF7FunctionKey:
628643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"F7";
629643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "F8"
630643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF8FunctionKey:
631643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"F8";
632643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "F9"
633643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF9FunctionKey:
634643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"F9";
635643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "F10"
636643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF10FunctionKey:
637643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"F10";
638643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "F11"
639643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF11FunctionKey:
640643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"F11";
641643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "F12"
642643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF12FunctionKey:
643643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"F12";
644643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "F13"
645643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF13FunctionKey:
646643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"F13";
647643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "F14"
648643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF14FunctionKey:
649643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"F14";
650643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "F15"
651643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF15FunctionKey:
652643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"F15";
653643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "F16"
654643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF16FunctionKey:
655643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"F16";
656643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "F17"
657643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF17FunctionKey:
658643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"F17";
659643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "F18"
660643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF18FunctionKey:
661643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"F18";
662643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "F19"
663643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF19FunctionKey:
664643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"F19";
665643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "F20"
666643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF20FunctionKey:
667643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"F20";
668643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "F21"
669643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF21FunctionKey:
670643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"F21";
671643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "F22"
672643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF22FunctionKey:
673643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"F22";
674643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "F23"
675643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF23FunctionKey:
676643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"F23";
677643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "F24"
678643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF24FunctionKey:
679643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"F24";
680643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
681643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "FinalMode"
682643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
683643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "Find"
684643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSFindFunctionKey:
685643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"Find";
686643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
687643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "FullWidth"
688643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "HalfWidth"
689643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "HangulMode"
690643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "HanjaMode"
691643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
692643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "Help"
693643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSHelpFunctionKey:
694643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"Help";
695643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
696643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "Hiragana"
697643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
698643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "Home"
699643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSHomeFunctionKey:
700643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"Home";
701643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "Insert"
702643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSInsertFunctionKey:
703643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"Insert";
704643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
705643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "JapaneseHiragana"
706643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "JapaneseKatakana"
707643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "JapaneseRomaji"
708643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "JunjaMode"
709643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "KanaMode"
710643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "KanjiMode"
711643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "Katakana"
712643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "LaunchApplication1"
713643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "LaunchApplication2"
714643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "LaunchMail"
715643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
716643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "Left"
717643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSLeftArrowFunctionKey:
718643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"Left";
719643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
720643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "Meta"
721643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "MediaNextTrack"
722643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "MediaPlayPause"
723643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "MediaPreviousTrack"
724643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "MediaStop"
725643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
726643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "ModeChange"
727643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSModeSwitchFunctionKey:
728643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"ModeChange";
729643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
730643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "Nonconvert"
731643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "NumLock"
732643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
733643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "PageDown"
734643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSPageDownFunctionKey:
735643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"PageDown";
736643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "PageUp"
737643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSPageUpFunctionKey:
738643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"PageUp";
739643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
740643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "Paste"
741643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
742643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "Pause"
743643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSPauseFunctionKey:
744643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"Pause";
745643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
746643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "Play"
747643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "PreviousCandidate"
748643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
749643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "PrintScreen"
750643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSPrintScreenFunctionKey:
751643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"PrintScreen";
752643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
753643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "Process"
754643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "Props"
755643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
756643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "Right"
757643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSRightArrowFunctionKey:
758643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"Right";
759643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
760643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "RomanCharacters"
761643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
762643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "Scroll"
763643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSScrollLockFunctionKey:
764643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"Scroll";
765643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "Select"
766643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSSelectFunctionKey:
767643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"Select";
768643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
769643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "SelectMedia"
770643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "Shift"
771643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
772643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "Stop"
773643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSStopFunctionKey:
774643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"Stop";
775643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "Up"
776643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSUpArrowFunctionKey:
777643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"Up";
778643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "Undo"
779643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSUndoFunctionKey:
780643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"Undo";
781643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
782643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "VolumeDown"
783643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "VolumeMute"
784643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "VolumeUp"
785643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "Win"
786643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "Zoom"
787643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
788643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // More function keys, not in the key identifier specification.
789643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF25FunctionKey:
790643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"F25";
791643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF26FunctionKey:
792643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"F26";
793643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF27FunctionKey:
794643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"F27";
795643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF28FunctionKey:
796643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"F28";
797643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF29FunctionKey:
798643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"F29";
799643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF30FunctionKey:
800643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"F30";
801643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF31FunctionKey:
802643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"F31";
803643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF32FunctionKey:
804643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"F32";
805643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF33FunctionKey:
806643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"F33";
807643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF34FunctionKey:
808643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"F34";
809643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSF35FunctionKey:
810643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"F35";
811643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
812643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // Turn 0x7F into 0x08, because backspace needs to always be 0x08.
813643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case 0x7F:
814643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"U+0008";
815643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // Standard says that DEL becomes U+007F.
816643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSDeleteFunctionKey:
817643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"U+007F";
818643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
819643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // Always use 0x09 for tab instead of AppKit's backtab character.
820643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSBackTabCharacter:
821643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return @"U+0009";
822643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
823643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSBeginFunctionKey:
824643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSBreakFunctionKey:
825643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSClearDisplayFunctionKey:
826643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSDeleteCharFunctionKey:
827643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSDeleteLineFunctionKey:
828643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSInsertCharFunctionKey:
829643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSInsertLineFunctionKey:
830643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSNextFunctionKey:
831643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSPrevFunctionKey:
832643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSPrintFunctionKey:
833643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSRedoFunctionKey:
834643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSResetFunctionKey:
835643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSSysReqFunctionKey:
836643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSSystemFunctionKey:
837643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSUserFunctionKey:
838643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        // FIXME: We should use something other than the vendor-area Unicode values for the above keys.
839643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        // For now, just fall through to the default.
840643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    default:
841643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return [NSString stringWithFormat:@"U+%04X", WTF::toASCIIUpper(c)];
842643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    }
843643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}
844643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
845643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// End Apple code.
846643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// ----------------------------------------------------------------------------
847643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
848643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockstatic inline int modifiersFromEvent(NSEvent* event) {
849643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    int modifiers = 0;
850643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
851643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if ([event modifierFlags] & NSControlKeyMask)
852643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        modifiers |= WebInputEvent::ControlKey;
853643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if ([event modifierFlags] & NSShiftKeyMask)
854643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        modifiers |= WebInputEvent::ShiftKey;
855643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if ([event modifierFlags] & NSAlternateKeyMask)
856643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        modifiers |= WebInputEvent::AltKey;
857643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if ([event modifierFlags] & NSCommandKeyMask)
858643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        modifiers |= WebInputEvent::MetaKey;
859643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // TODO(port): Set mouse button states
860643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
861643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    return modifiers;
862643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}
863643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
864643ca7872b450ea4efacab6188849e5aac2ba161Steve BlockWebKeyboardEvent WebInputEventFactory::keyboardEvent(NSEvent* event)
865643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{
866643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    WebKeyboardEvent result;
867643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
868643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    result.type =
869643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        isKeyUpEvent(event) ? WebInputEvent::KeyUp : WebInputEvent::RawKeyDown;
870643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
871643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    result.modifiers = modifiersFromEvent(event);
872643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
873643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (isKeypadEvent(event))
874643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        result.modifiers |= WebInputEvent::IsKeyPad;
875643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
876643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (([event type] != NSFlagsChanged) && [event isARepeat])
877643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        result.modifiers |= WebInputEvent::IsAutoRepeat;
878643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
879643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    result.windowsKeyCode = windowsKeyCodeForKeyEvent(event);
880643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    result.nativeKeyCode = [event keyCode];
881643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
882643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    NSString* textStr = textFromEvent(event);
883643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    NSString* unmodifiedStr = unmodifiedTextFromEvent(event);
884643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    NSString* identifierStr = keyIdentifierForKeyEvent(event);
885643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
886643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // Begin Apple code, copied from KeyEventMac.mm
887643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
888643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // Always use 13 for Enter/Return -- we don't want to use AppKit's
889643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // different character for Enter.
890643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (result.windowsKeyCode == '\r') {
891643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        textStr = @"\r";
892643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        unmodifiedStr = @"\r";
893643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    }
894643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
895643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // The adjustments below are only needed in backward compatibility mode,
896643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // but we cannot tell what mode we are in from here.
897643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
898643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // Turn 0x7F into 8, because backspace needs to always be 8.
899643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if ([textStr isEqualToString:@"\x7F"])
900643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        textStr = @"\x8";
901643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if ([unmodifiedStr isEqualToString:@"\x7F"])
902643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        unmodifiedStr = @"\x8";
903643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // Always use 9 for tab -- we don't want to use AppKit's different character
904643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // for shift-tab.
905643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (result.windowsKeyCode == 9) {
906643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        textStr = @"\x9";
907643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        unmodifiedStr = @"\x9";
908643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    }
909643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
910643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // End Apple code.
911643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
912643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if ([textStr length] < WebKeyboardEvent::textLengthCap &&
913643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        [unmodifiedStr length] < WebKeyboardEvent::textLengthCap) {
914643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        [textStr getCharacters:&result.text[0]];
915643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        [unmodifiedStr getCharacters:&result.unmodifiedText[0]];
916643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    } else
917643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        ASSERT_NOT_REACHED();
918643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
919643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    [identifierStr getCString:&result.keyIdentifier[0]
920643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                    maxLength:sizeof(result.keyIdentifier)
921643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                     encoding:NSASCIIStringEncoding];
922643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
923643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    result.timeStampSeconds = [event timestamp];
924643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
925643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // Windows and Linux set |isSystemKey| if alt is down. WebKit looks at this
926643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // flag to decide if it should handle a key or not. E.g. alt-left/right
927643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // shouldn't be used by WebKit to scroll the current page, because we want
928643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // to get that key back for it to do history navigation. Hence, the
929643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // corresponding situation on OS X is to set this for cmd key presses.
930643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (result.modifiers & WebInputEvent::MetaKey)
931643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        result.isSystemKey = true;
932643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
933643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    return result;
934643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}
935643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
936643ca7872b450ea4efacab6188849e5aac2ba161Steve BlockWebKeyboardEvent WebInputEventFactory::keyboardEvent(wchar_t character,
937643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                                                     int modifiers,
938643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                                                     double timeStampSeconds)
939643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{
940643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // keyboardEvent(NSEvent*) depends on the NSEvent object and
941643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // it is hard to use it from methods of the NSTextInput protocol. For
942643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // such methods, this function creates a WebInputEvent::Char event without
943643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // using a NSEvent object.
944643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    WebKeyboardEvent result;
945643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    result.type = WebKit::WebInputEvent::Char;
946643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    result.timeStampSeconds = timeStampSeconds;
947643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    result.modifiers = modifiers;
948643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    result.windowsKeyCode = character;
949643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    result.nativeKeyCode = character;
950643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    result.text[0] = character;
951643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    result.unmodifiedText[0] = character;
952643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
953643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // Windows and Linux set |isSystemKey| if alt is down. WebKit looks at this
954643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // flag to decide if it should handle a key or not. E.g. alt-left/right
955643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // shouldn't be used by WebKit to scroll the current page, because we want
956643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // to get that key back for it to do history navigation. Hence, the
957643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // corresponding situation on OS X is to set this for cmd key presses.
958643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (result.modifiers & WebInputEvent::MetaKey)
959643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        result.isSystemKey = true;
960643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
961643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    return result;
962643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}
963643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
964643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// WebMouseEvent --------------------------------------------------------------
965643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
966643ca7872b450ea4efacab6188849e5aac2ba161Steve BlockWebMouseEvent WebInputEventFactory::mouseEvent(NSEvent* event, NSView* view)
967643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{
968643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    WebMouseEvent result;
969643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
970643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    result.clickCount = 0;
971643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
972643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    switch ([event type]) {
973643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSMouseExited:
974643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        result.type = WebInputEvent::MouseLeave;
975643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        result.button = WebMouseEvent::ButtonNone;
976643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        break;
977643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSLeftMouseDown:
978643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        result.type = WebInputEvent::MouseDown;
979643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        result.clickCount = [event clickCount];
980643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        result.button = WebMouseEvent::ButtonLeft;
981643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        break;
982643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSOtherMouseDown:
983643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        result.type = WebInputEvent::MouseDown;
984643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        result.clickCount = [event clickCount];
985643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        result.button = WebMouseEvent::ButtonMiddle;
986643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        break;
987643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSRightMouseDown:
988643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        result.type = WebInputEvent::MouseDown;
989643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        result.clickCount = [event clickCount];
990643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        result.button = WebMouseEvent::ButtonRight;
991643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        break;
992643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSLeftMouseUp:
993643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        result.type = WebInputEvent::MouseUp;
994643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        result.button = WebMouseEvent::ButtonLeft;
995643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        break;
996643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSOtherMouseUp:
997643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        result.type = WebInputEvent::MouseUp;
998643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        result.button = WebMouseEvent::ButtonMiddle;
999643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        break;
1000643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSRightMouseUp:
1001643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        result.type = WebInputEvent::MouseUp;
1002643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        result.button = WebMouseEvent::ButtonRight;
1003643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        break;
1004643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSMouseMoved:
1005643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSMouseEntered:
1006643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        result.type = WebInputEvent::MouseMove;
1007643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        break;
1008643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSLeftMouseDragged:
1009643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        result.type = WebInputEvent::MouseMove;
1010643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        result.button = WebMouseEvent::ButtonLeft;
1011643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        break;
1012643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSOtherMouseDragged:
1013643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        result.type = WebInputEvent::MouseMove;
1014643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        result.button = WebMouseEvent::ButtonMiddle;
1015643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        break;
1016643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case NSRightMouseDragged:
1017643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        result.type = WebInputEvent::MouseMove;
1018643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        result.button = WebMouseEvent::ButtonRight;
1019643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        break;
1020643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    default:
1021643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        ASSERT_NOT_REACHED();
1022643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    }
1023643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
1024643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    NSPoint location = [NSEvent mouseLocation];  // global coordinates
1025643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    result.globalX = location.x;
1026643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    result.globalY = [[[view window] screen] frame].size.height - location.y;
1027643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
1028643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    NSPoint windowLocal = [event locationInWindow];
1029643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    location = [view convertPoint:windowLocal fromView:nil];
1030643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    result.y = [view frame].size.height - location.y;  // flip y
1031643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    result.x = location.x;
1032643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    result.windowX = result.x;
1033643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    result.windowY = result.y;
1034643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
1035643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    result.modifiers = modifiersFromEvent(event);
1036643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
1037643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    result.timeStampSeconds = [event timestamp];
1038643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
1039643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    return result;
1040643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}
1041643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
1042643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// WebMouseWheelEvent ---------------------------------------------------------
1043643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
1044643ca7872b450ea4efacab6188849e5aac2ba161Steve BlockWebMouseWheelEvent WebInputEventFactory::mouseWheelEvent(NSEvent* event, NSView* view)
1045643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{
1046643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    WebMouseWheelEvent result;
1047643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
1048643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    result.type = WebInputEvent::MouseWheel;
1049643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    result.button = WebMouseEvent::ButtonNone;
1050643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
1051643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    result.modifiers = modifiersFromEvent(event);
1052643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
1053643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // Set coordinates by translating event coordinates from screen to client.
1054643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    NSPoint location = [NSEvent mouseLocation];  // global coordinates
1055643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    result.globalX = location.x;
1056643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    result.globalY = location.y;
1057643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    NSPoint windowLocal = [event locationInWindow];
1058643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    location = [view convertPoint:windowLocal fromView:nil];
1059643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    result.x = location.x;
1060643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    result.y = [view frame].size.height - location.y;  // flip y
1061643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    result.windowX = result.x;
1062643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    result.windowY = result.y;
1063643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
1064643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // Of Mice and Men
1065643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // ---------------
1066643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //
1067643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // There are three types of scroll data available on a scroll wheel CGEvent.
1068643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // Apple's documentation ([1]) is rather vague in their differences, and not
1069643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // terribly helpful in deciding which to use. This is what's really going on.
1070643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //
1071643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // First, these events behave very differently depending on whether a standard
1072643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // wheel mouse is used (one that scrolls in discrete units) or a
1073643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // trackpad/Mighty Mouse is used (which both provide continuous scrolling).
1074643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // You must check to see which was used for the event by testing the
1075643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // kCGScrollWheelEventIsContinuous field.
1076643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //
1077643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // Second, these events refer to "axes". Axis 1 is the y-axis, and axis 2 is
1078643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // the x-axis.
1079643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //
1080643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // Third, there is a concept of mouse acceleration. Scrolling the same amount
1081643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // of physical distance will give you different results logically depending on
1082643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // whether you scrolled a little at a time or in one continuous motion. Some
1083643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // fields account for this while others do not.
1084643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //
1085643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // Fourth, for trackpads there is a concept of chunkiness. When scrolling
1086643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // continuously, events can be delivered in chunks. That is to say, lots of
1087643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // scroll events with delta 0 will be delivered, and every so often an event
1088643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // with a non-zero delta will be delivered, containing the accumulated deltas
1089643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // from all the intermediate moves. [2]
1090643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //
1091643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // For notchy wheel mice (kCGScrollWheelEventIsContinuous == 0)
1092643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // ------------------------------------------------------------
1093643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //
1094643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // kCGScrollWheelEventDeltaAxis*
1095643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //   This is the rawest of raw events. For each mouse notch you get a value of
1096643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //   +1/-1. This does not take acceleration into account and thus is less
1097643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //   useful for building UIs.
1098643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //
1099643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // kCGScrollWheelEventPointDeltaAxis*
1100643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //   This is smarter. In general, for each mouse notch you get a value of
1101643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //   +1/-1, but this _does_ take acceleration into account, so you will get
1102643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //   larger values on longer scrolls. This field would be ideal for building
1103643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //   UIs except for one nasty bug: when the shift key is pressed, this set of
1104643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //   fields fails to move the value into the axis2 field (the other two types
1105643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //   of data do). This wouldn't be so bad except for the fact that while the
1106643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //   number of axes is used in the creation of a CGScrollWheelEvent, there is
1107643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //   no way to get that information out of the event once created.
1108643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //
1109643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // kCGScrollWheelEventFixedPtDeltaAxis*
1110643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //   This is a fixed value, and for each mouse notch you get a value of
1111643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //   +0.1/-0.1 (but, like above, scaled appropriately for acceleration). This
1112643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //   value takes acceleration into account, and in fact is identical to the
1113643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //   results you get from -[NSEvent delta*]. (That is, if you linked on Tiger
1114643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //   or greater; see [2] for details.)
1115643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //
1116643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // A note about continuous devices
1117643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // -------------------------------
1118643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //
1119643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // There are two devices that provide continuous scrolling events (trackpads
1120643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // and Mighty Mouses) and they behave rather differently. The Mighty Mouse
1121643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // behaves a lot like a regular mouse. There is no chunking, and the
1122643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // FixedPtDelta values are the PointDelta values multiplied by 0.1. With the
1123643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // trackpad, though, there is chunking. While the FixedPtDelta values are
1124643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // reasonable (they occur about every fifth event but have values five times
1125643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // larger than usual) the Delta values are unreasonable. They don't appear to
1126643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // accumulate properly.
1127643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //
1128643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // For continuous devices (kCGScrollWheelEventIsContinuous != 0)
1129643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // -------------------------------------------------------------
1130643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //
1131643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // kCGScrollWheelEventDeltaAxis*
1132643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //   This provides values with no acceleration. With a trackpad, these values
1133643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //   are chunked but each non-zero value does not appear to be cumulative.
1134643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //   This seems to be a bug.
1135643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //
1136643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // kCGScrollWheelEventPointDeltaAxis*
1137643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //   This provides values with acceleration. With a trackpad, these values are
1138643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //   not chunked and are highly accurate.
1139643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //
1140643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // kCGScrollWheelEventFixedPtDeltaAxis*
1141643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //   This provides values with acceleration. With a trackpad, these values are
1142643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //   chunked but unlike Delta events are properly cumulative.
1143643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //
1144643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // Summary
1145643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // -------
1146643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //
1147643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // In general the best approach to take is: determine if the event is
1148643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // continuous. If it is not, then use the FixedPtDelta events (or just stick
1149643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // with Cocoa events). They provide both acceleration and proper horizontal
1150643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // scrolling. If the event is continuous, then doing pixel scrolling with the
1151643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // PointDelta is the way to go. In general, avoid the Delta events. They're
1152643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // the oldest (dating back to 10.4, before CGEvents were public) but they lack
1153643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // acceleration and precision, making them useful only in specific edge cases.
1154643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //
1155643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // References
1156643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // ----------
1157643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //
1158643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // [1] <http://developer.apple.com/documentation/Carbon/Reference/QuartzEventServicesRef/Reference/reference.html>
1159643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // [2] <http://developer.apple.com/releasenotes/Cocoa/AppKitOlderNotes.html>
1160643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //     Scroll to the section headed "NSScrollWheel events".
1161643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    //
1162643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // P.S. The "smooth scrolling" option in the system preferences is utterly
1163643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // unrelated to any of this.
1164643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
1165643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    CGEventRef cgEvent = [event CGEvent];
1166643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    ASSERT(cgEvent);
1167643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
1168643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // Wheel ticks are supposed to be raw, unaccelerated values, one per physical
1169643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // mouse wheel notch. The delta event is perfect for this (being a good
1170643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // "specific edge case" as mentioned above). Trackpads, unfortunately, do
1171643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // event chunking, and sending mousewheel events with 0 ticks causes some
1172643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // websites to malfunction. Therefore, for all continuous input devices we use
1173643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // the point delta data instead, since we cannot distinguish trackpad data
1174643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // from data from any other continuous device.
1175643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
1176643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEventIsContinuous)) {
1177643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        result.wheelTicksY = result.deltaY =
1178643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEventPointDeltaAxis1);
1179643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        result.wheelTicksX = result.deltaX =
1180643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEventPointDeltaAxis2);
1181643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    } else {
1182643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        result.wheelTicksY =
1183643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEventDeltaAxis1);
1184643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        result.wheelTicksX =
1185643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEventDeltaAxis2);
1186643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
1187643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        // Convert wheel delta amount to a number of pixels to scroll.
1188643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        static const double scrollbarPixelsPerCocoaTick = 40.0;
1189643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
1190643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        result.deltaX = [event deltaX] * scrollbarPixelsPerCocoaTick;
1191643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        result.deltaY = [event deltaY] * scrollbarPixelsPerCocoaTick;
1192643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    }
1193643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
1194643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    result.timeStampSeconds = [event timestamp];
1195643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
1196643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    return result;
1197643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}
1198643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
1199643ca7872b450ea4efacab6188849e5aac2ba161Steve Block} // namespace WebKit
1200