Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(46)

Side by Side Diff: Source/web/mac/WebInputEventFactory.mm

Issue 26247009: Remove web/{android, gtk, win} (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Reworked on comments! Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « Source/web/gtk/WebInputEventFactory.cpp ('k') | Source/web/web.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2004, 2006, 2007 Apple Inc. All rights reserved.
3 * Copyright (C) 2006-2009 Google Inc.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27 #include "config.h"
28 #include "WebInputEventFactory.h"
29
30 #include <ApplicationServices/ApplicationServices.h>
31 #import <AvailabilityMacros.h>
32 #import <Cocoa/Cocoa.h>
33
34 #include "WebInputEvent.h"
35 #include "core/platform/WindowsKeyboardCodes.h"
36 #include "wtf/ASCIICType.h"
37
38 #if __MAC_OS_X_VERSION_MAX_ALLOWED == 1060
39
40 // Additional Lion APIs.
41 enum {
42 NSEventPhaseNone = 0,
43 NSEventPhaseBegan = 0x1 << 0,
44 NSEventPhaseStationary = 0x1 << 1,
45 NSEventPhaseChanged = 0x1 << 2,
46 NSEventPhaseEnded = 0x1 << 3,
47 NSEventPhaseCancelled = 0x1 << 4
48 };
49 typedef NSUInteger NSEventPhase;
50
51 @interface NSEvent (LionSDKDeclarations)
52 - (NSEventPhase)phase;
53 - (NSEventPhase)momentumPhase;
54 @end
55
56 #endif // __MAC_OS_X_VERSION_MAX_ALLOWED == 1060
57
58 #if __MAC_OS_X_VERSION_MAX_ALLOWED < 1080
59
60 // Additional Mountain Lion APIs.
61 enum {
62 NSEventPhaseMayBegin = 0x1 << 5
63 };
64
65 #endif // __MAC_OS_X_VERSION_MAX_ALLOWED < 1080
66
67 namespace WebKit {
68
69 static int windowsKeyCodeForKeyCode(uint16_t keyCode)
70 {
71 static const int windowsKeyCode[] = {
72 /* 0 */ VK_A,
73 /* 1 */ VK_S,
74 /* 2 */ VK_D,
75 /* 3 */ VK_F,
76 /* 4 */ VK_H,
77 /* 5 */ VK_G,
78 /* 6 */ VK_Z,
79 /* 7 */ VK_X,
80 /* 8 */ VK_C,
81 /* 9 */ VK_V,
82 /* 0x0A */ VK_OEM_3, // "Section" - key to the left from 1 (ISO Keyboard Only)
83 /* 0x0B */ VK_B,
84 /* 0x0C */ VK_Q,
85 /* 0x0D */ VK_W,
86 /* 0x0E */ VK_E,
87 /* 0x0F */ VK_R,
88 /* 0x10 */ VK_Y,
89 /* 0x11 */ VK_T,
90 /* 0x12 */ VK_1,
91 /* 0x13 */ VK_2,
92 /* 0x14 */ VK_3,
93 /* 0x15 */ VK_4,
94 /* 0x16 */ VK_6,
95 /* 0x17 */ VK_5,
96 /* 0x18 */ VK_OEM_PLUS, // =+
97 /* 0x19 */ VK_9,
98 /* 0x1A */ VK_7,
99 /* 0x1B */ VK_OEM_MINUS, // -_
100 /* 0x1C */ VK_8,
101 /* 0x1D */ VK_0,
102 /* 0x1E */ VK_OEM_6, // ]}
103 /* 0x1F */ VK_O,
104 /* 0x20 */ VK_U,
105 /* 0x21 */ VK_OEM_4, // {[
106 /* 0x22 */ VK_I,
107 /* 0x23 */ VK_P,
108 /* 0x24 */ VK_RETURN, // Return
109 /* 0x25 */ VK_L,
110 /* 0x26 */ VK_J,
111 /* 0x27 */ VK_OEM_7, // '"
112 /* 0x28 */ VK_K,
113 /* 0x29 */ VK_OEM_1, // ;:
114 /* 0x2A */ VK_OEM_5, // \|
115 /* 0x2B */ VK_OEM_COMMA, // ,<
116 /* 0x2C */ VK_OEM_2, // /?
117 /* 0x2D */ VK_N,
118 /* 0x2E */ VK_M,
119 /* 0x2F */ VK_OEM_PERIOD, // .>
120 /* 0x30 */ VK_TAB,
121 /* 0x31 */ VK_SPACE,
122 /* 0x32 */ VK_OEM_3, // `~
123 /* 0x33 */ VK_BACK, // Backspace
124 /* 0x34 */ 0, // n/a
125 /* 0x35 */ VK_ESCAPE,
126 /* 0x36 */ VK_APPS, // Right Command
127 /* 0x37 */ VK_LWIN, // Left Command
128 /* 0x38 */ VK_LSHIFT, // Left Shift
129 /* 0x39 */ VK_CAPITAL, // Caps Lock
130 /* 0x3A */ VK_LMENU, // Left Option
131 /* 0x3B */ VK_LCONTROL, // Left Ctrl
132 /* 0x3C */ VK_RSHIFT, // Right Shift
133 /* 0x3D */ VK_RMENU, // Right Option
134 /* 0x3E */ VK_RCONTROL, // Right Ctrl
135 /* 0x3F */ 0, // fn
136 /* 0x40 */ VK_F17,
137 /* 0x41 */ VK_DECIMAL, // Num Pad .
138 /* 0x42 */ 0, // n/a
139 /* 0x43 */ VK_MULTIPLY, // Num Pad *
140 /* 0x44 */ 0, // n/a
141 /* 0x45 */ VK_ADD, // Num Pad +
142 /* 0x46 */ 0, // n/a
143 /* 0x47 */ VK_CLEAR, // Num Pad Clear
144 /* 0x48 */ VK_VOLUME_UP,
145 /* 0x49 */ VK_VOLUME_DOWN,
146 /* 0x4A */ VK_VOLUME_MUTE,
147 /* 0x4B */ VK_DIVIDE, // Num Pad /
148 /* 0x4C */ VK_RETURN, // Num Pad Enter
149 /* 0x4D */ 0, // n/a
150 /* 0x4E */ VK_SUBTRACT, // Num Pad -
151 /* 0x4F */ VK_F18,
152 /* 0x50 */ VK_F19,
153 /* 0x51 */ VK_OEM_PLUS, // Num Pad =. There is no such key on common PC keyboards, mapping to normal "+=".
154 /* 0x52 */ VK_NUMPAD0,
155 /* 0x53 */ VK_NUMPAD1,
156 /* 0x54 */ VK_NUMPAD2,
157 /* 0x55 */ VK_NUMPAD3,
158 /* 0x56 */ VK_NUMPAD4,
159 /* 0x57 */ VK_NUMPAD5,
160 /* 0x58 */ VK_NUMPAD6,
161 /* 0x59 */ VK_NUMPAD7,
162 /* 0x5A */ VK_F20,
163 /* 0x5B */ VK_NUMPAD8,
164 /* 0x5C */ VK_NUMPAD9,
165 /* 0x5D */ 0, // Yen (JIS Keyboard Only)
166 /* 0x5E */ 0, // Underscore (JIS Keyboard Only)
167 /* 0x5F */ 0, // KeypadComma (JIS Keyboard Only)
168 /* 0x60 */ VK_F5,
169 /* 0x61 */ VK_F6,
170 /* 0x62 */ VK_F7,
171 /* 0x63 */ VK_F3,
172 /* 0x64 */ VK_F8,
173 /* 0x65 */ VK_F9,
174 /* 0x66 */ 0, // Eisu (JIS Keyboard Only)
175 /* 0x67 */ VK_F11,
176 /* 0x68 */ 0, // Kana (JIS Keyboard Only)
177 /* 0x69 */ VK_F13,
178 /* 0x6A */ VK_F16,
179 /* 0x6B */ VK_F14,
180 /* 0x6C */ 0, // n/a
181 /* 0x6D */ VK_F10,
182 /* 0x6E */ 0, // n/a (Windows95 key?)
183 /* 0x6F */ VK_F12,
184 /* 0x70 */ 0, // n/a
185 /* 0x71 */ VK_F15,
186 /* 0x72 */ VK_INSERT, // Help
187 /* 0x73 */ VK_HOME, // Home
188 /* 0x74 */ VK_PRIOR, // Page Up
189 /* 0x75 */ VK_DELETE, // Forward Delete
190 /* 0x76 */ VK_F4,
191 /* 0x77 */ VK_END, // End
192 /* 0x78 */ VK_F2,
193 /* 0x79 */ VK_NEXT, // Page Down
194 /* 0x7A */ VK_F1,
195 /* 0x7B */ VK_LEFT, // Left Arrow
196 /* 0x7C */ VK_RIGHT, // Right Arrow
197 /* 0x7D */ VK_DOWN, // Down Arrow
198 /* 0x7E */ VK_UP, // Up Arrow
199 /* 0x7F */ 0 // n/a
200 };
201
202 if (keyCode >= 0x80)
203 return 0;
204
205 return windowsKeyCode[keyCode];
206 }
207
208 static int windowsKeyCodeForCharCode(unichar charCode)
209 {
210 switch (charCode) {
211
212 case 'a': case 'A': return VK_A;
213 case 'b': case 'B': return VK_B;
214 case 'c': case 'C': return VK_C;
215 case 'd': case 'D': return VK_D;
216 case 'e': case 'E': return VK_E;
217 case 'f': case 'F': return VK_F;
218 case 'g': case 'G': return VK_G;
219 case 'h': case 'H': return VK_H;
220 case 'i': case 'I': return VK_I;
221 case 'j': case 'J': return VK_J;
222 case 'k': case 'K': return VK_K;
223 case 'l': case 'L': return VK_L;
224 case 'm': case 'M': return VK_M;
225 case 'n': case 'N': return VK_N;
226 case 'o': case 'O': return VK_O;
227 case 'p': case 'P': return VK_P;
228 case 'q': case 'Q': return VK_Q;
229 case 'r': case 'R': return VK_R;
230 case 's': case 'S': return VK_S;
231 case 't': case 'T': return VK_T;
232 case 'u': case 'U': return VK_U;
233 case 'v': case 'V': return VK_V;
234 case 'w': case 'W': return VK_W;
235 case 'x': case 'X': return VK_X;
236 case 'y': case 'Y': return VK_Y;
237 case 'z': case 'Z': return VK_Z;
238
239 // AppKit generates Unicode PUA character codes for some function keys; using these when key code is not known.
240 case NSPauseFunctionKey: return VK_PAUSE;
241 case NSSelectFunctionKey: return VK_SELECT;
242 case NSPrintFunctionKey: return VK_PRINT;
243 case NSExecuteFunctionKey: return VK_EXECUTE;
244 case NSPrintScreenFunctionKey: return VK_SNAPSHOT;
245 case NSInsertFunctionKey: return VK_INSERT;
246
247 case NSF21FunctionKey: return VK_F21;
248 case NSF22FunctionKey: return VK_F22;
249 case NSF23FunctionKey: return VK_F23;
250 case NSF24FunctionKey: return VK_F24;
251 case NSScrollLockFunctionKey: return VK_SCROLL;
252
253 // This is for U.S. keyboard mapping, and doesn't necessarily make sense for different keyboard layouts.
254 // For example, '"' on Windows Russian layout is VK_2, not VK_OEM_7.
255 case ';': case ':': return VK_OEM_1;
256 case '=': case '+': return VK_OEM_PLUS;
257 case ',': case '<': return VK_OEM_COMMA;
258 case '-': case '_': return VK_OEM_MINUS;
259 case '.': case '>': return VK_OEM_PERIOD;
260 case '/': case '?': return VK_OEM_2;
261 case '`': case '~': return VK_OEM_3;
262 case '[': case '{': return VK_OEM_4;
263 case '\\': case '|': return VK_OEM_5;
264 case ']': case '}': return VK_OEM_6;
265 case '\'': case '"': return VK_OEM_7;
266
267 }
268
269 return 0;
270 }
271
272 static inline bool isKeyUpEvent(NSEvent* event)
273 {
274 if ([event type] != NSFlagsChanged)
275 return [event type] == NSKeyUp;
276 // FIXME: This logic fails if the user presses both Shift keys at once, for example:
277 // we treat releasing one of them as keyDown.
278 switch ([event keyCode]) {
279 case 54: // Right Command
280 case 55: // Left Command
281 return ([event modifierFlags] & NSCommandKeyMask) == 0;
282
283 case 57: // Capslock
284 return ([event modifierFlags] & NSAlphaShiftKeyMask) == 0;
285
286 case 56: // Left Shift
287 case 60: // Right Shift
288 return ([event modifierFlags] & NSShiftKeyMask) == 0;
289
290 case 58: // Left Alt
291 case 61: // Right Alt
292 return ([event modifierFlags] & NSAlternateKeyMask) == 0;
293
294 case 59: // Left Ctrl
295 case 62: // Right Ctrl
296 return ([event modifierFlags] & NSControlKeyMask) == 0;
297
298 case 63: // Function
299 return ([event modifierFlags] & NSFunctionKeyMask) == 0;
300 }
301 return false;
302 }
303
304 static bool isKeypadEvent(NSEvent* event)
305 {
306 // Check that this is the type of event that has a keyCode.
307 switch ([event type]) {
308 case NSKeyDown:
309 case NSKeyUp:
310 case NSFlagsChanged:
311 break;
312 default:
313 return false;
314 }
315
316 switch ([event keyCode]) {
317 case 71: // Clear
318 case 81: // =
319 case 75: // /
320 case 67: // *
321 case 78: // -
322 case 69: // +
323 case 76: // Enter
324 case 65: // .
325 case 82: // 0
326 case 83: // 1
327 case 84: // 2
328 case 85: // 3
329 case 86: // 4
330 case 87: // 5
331 case 88: // 6
332 case 89: // 7
333 case 91: // 8
334 case 92: // 9
335 return true;
336 }
337
338 return false;
339 }
340
341 static int windowsKeyCodeForKeyEvent(NSEvent* event)
342 {
343 int code = 0;
344 // There are several kinds of characters for which we produce key code from char code:
345 // 1. Roman letters. Windows keyboard layouts affect both virtual key codes and character codes for these,
346 // so e.g. 'A' gets the same keyCode on QWERTY, AZERTY or Dvorak layouts.
347 // 2. Keys for which there is no known Mac virtual key codes, like PrintScre en.
348 // 3. Certain punctuation keys. On Windows, these are also remapped dependin g on current keyboard layout,
349 // but see comment in windowsKeyCodeForCharCode().
350 if (!isKeypadEvent(event) && ([event type] == NSKeyDown || [event type] == N SKeyUp)) {
351 // Cmd switches Roman letters for Dvorak-QWERTY layout, so try modified characters first.
352 NSString* s = [event characters];
353 code = [s length] > 0 ? windowsKeyCodeForCharCode([s characterAtIndex:0] ) : 0;
354 if (code)
355 return code;
356
357 // Ctrl+A on an AZERTY keyboard would get VK_Q keyCode if we relied on - [NSEvent keyCode] below.
358 s = [event charactersIgnoringModifiers];
359 code = [s length] > 0 ? windowsKeyCodeForCharCode([s characterAtIndex:0] ) : 0;
360 if (code)
361 return code;
362 }
363
364 // Map Mac virtual key code directly to Windows one for any keys not handled above.
365 // E.g. the key next to Caps Lock has the same Event.keyCode on U.S. keyboar d ('A') and on Russian keyboard (CYRILLIC LETTER EF).
366 return windowsKeyCodeForKeyCode([event keyCode]);
367 }
368
369 static WebInputEvent::Type gestureEventTypeForEvent(NSEvent *event)
370 {
371 switch ([event type]) {
372 case NSEventTypeBeginGesture:
373 return WebInputEvent::GestureScrollBegin;
374 case NSEventTypeEndGesture:
375 return WebInputEvent::GestureScrollEnd;
376 default:
377 ASSERT_NOT_REACHED();
378 return WebInputEvent::GestureScrollEnd;
379 }
380 }
381
382 static inline NSString* textFromEvent(NSEvent* event)
383 {
384 if ([event type] == NSFlagsChanged)
385 return @"";
386 return [event characters];
387 }
388
389 static inline NSString* unmodifiedTextFromEvent(NSEvent* event)
390 {
391 if ([event type] == NSFlagsChanged)
392 return @"";
393 return [event charactersIgnoringModifiers];
394 }
395
396 static NSString* keyIdentifierForKeyEvent(NSEvent* event)
397 {
398 if ([event type] == NSFlagsChanged) {
399 switch ([event keyCode]) {
400 case 54: // Right Command
401 case 55: // Left Command
402 return @"Meta";
403
404 case 57: // Capslock
405 return @"CapsLock";
406
407 case 56: // Left Shift
408 case 60: // Right Shift
409 return @"Shift";
410
411 case 58: // Left Alt
412 case 61: // Right Alt
413 return @"Alt";
414
415 case 59: // Left Ctrl
416 case 62: // Right Ctrl
417 return @"Control";
418
419 // Begin non-Apple addition/modification --------------------------------------
420 case 63: // Function
421 return @"Function";
422
423 default: // Unknown, but this may be a strange/new keyboard.
424 return @"Unidentified";
425 // End non-Apple addition/modification ----------------------------------------
426 }
427 }
428
429 NSString* s = [event charactersIgnoringModifiers];
430 if ([s length] != 1)
431 return @"Unidentified";
432
433 unichar c = [s characterAtIndex:0];
434 switch (c) {
435 // Each identifier listed in the DOM spec is listed here.
436 // Many are simply commented out since they do not appear on standard Macint osh keyboards
437 // or are on a key that doesn't have a corresponding character.
438
439 // "Accept"
440 // "AllCandidates"
441
442 // "Alt"
443 case NSMenuFunctionKey:
444 return @"Alt";
445
446 // "Apps"
447 // "BrowserBack"
448 // "BrowserForward"
449 // "BrowserHome"
450 // "BrowserRefresh"
451 // "BrowserSearch"
452 // "BrowserStop"
453 // "CapsLock"
454
455 // "Clear"
456 case NSClearLineFunctionKey:
457 return @"Clear";
458
459 // "CodeInput"
460 // "Compose"
461 // "Control"
462 // "Crsel"
463 // "Convert"
464 // "Copy"
465 // "Cut"
466
467 // "Down"
468 case NSDownArrowFunctionKey:
469 return @"Down";
470 // "End"
471 case NSEndFunctionKey:
472 return @"End";
473 // "Enter"
474 case 0x3: case 0xA: case 0xD: // Macintosh calls the one on the main keyboar d Return, but Windows calls it Enter, so we'll do the same for the DOM
475 return @"Enter";
476
477 // "EraseEof"
478
479 // "Execute"
480 case NSExecuteFunctionKey:
481 return @"Execute";
482
483 // "Exsel"
484
485 // "F1"
486 case NSF1FunctionKey:
487 return @"F1";
488 // "F2"
489 case NSF2FunctionKey:
490 return @"F2";
491 // "F3"
492 case NSF3FunctionKey:
493 return @"F3";
494 // "F4"
495 case NSF4FunctionKey:
496 return @"F4";
497 // "F5"
498 case NSF5FunctionKey:
499 return @"F5";
500 // "F6"
501 case NSF6FunctionKey:
502 return @"F6";
503 // "F7"
504 case NSF7FunctionKey:
505 return @"F7";
506 // "F8"
507 case NSF8FunctionKey:
508 return @"F8";
509 // "F9"
510 case NSF9FunctionKey:
511 return @"F9";
512 // "F10"
513 case NSF10FunctionKey:
514 return @"F10";
515 // "F11"
516 case NSF11FunctionKey:
517 return @"F11";
518 // "F12"
519 case NSF12FunctionKey:
520 return @"F12";
521 // "F13"
522 case NSF13FunctionKey:
523 return @"F13";
524 // "F14"
525 case NSF14FunctionKey:
526 return @"F14";
527 // "F15"
528 case NSF15FunctionKey:
529 return @"F15";
530 // "F16"
531 case NSF16FunctionKey:
532 return @"F16";
533 // "F17"
534 case NSF17FunctionKey:
535 return @"F17";
536 // "F18"
537 case NSF18FunctionKey:
538 return @"F18";
539 // "F19"
540 case NSF19FunctionKey:
541 return @"F19";
542 // "F20"
543 case NSF20FunctionKey:
544 return @"F20";
545 // "F21"
546 case NSF21FunctionKey:
547 return @"F21";
548 // "F22"
549 case NSF22FunctionKey:
550 return @"F22";
551 // "F23"
552 case NSF23FunctionKey:
553 return @"F23";
554 // "F24"
555 case NSF24FunctionKey:
556 return @"F24";
557
558 // "FinalMode"
559
560 // "Find"
561 case NSFindFunctionKey:
562 return @"Find";
563
564 // "FullWidth"
565 // "HalfWidth"
566 // "HangulMode"
567 // "HanjaMode"
568
569 // "Help"
570 case NSHelpFunctionKey:
571 return @"Help";
572
573 // "Hiragana"
574
575 // "Home"
576 case NSHomeFunctionKey:
577 return @"Home";
578 // "Insert"
579 case NSInsertFunctionKey:
580 return @"Insert";
581
582 // "JapaneseHiragana"
583 // "JapaneseKatakana"
584 // "JapaneseRomaji"
585 // "JunjaMode"
586 // "KanaMode"
587 // "KanjiMode"
588 // "Katakana"
589 // "LaunchApplication1"
590 // "LaunchApplication2"
591 // "LaunchMail"
592
593 // "Left"
594 case NSLeftArrowFunctionKey:
595 return @"Left";
596
597 // "Meta"
598 // "MediaNextTrack"
599 // "MediaPlayPause"
600 // "MediaPreviousTrack"
601 // "MediaStop"
602
603 // "ModeChange"
604 case NSModeSwitchFunctionKey:
605 return @"ModeChange";
606
607 // "Nonconvert"
608 // "NumLock"
609
610 // "PageDown"
611 case NSPageDownFunctionKey:
612 return @"PageDown";
613 // "PageUp"
614 case NSPageUpFunctionKey:
615 return @"PageUp";
616
617 // "Paste"
618
619 // "Pause"
620 case NSPauseFunctionKey:
621 return @"Pause";
622
623 // "Play"
624 // "PreviousCandidate"
625
626 // "PrintScreen"
627 case NSPrintScreenFunctionKey:
628 return @"PrintScreen";
629
630 // "Process"
631 // "Props"
632
633 // "Right"
634 case NSRightArrowFunctionKey:
635 return @"Right";
636
637 // "RomanCharacters"
638
639 // "Scroll"
640 case NSScrollLockFunctionKey:
641 return @"Scroll";
642 // "Select"
643 case NSSelectFunctionKey:
644 return @"Select";
645
646 // "SelectMedia"
647 // "Shift"
648
649 // "Stop"
650 case NSStopFunctionKey:
651 return @"Stop";
652 // "Up"
653 case NSUpArrowFunctionKey:
654 return @"Up";
655 // "Undo"
656 case NSUndoFunctionKey:
657 return @"Undo";
658
659 // "VolumeDown"
660 // "VolumeMute"
661 // "VolumeUp"
662 // "Win"
663 // "Zoom"
664
665 // More function keys, not in the key identifier specification.
666 case NSF25FunctionKey:
667 return @"F25";
668 case NSF26FunctionKey:
669 return @"F26";
670 case NSF27FunctionKey:
671 return @"F27";
672 case NSF28FunctionKey:
673 return @"F28";
674 case NSF29FunctionKey:
675 return @"F29";
676 case NSF30FunctionKey:
677 return @"F30";
678 case NSF31FunctionKey:
679 return @"F31";
680 case NSF32FunctionKey:
681 return @"F32";
682 case NSF33FunctionKey:
683 return @"F33";
684 case NSF34FunctionKey:
685 return @"F34";
686 case NSF35FunctionKey:
687 return @"F35";
688
689 // Turn 0x7F into 0x08, because backspace needs to always be 0x08.
690 case 0x7F:
691 return @"U+0008";
692 // Standard says that DEL becomes U+007F.
693 case NSDeleteFunctionKey:
694 return @"U+007F";
695
696 // Always use 0x09 for tab instead of AppKit's backtab character.
697 case NSBackTabCharacter:
698 return @"U+0009";
699
700 case NSBeginFunctionKey:
701 case NSBreakFunctionKey:
702 case NSClearDisplayFunctionKey:
703 case NSDeleteCharFunctionKey:
704 case NSDeleteLineFunctionKey:
705 case NSInsertCharFunctionKey:
706 case NSInsertLineFunctionKey:
707 case NSNextFunctionKey:
708 case NSPrevFunctionKey:
709 case NSPrintFunctionKey:
710 case NSRedoFunctionKey:
711 case NSResetFunctionKey:
712 case NSSysReqFunctionKey:
713 case NSSystemFunctionKey:
714 case NSUserFunctionKey:
715 // FIXME: We should use something other than the vendor-area Unicode val ues for the above keys.
716 // For now, just fall through to the default.
717 default:
718 return [NSString stringWithFormat:@"U+%04X", WTF::toASCIIUpper(c)];
719 }
720 }
721
722 // End Apple code.
723 // ----------------------------------------------------------------------------
724
725 static inline int modifiersFromEvent(NSEvent* event) {
726 int modifiers = 0;
727
728 if ([event modifierFlags] & NSControlKeyMask)
729 modifiers |= WebInputEvent::ControlKey;
730 if ([event modifierFlags] & NSShiftKeyMask)
731 modifiers |= WebInputEvent::ShiftKey;
732 if ([event modifierFlags] & NSAlternateKeyMask)
733 modifiers |= WebInputEvent::AltKey;
734 if ([event modifierFlags] & NSCommandKeyMask)
735 modifiers |= WebInputEvent::MetaKey;
736 if ([event modifierFlags] & NSAlphaShiftKeyMask)
737 modifiers |= WebInputEvent::CapsLockOn;
738 // TODO(port): Set mouse button states
739
740 return modifiers;
741 }
742
743 static inline void setWebEventLocationFromEventInView(WebMouseEvent* result,
744 NSEvent* event,
745 NSView* view) {
746 NSPoint windowLocal = [event locationInWindow];
747
748 NSPoint screenLocal = [[view window] convertBaseToScreen:windowLocal];
749 result->globalX = screenLocal.x;
750 // Flip y.
751 NSScreen* primaryScreen = ([[NSScreen screens] count] > 0) ?
752 [[NSScreen screens] objectAtIndex:0] : nil;
753 if (primaryScreen)
754 result->globalY = [primaryScreen frame].size.height - screenLocal.y;
755 else
756 result->globalY = screenLocal.y;
757
758 NSPoint contentLocal = [view convertPoint:windowLocal fromView:nil];
759 result->x = contentLocal.x;
760 result->y = [view frame].size.height - contentLocal.y; // Flip y.
761
762 result->windowX = result->x;
763 result->windowY = result->y;
764
765 result->movementX = [event deltaX];
766 result->movementY = [event deltaY];
767 }
768
769 WebKeyboardEvent WebInputEventFactory::keyboardEvent(NSEvent* event)
770 {
771 WebKeyboardEvent result;
772
773 result.type =
774 isKeyUpEvent(event) ? WebInputEvent::KeyUp : WebInputEvent::RawKeyDown;
775
776 result.modifiers = modifiersFromEvent(event);
777
778 if (isKeypadEvent(event))
779 result.modifiers |= WebInputEvent::IsKeyPad;
780
781 if (([event type] != NSFlagsChanged) && [event isARepeat])
782 result.modifiers |= WebInputEvent::IsAutoRepeat;
783
784 int windowsKeyCode = windowsKeyCodeForKeyEvent(event);
785 result.windowsKeyCode = WebKeyboardEvent::windowsKeyCodeWithoutLocation(wind owsKeyCode);
786 result.modifiers |= WebKeyboardEvent::locationModifiersFromWindowsKeyCode(wi ndowsKeyCode);
787 result.nativeKeyCode = [event keyCode];
788
789 NSString* textStr = textFromEvent(event);
790 NSString* unmodifiedStr = unmodifiedTextFromEvent(event);
791 NSString* identifierStr = keyIdentifierForKeyEvent(event);
792
793 // Begin Apple code, copied from KeyEventMac.mm
794
795 // Always use 13 for Enter/Return -- we don't want to use AppKit's
796 // different character for Enter.
797 if (result.windowsKeyCode == '\r') {
798 textStr = @"\r";
799 unmodifiedStr = @"\r";
800 }
801
802 // The adjustments below are only needed in backward compatibility mode,
803 // but we cannot tell what mode we are in from here.
804
805 // Turn 0x7F into 8, because backspace needs to always be 8.
806 if ([textStr isEqualToString:@"\x7F"])
807 textStr = @"\x8";
808 if ([unmodifiedStr isEqualToString:@"\x7F"])
809 unmodifiedStr = @"\x8";
810 // Always use 9 for tab -- we don't want to use AppKit's different character
811 // for shift-tab.
812 if (result.windowsKeyCode == 9) {
813 textStr = @"\x9";
814 unmodifiedStr = @"\x9";
815 }
816
817 // End Apple code.
818
819 if ([textStr length] < WebKeyboardEvent::textLengthCap &&
820 [unmodifiedStr length] < WebKeyboardEvent::textLengthCap) {
821 [textStr getCharacters:&result.text[0]];
822 [unmodifiedStr getCharacters:&result.unmodifiedText[0]];
823 } else
824 ASSERT_NOT_REACHED();
825
826 [identifierStr getCString:&result.keyIdentifier[0]
827 maxLength:sizeof(result.keyIdentifier)
828 encoding:NSASCIIStringEncoding];
829
830 result.timeStampSeconds = [event timestamp];
831
832 // Windows and Linux set |isSystemKey| if alt is down. WebKit looks at this
833 // flag to decide if it should handle a key or not. E.g. alt-left/right
834 // shouldn't be used by WebKit to scroll the current page, because we want
835 // to get that key back for it to do history navigation. Hence, the
836 // corresponding situation on OS X is to set this for cmd key presses.
837 if (result.modifiers & WebInputEvent::MetaKey)
838 result.isSystemKey = true;
839
840 return result;
841 }
842
843 WebKeyboardEvent WebInputEventFactory::keyboardEvent(wchar_t character,
844 int modifiers,
845 double timeStampSeconds)
846 {
847 // keyboardEvent(NSEvent*) depends on the NSEvent object and
848 // it is hard to use it from methods of the NSTextInput protocol. For
849 // such methods, this function creates a WebInputEvent::Char event without
850 // using a NSEvent object.
851 WebKeyboardEvent result;
852 result.type = WebKit::WebInputEvent::Char;
853 result.timeStampSeconds = timeStampSeconds;
854 result.modifiers = modifiers;
855 result.windowsKeyCode = character;
856 result.nativeKeyCode = character;
857 result.text[0] = character;
858 result.unmodifiedText[0] = character;
859
860 // Windows and Linux set |isSystemKey| if alt is down. WebKit looks at this
861 // flag to decide if it should handle a key or not. E.g. alt-left/right
862 // shouldn't be used by WebKit to scroll the current page, because we want
863 // to get that key back for it to do history navigation. Hence, the
864 // corresponding situation on OS X is to set this for cmd key presses.
865 if (result.modifiers & WebInputEvent::MetaKey)
866 result.isSystemKey = true;
867
868 return result;
869 }
870
871 // WebMouseEvent --------------------------------------------------------------
872
873 WebMouseEvent WebInputEventFactory::mouseEvent(NSEvent* event, NSView* view)
874 {
875 WebMouseEvent result;
876
877 result.clickCount = 0;
878
879 switch ([event type]) {
880 case NSMouseExited:
881 result.type = WebInputEvent::MouseLeave;
882 result.button = WebMouseEvent::ButtonNone;
883 break;
884 case NSLeftMouseDown:
885 result.type = WebInputEvent::MouseDown;
886 result.clickCount = [event clickCount];
887 result.button = WebMouseEvent::ButtonLeft;
888 break;
889 case NSOtherMouseDown:
890 result.type = WebInputEvent::MouseDown;
891 result.clickCount = [event clickCount];
892 result.button = WebMouseEvent::ButtonMiddle;
893 break;
894 case NSRightMouseDown:
895 result.type = WebInputEvent::MouseDown;
896 result.clickCount = [event clickCount];
897 result.button = WebMouseEvent::ButtonRight;
898 break;
899 case NSLeftMouseUp:
900 result.type = WebInputEvent::MouseUp;
901 result.clickCount = [event clickCount];
902 result.button = WebMouseEvent::ButtonLeft;
903 break;
904 case NSOtherMouseUp:
905 result.type = WebInputEvent::MouseUp;
906 result.clickCount = [event clickCount];
907 result.button = WebMouseEvent::ButtonMiddle;
908 break;
909 case NSRightMouseUp:
910 result.type = WebInputEvent::MouseUp;
911 result.clickCount = [event clickCount];
912 result.button = WebMouseEvent::ButtonRight;
913 break;
914 case NSMouseMoved:
915 case NSMouseEntered:
916 result.type = WebInputEvent::MouseMove;
917 break;
918 case NSLeftMouseDragged:
919 result.type = WebInputEvent::MouseMove;
920 result.button = WebMouseEvent::ButtonLeft;
921 break;
922 case NSOtherMouseDragged:
923 result.type = WebInputEvent::MouseMove;
924 result.button = WebMouseEvent::ButtonMiddle;
925 break;
926 case NSRightMouseDragged:
927 result.type = WebInputEvent::MouseMove;
928 result.button = WebMouseEvent::ButtonRight;
929 break;
930 default:
931 ASSERT_NOT_REACHED();
932 }
933
934 setWebEventLocationFromEventInView(&result, event, view);
935
936 result.modifiers = modifiersFromEvent(event);
937
938 result.timeStampSeconds = [event timestamp];
939
940 return result;
941 }
942
943 // WebMouseWheelEvent ---------------------------------------------------------
944
945 static WebMouseWheelEvent::Phase phaseForNSEventPhase(NSEventPhase eventPhase)
946 {
947 uint32_t phase = WebMouseWheelEvent::PhaseNone;
948 if (eventPhase & NSEventPhaseBegan)
949 phase |= WebMouseWheelEvent::PhaseBegan;
950 if (eventPhase & NSEventPhaseStationary)
951 phase |= WebMouseWheelEvent::PhaseStationary;
952 if (eventPhase & NSEventPhaseChanged)
953 phase |= WebMouseWheelEvent::PhaseChanged;
954 if (eventPhase & NSEventPhaseEnded)
955 phase |= WebMouseWheelEvent::PhaseEnded;
956 if (eventPhase & NSEventPhaseCancelled)
957 phase |= WebMouseWheelEvent::PhaseCancelled;
958 if (eventPhase & NSEventPhaseMayBegin)
959 phase |= WebMouseWheelEvent::PhaseMayBegin;
960 return static_cast<WebMouseWheelEvent::Phase>(phase);
961 }
962
963 static WebMouseWheelEvent::Phase phaseForEvent(NSEvent *event)
964 {
965 if (![event respondsToSelector:@selector(phase)])
966 return WebMouseWheelEvent::PhaseNone;
967
968 NSEventPhase eventPhase = [event phase];
969 return phaseForNSEventPhase(eventPhase);
970 }
971
972 static WebMouseWheelEvent::Phase momentumPhaseForEvent(NSEvent *event)
973 {
974 if (![event respondsToSelector:@selector(momentumPhase)])
975 return WebMouseWheelEvent::PhaseNone;
976
977 NSEventPhase eventMomentumPhase = [event momentumPhase];
978 return phaseForNSEventPhase(eventMomentumPhase);
979 }
980
981 WebMouseWheelEvent WebInputEventFactory::mouseWheelEvent(NSEvent* event, NSView* view)
982 {
983 WebMouseWheelEvent result;
984
985 result.type = WebInputEvent::MouseWheel;
986 result.button = WebMouseEvent::ButtonNone;
987
988 result.modifiers = modifiersFromEvent(event);
989
990 setWebEventLocationFromEventInView(&result, event, view);
991
992 // Of Mice and Men
993 // ---------------
994 //
995 // There are three types of scroll data available on a scroll wheel CGEvent.
996 // Apple's documentation ([1]) is rather vague in their differences, and not
997 // terribly helpful in deciding which to use. This is what's really going on .
998 //
999 // First, these events behave very differently depending on whether a standa rd
1000 // wheel mouse is used (one that scrolls in discrete units) or a
1001 // trackpad/Mighty Mouse is used (which both provide continuous scrolling).
1002 // You must check to see which was used for the event by testing the
1003 // kCGScrollWheelEventIsContinuous field.
1004 //
1005 // Second, these events refer to "axes". Axis 1 is the y-axis, and axis 2 is
1006 // the x-axis.
1007 //
1008 // Third, there is a concept of mouse acceleration. Scrolling the same amoun t
1009 // of physical distance will give you different results logically depending on
1010 // whether you scrolled a little at a time or in one continuous motion. Some
1011 // fields account for this while others do not.
1012 //
1013 // Fourth, for trackpads there is a concept of chunkiness. When scrolling
1014 // continuously, events can be delivered in chunks. That is to say, lots of
1015 // scroll events with delta 0 will be delivered, and every so often an event
1016 // with a non-zero delta will be delivered, containing the accumulated delta s
1017 // from all the intermediate moves. [2]
1018 //
1019 // For notchy wheel mice (kCGScrollWheelEventIsContinuous == 0)
1020 // ------------------------------------------------------------
1021 //
1022 // kCGScrollWheelEventDeltaAxis*
1023 // This is the rawest of raw events. For each mouse notch you get a value of
1024 // +1/-1. This does not take acceleration into account and thus is less
1025 // useful for building UIs.
1026 //
1027 // kCGScrollWheelEventPointDeltaAxis*
1028 // This is smarter. In general, for each mouse notch you get a value of
1029 // +1/-1, but this _does_ take acceleration into account, so you will get
1030 // larger values on longer scrolls. This field would be ideal for building
1031 // UIs except for one nasty bug: when the shift key is pressed, this set o f
1032 // fields fails to move the value into the axis2 field (the other two type s
1033 // of data do). This wouldn't be so bad except for the fact that while the
1034 // number of axes is used in the creation of a CGScrollWheelEvent, there i s
1035 // no way to get that information out of the event once created.
1036 //
1037 // kCGScrollWheelEventFixedPtDeltaAxis*
1038 // This is a fixed value, and for each mouse notch you get a value of
1039 // +0.1/-0.1 (but, like above, scaled appropriately for acceleration). Thi s
1040 // value takes acceleration into account, and in fact is identical to the
1041 // results you get from -[NSEvent delta*]. (That is, if you linked on Tige r
1042 // or greater; see [2] for details.)
1043 //
1044 // A note about continuous devices
1045 // -------------------------------
1046 //
1047 // There are two devices that provide continuous scrolling events (trackpads
1048 // and Mighty Mouses) and they behave rather differently. The Mighty Mouse
1049 // behaves a lot like a regular mouse. There is no chunking, and the
1050 // FixedPtDelta values are the PointDelta values multiplied by 0.1. With the
1051 // trackpad, though, there is chunking. While the FixedPtDelta values are
1052 // reasonable (they occur about every fifth event but have values five times
1053 // larger than usual) the Delta values are unreasonable. They don't appear t o
1054 // accumulate properly.
1055 //
1056 // For continuous devices (kCGScrollWheelEventIsContinuous != 0)
1057 // -------------------------------------------------------------
1058 //
1059 // kCGScrollWheelEventDeltaAxis*
1060 // This provides values with no acceleration. With a trackpad, these value s
1061 // are chunked but each non-zero value does not appear to be cumulative.
1062 // This seems to be a bug.
1063 //
1064 // kCGScrollWheelEventPointDeltaAxis*
1065 // This provides values with acceleration. With a trackpad, these values a re
1066 // not chunked and are highly accurate.
1067 //
1068 // kCGScrollWheelEventFixedPtDeltaAxis*
1069 // This provides values with acceleration. With a trackpad, these values a re
1070 // chunked but unlike Delta events are properly cumulative.
1071 //
1072 // Summary
1073 // -------
1074 //
1075 // In general the best approach to take is: determine if the event is
1076 // continuous. If it is not, then use the FixedPtDelta events (or just stick
1077 // with Cocoa events). They provide both acceleration and proper horizontal
1078 // scrolling. If the event is continuous, then doing pixel scrolling with th e
1079 // PointDelta is the way to go. In general, avoid the Delta events. They're
1080 // the oldest (dating back to 10.4, before CGEvents were public) but they la ck
1081 // acceleration and precision, making them useful only in specific edge case s.
1082 //
1083 // References
1084 // ----------
1085 //
1086 // [1] <http://developer.apple.com/documentation/Carbon/Reference/QuartzEven tServicesRef/Reference/reference.html>
1087 // [2] <http://developer.apple.com/releasenotes/Cocoa/AppKitOlderNotes.html>
1088 // Scroll to the section headed "NSScrollWheel events".
1089 //
1090 // P.S. The "smooth scrolling" option in the system preferences is utterly
1091 // unrelated to any of this.
1092
1093 CGEventRef cgEvent = [event CGEvent];
1094 ASSERT(cgEvent);
1095
1096 // Wheel ticks are supposed to be raw, unaccelerated values, one per physica l
1097 // mouse wheel notch. The delta event is perfect for this (being a good
1098 // "specific edge case" as mentioned above). Trackpads, unfortunately, do
1099 // event chunking, and sending mousewheel events with 0 ticks causes some
1100 // websites to malfunction. Therefore, for all continuous input devices we u se
1101 // the point delta data instead, since we cannot distinguish trackpad data
1102 // from data from any other continuous device.
1103
1104 // Conversion between wheel delta amounts and number of pixels to scroll.
1105 static const double scrollbarPixelsPerCocoaTick = 40.0;
1106
1107 if (CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEventIsContinuous)) {
1108 result.deltaX = CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEvent PointDeltaAxis2);
1109 result.deltaY = CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEvent PointDeltaAxis1);
1110 result.wheelTicksX = result.deltaX / scrollbarPixelsPerCocoaTick;
1111 result.wheelTicksY = result.deltaY / scrollbarPixelsPerCocoaTick;
1112 result.hasPreciseScrollingDeltas = true;
1113 } else {
1114 result.deltaX = [event deltaX] * scrollbarPixelsPerCocoaTick;
1115 result.deltaY = [event deltaY] * scrollbarPixelsPerCocoaTick;
1116 result.wheelTicksY = CGEventGetIntegerValueField(cgEvent, kCGScrollWheel EventDeltaAxis1);
1117 result.wheelTicksX = CGEventGetIntegerValueField(cgEvent, kCGScrollWheel EventDeltaAxis2);
1118 }
1119
1120 result.timeStampSeconds = [event timestamp];
1121
1122 result.phase = phaseForEvent(event);
1123 result.momentumPhase = momentumPhaseForEvent(event);
1124
1125 return result;
1126 }
1127
1128 WebGestureEvent WebInputEventFactory::gestureEvent(NSEvent *event, NSView *view)
1129 {
1130 WebGestureEvent result;
1131
1132 // Use a temporary WebMouseEvent to get the location.
1133 WebMouseEvent temp;
1134
1135 setWebEventLocationFromEventInView(&temp, event, view);
1136 result.x = temp.x;
1137 result.y = temp.y;
1138 result.globalX = temp.globalX;
1139 result.globalY = temp.globalY;
1140
1141 result.type = gestureEventTypeForEvent(event);
1142 result.modifiers = modifiersFromEvent(event);
1143 result.timeStampSeconds = [event timestamp];
1144
1145 return result;
1146 }
1147
1148 } // namespace WebKit
OLDNEW
« no previous file with comments | « Source/web/gtk/WebInputEventFactory.cpp ('k') | Source/web/web.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698