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 3381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch#import "KeyEventCocoa.h" 34643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#include "WebInputEvent.h" 35643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#include <wtf/ASCIICType.h> 36643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 37643ca7872b450ea4efacab6188849e5aac2ba161Steve Blocknamespace WebKit { 38643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 39643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// WebKeyboardEvent ----------------------------------------------------------- 40643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 41643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// ---------------------------------------------------------------------------- 42643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// Begin Apple code, copied from KeyEventMac.mm 43643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// 44643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// We can share some of this code if we factored it out of KeyEventMac, but 45643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// the main problem is that it relies on the NSString ctor on String for 46643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// conversions, and since we're building without PLATFORM(MAC), we don't have 47643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// that. As a result we have to use NSString here exclusively and thus tweak 48643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// the code so it's not re-usable as-is. One possiblity would be to make the 49643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// upstream code only use NSString, but I'm not certain how far that change 50643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// would propagate. 51643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 52643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockstatic inline bool isKeyUpEvent(NSEvent* event) 53643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{ 54643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if ([event type] != NSFlagsChanged) 55643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return [event type] == NSKeyUp; 56643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // FIXME: This logic fails if the user presses both Shift keys at once, for example: 57643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // we treat releasing one of them as keyDown. 58643ca7872b450ea4efacab6188849e5aac2ba161Steve Block switch ([event keyCode]) { 59643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case 54: // Right Command 60643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case 55: // Left Command 61643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return ([event modifierFlags] & NSCommandKeyMask) == 0; 62643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 63643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case 57: // Capslock 64643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return ([event modifierFlags] & NSAlphaShiftKeyMask) == 0; 65643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 66643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case 56: // Left Shift 67643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case 60: // Right Shift 68643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return ([event modifierFlags] & NSShiftKeyMask) == 0; 69643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 70643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case 58: // Left Alt 71643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case 61: // Right Alt 72643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return ([event modifierFlags] & NSAlternateKeyMask) == 0; 73643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 74643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case 59: // Left Ctrl 75643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case 62: // Right Ctrl 76643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return ([event modifierFlags] & NSControlKeyMask) == 0; 77643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 78643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case 63: // Function 79643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return ([event modifierFlags] & NSFunctionKeyMask) == 0; 80643ca7872b450ea4efacab6188849e5aac2ba161Steve Block } 81643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return false; 82643ca7872b450ea4efacab6188849e5aac2ba161Steve Block} 83643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 84643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockstatic bool isKeypadEvent(NSEvent* event) 85643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{ 86643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // Check that this is the type of event that has a keyCode. 87643ca7872b450ea4efacab6188849e5aac2ba161Steve Block switch ([event type]) { 88643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSKeyDown: 89643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSKeyUp: 90643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSFlagsChanged: 91643ca7872b450ea4efacab6188849e5aac2ba161Steve Block break; 92643ca7872b450ea4efacab6188849e5aac2ba161Steve Block default: 93643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return false; 94643ca7872b450ea4efacab6188849e5aac2ba161Steve Block } 95643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 96d0825bca7fe65beaee391d30da42e937db621564Steve Block if ([event modifierFlags] & NSNumericPadKeyMask) 97d0825bca7fe65beaee391d30da42e937db621564Steve Block return true; 98d0825bca7fe65beaee391d30da42e937db621564Steve Block 99643ca7872b450ea4efacab6188849e5aac2ba161Steve Block switch ([event keyCode]) { 100643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case 71: // Clear 101643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case 81: // = 102643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case 75: // / 103643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case 67: // * 104643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case 78: // - 105643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case 69: // + 106643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case 76: // Enter 107643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case 65: // . 108643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case 82: // 0 109643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case 83: // 1 110643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case 84: // 2 111643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case 85: // 3 112643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case 86: // 4 113643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case 87: // 5 114643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case 88: // 6 115643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case 89: // 7 116643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case 91: // 8 117643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case 92: // 9 118643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return true; 119643ca7872b450ea4efacab6188849e5aac2ba161Steve Block } 120643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 121643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return false; 122643ca7872b450ea4efacab6188849e5aac2ba161Steve Block} 123643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 124643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockstatic int windowsKeyCodeForKeyEvent(NSEvent* event) 125643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{ 12681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch int code = 0; 12781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch // There are several kinds of characters for which we produce key code from char code: 12881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch // 1. Roman letters. Windows keyboard layouts affect both virtual key codes and character codes for these, 12981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch // so e.g. 'A' gets the same keyCode on QWERTY, AZERTY or Dvorak layouts. 13081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch // 2. Keys for which there is no known Mac virtual key codes, like PrintScreen. 13181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch // 3. Certain punctuation keys. On Windows, these are also remapped depending on current keyboard layout, 13281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch // but see comment in windowsKeyCodeForCharCode(). 13381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch if ([event type] == NSKeyDown || [event type] == NSKeyUp) { 13481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch // Cmd switches Roman letters for Dvorak-QWERTY layout, so try modified characters first. 13581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch NSString* s = [event characters]; 13681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch code = [s length] > 0 ? WebCore::windowsKeyCodeForCharCode([s characterAtIndex:0]) : 0; 13781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch if (code) 13881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch return code; 13981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 14081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch // Ctrl+A on an AZERTY keyboard would get VK_Q keyCode if we relied on -[NSEvent keyCode] below. 14181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch s = [event charactersIgnoringModifiers]; 14281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch code = [s length] > 0 ? WebCore::windowsKeyCodeForCharCode([s characterAtIndex:0]) : 0; 14381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch if (code) 14481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch return code; 145643ca7872b450ea4efacab6188849e5aac2ba161Steve Block } 146643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 14781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch // Map Mac virtual key code directly to Windows one for any keys not handled above. 14881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch // E.g. the key next to Caps Lock has the same Event.keyCode on U.S. keyboard ('A') and on Russian keyboard (CYRILLIC LETTER EF). 14981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch return WebCore::windowsKeyCodeForKeyCode([event keyCode]); 150643ca7872b450ea4efacab6188849e5aac2ba161Steve Block} 151643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 152643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockstatic inline NSString* textFromEvent(NSEvent* event) 153643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{ 154643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if ([event type] == NSFlagsChanged) 155643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @""; 156643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return [event characters]; 157643ca7872b450ea4efacab6188849e5aac2ba161Steve Block} 158643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 159643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockstatic inline NSString* unmodifiedTextFromEvent(NSEvent* event) 160643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{ 161643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if ([event type] == NSFlagsChanged) 162643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @""; 163643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return [event charactersIgnoringModifiers]; 164643ca7872b450ea4efacab6188849e5aac2ba161Steve Block} 165643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 166643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockstatic NSString* keyIdentifierForKeyEvent(NSEvent* event) 167643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{ 168643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if ([event type] == NSFlagsChanged) { 169643ca7872b450ea4efacab6188849e5aac2ba161Steve Block switch ([event keyCode]) { 170643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case 54: // Right Command 171643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case 55: // Left Command 172643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"Meta"; 173643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 174643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case 57: // Capslock 175643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"CapsLock"; 176643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 177643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case 56: // Left Shift 178643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case 60: // Right Shift 179643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"Shift"; 180643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 181643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case 58: // Left Alt 182643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case 61: // Right Alt 183643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"Alt"; 184643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 185643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case 59: // Left Ctrl 186643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case 62: // Right Ctrl 187643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"Control"; 188643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 189643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// Begin non-Apple addition/modification -------------------------------------- 190643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case 63: // Function 191643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"Function"; 192643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 193643ca7872b450ea4efacab6188849e5aac2ba161Steve Block default: // Unknown, but this may be a strange/new keyboard. 194643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"Unidentified"; 195643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// End non-Apple addition/modification ---------------------------------------- 196643ca7872b450ea4efacab6188849e5aac2ba161Steve Block } 197643ca7872b450ea4efacab6188849e5aac2ba161Steve Block } 198643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 199643ca7872b450ea4efacab6188849e5aac2ba161Steve Block NSString* s = [event charactersIgnoringModifiers]; 200643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if ([s length] != 1) 201643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"Unidentified"; 202643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 203643ca7872b450ea4efacab6188849e5aac2ba161Steve Block unichar c = [s characterAtIndex:0]; 204643ca7872b450ea4efacab6188849e5aac2ba161Steve Block switch (c) { 205643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // Each identifier listed in the DOM spec is listed here. 206643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // Many are simply commented out since they do not appear on standard Macintosh keyboards 207643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // or are on a key that doesn't have a corresponding character. 208643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 209643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "Accept" 210643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "AllCandidates" 211643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 212643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "Alt" 213643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSMenuFunctionKey: 214643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"Alt"; 215643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 216643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "Apps" 217643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "BrowserBack" 218643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "BrowserForward" 219643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "BrowserHome" 220643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "BrowserRefresh" 221643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "BrowserSearch" 222643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "BrowserStop" 223643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "CapsLock" 224643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 225643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "Clear" 226643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSClearLineFunctionKey: 227643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"Clear"; 228643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 229643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "CodeInput" 230643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "Compose" 231643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "Control" 232643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "Crsel" 233643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "Convert" 234643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "Copy" 235643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "Cut" 236643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 237643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "Down" 238643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSDownArrowFunctionKey: 239643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"Down"; 240643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "End" 241643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSEndFunctionKey: 242643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"End"; 243643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "Enter" 244643ca7872b450ea4efacab6188849e5aac2ba161Steve 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 245643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"Enter"; 246643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 247643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "EraseEof" 248643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 249643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "Execute" 250643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSExecuteFunctionKey: 251643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"Execute"; 252643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 253643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "Exsel" 254643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 255643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "F1" 256643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSF1FunctionKey: 257643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"F1"; 258643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "F2" 259643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSF2FunctionKey: 260643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"F2"; 261643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "F3" 262643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSF3FunctionKey: 263643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"F3"; 264643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "F4" 265643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSF4FunctionKey: 266643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"F4"; 267643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "F5" 268643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSF5FunctionKey: 269643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"F5"; 270643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "F6" 271643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSF6FunctionKey: 272643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"F6"; 273643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "F7" 274643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSF7FunctionKey: 275643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"F7"; 276643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "F8" 277643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSF8FunctionKey: 278643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"F8"; 279643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "F9" 280643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSF9FunctionKey: 281643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"F9"; 282643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "F10" 283643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSF10FunctionKey: 284643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"F10"; 285643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "F11" 286643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSF11FunctionKey: 287643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"F11"; 288643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "F12" 289643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSF12FunctionKey: 290643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"F12"; 291643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "F13" 292643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSF13FunctionKey: 293643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"F13"; 294643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "F14" 295643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSF14FunctionKey: 296643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"F14"; 297643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "F15" 298643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSF15FunctionKey: 299643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"F15"; 300643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "F16" 301643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSF16FunctionKey: 302643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"F16"; 303643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "F17" 304643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSF17FunctionKey: 305643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"F17"; 306643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "F18" 307643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSF18FunctionKey: 308643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"F18"; 309643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "F19" 310643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSF19FunctionKey: 311643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"F19"; 312643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "F20" 313643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSF20FunctionKey: 314643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"F20"; 315643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "F21" 316643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSF21FunctionKey: 317643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"F21"; 318643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "F22" 319643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSF22FunctionKey: 320643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"F22"; 321643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "F23" 322643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSF23FunctionKey: 323643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"F23"; 324643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "F24" 325643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSF24FunctionKey: 326643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"F24"; 327643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 328643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "FinalMode" 329643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 330643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "Find" 331643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSFindFunctionKey: 332643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"Find"; 333643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 334643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "FullWidth" 335643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "HalfWidth" 336643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "HangulMode" 337643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "HanjaMode" 338643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 339643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "Help" 340643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSHelpFunctionKey: 341643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"Help"; 342643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 343643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "Hiragana" 344643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 345643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "Home" 346643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSHomeFunctionKey: 347643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"Home"; 348643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "Insert" 349643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSInsertFunctionKey: 350643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"Insert"; 351643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 352643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "JapaneseHiragana" 353643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "JapaneseKatakana" 354643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "JapaneseRomaji" 355643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "JunjaMode" 356643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "KanaMode" 357643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "KanjiMode" 358643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "Katakana" 359643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "LaunchApplication1" 360643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "LaunchApplication2" 361643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "LaunchMail" 362643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 363643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "Left" 364643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSLeftArrowFunctionKey: 365643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"Left"; 366643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 367643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "Meta" 368643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "MediaNextTrack" 369643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "MediaPlayPause" 370643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "MediaPreviousTrack" 371643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "MediaStop" 372643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 373643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "ModeChange" 374643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSModeSwitchFunctionKey: 375643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"ModeChange"; 376643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 377643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "Nonconvert" 378643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "NumLock" 379643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 380643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "PageDown" 381643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSPageDownFunctionKey: 382643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"PageDown"; 383643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "PageUp" 384643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSPageUpFunctionKey: 385643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"PageUp"; 386643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 387643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "Paste" 388643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 389643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "Pause" 390643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSPauseFunctionKey: 391643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"Pause"; 392643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 393643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "Play" 394643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "PreviousCandidate" 395643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 396643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "PrintScreen" 397643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSPrintScreenFunctionKey: 398643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"PrintScreen"; 399643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 400643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "Process" 401643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "Props" 402643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 403643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "Right" 404643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSRightArrowFunctionKey: 405643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"Right"; 406643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 407643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "RomanCharacters" 408643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 409643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "Scroll" 410643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSScrollLockFunctionKey: 411643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"Scroll"; 412643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "Select" 413643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSSelectFunctionKey: 414643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"Select"; 415643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 416643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "SelectMedia" 417643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "Shift" 418643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 419643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "Stop" 420643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSStopFunctionKey: 421643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"Stop"; 422643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "Up" 423643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSUpArrowFunctionKey: 424643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"Up"; 425643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "Undo" 426643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSUndoFunctionKey: 427643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"Undo"; 428643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 429643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "VolumeDown" 430643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "VolumeMute" 431643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "VolumeUp" 432643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "Win" 433643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "Zoom" 434643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 435643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // More function keys, not in the key identifier specification. 436643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSF25FunctionKey: 437643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"F25"; 438643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSF26FunctionKey: 439643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"F26"; 440643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSF27FunctionKey: 441643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"F27"; 442643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSF28FunctionKey: 443643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"F28"; 444643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSF29FunctionKey: 445643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"F29"; 446643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSF30FunctionKey: 447643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"F30"; 448643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSF31FunctionKey: 449643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"F31"; 450643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSF32FunctionKey: 451643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"F32"; 452643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSF33FunctionKey: 453643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"F33"; 454643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSF34FunctionKey: 455643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"F34"; 456643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSF35FunctionKey: 457643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"F35"; 458643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 459643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // Turn 0x7F into 0x08, because backspace needs to always be 0x08. 460643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case 0x7F: 461643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"U+0008"; 462643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // Standard says that DEL becomes U+007F. 463643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSDeleteFunctionKey: 464643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"U+007F"; 465643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 466643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // Always use 0x09 for tab instead of AppKit's backtab character. 467643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSBackTabCharacter: 468643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return @"U+0009"; 469643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 470643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSBeginFunctionKey: 471643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSBreakFunctionKey: 472643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSClearDisplayFunctionKey: 473643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSDeleteCharFunctionKey: 474643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSDeleteLineFunctionKey: 475643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSInsertCharFunctionKey: 476643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSInsertLineFunctionKey: 477643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSNextFunctionKey: 478643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSPrevFunctionKey: 479643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSPrintFunctionKey: 480643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSRedoFunctionKey: 481643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSResetFunctionKey: 482643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSSysReqFunctionKey: 483643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSSystemFunctionKey: 484643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSUserFunctionKey: 485643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // FIXME: We should use something other than the vendor-area Unicode values for the above keys. 486643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // For now, just fall through to the default. 487643ca7872b450ea4efacab6188849e5aac2ba161Steve Block default: 488643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return [NSString stringWithFormat:@"U+%04X", WTF::toASCIIUpper(c)]; 489643ca7872b450ea4efacab6188849e5aac2ba161Steve Block } 490643ca7872b450ea4efacab6188849e5aac2ba161Steve Block} 491643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 492643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// End Apple code. 493643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// ---------------------------------------------------------------------------- 494643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 495643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockstatic inline int modifiersFromEvent(NSEvent* event) { 496643ca7872b450ea4efacab6188849e5aac2ba161Steve Block int modifiers = 0; 497643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 498643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if ([event modifierFlags] & NSControlKeyMask) 499643ca7872b450ea4efacab6188849e5aac2ba161Steve Block modifiers |= WebInputEvent::ControlKey; 500643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if ([event modifierFlags] & NSShiftKeyMask) 501643ca7872b450ea4efacab6188849e5aac2ba161Steve Block modifiers |= WebInputEvent::ShiftKey; 502643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if ([event modifierFlags] & NSAlternateKeyMask) 503643ca7872b450ea4efacab6188849e5aac2ba161Steve Block modifiers |= WebInputEvent::AltKey; 504643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if ([event modifierFlags] & NSCommandKeyMask) 505643ca7872b450ea4efacab6188849e5aac2ba161Steve Block modifiers |= WebInputEvent::MetaKey; 506e14391e94c850b8bd03680c23b38978db68687a8John Reck if ([event modifierFlags] & NSAlphaShiftKeyMask) 507e14391e94c850b8bd03680c23b38978db68687a8John Reck modifiers |= WebInputEvent::CapsLockOn; 508643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // TODO(port): Set mouse button states 509643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 510643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return modifiers; 511643ca7872b450ea4efacab6188849e5aac2ba161Steve Block} 512643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 513dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockstatic inline void setWebEventLocationFromEventInView(WebMouseEvent* result, 514dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block NSEvent* event, 515dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block NSView* view) { 516dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block NSPoint windowLocal = [event locationInWindow]; 517dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 518dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block NSPoint screenLocal = [[view window] convertBaseToScreen:windowLocal]; 519dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block result->globalX = screenLocal.x; 520dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // Flip y. 521dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block NSScreen* primaryScreen = ([[NSScreen screens] count] > 0) ? 522dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block [[NSScreen screens] objectAtIndex:0] : nil; 523dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (primaryScreen) 524dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block result->globalY = [primaryScreen frame].size.height - screenLocal.y; 525dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block else 526dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block result->globalY = screenLocal.y; 527dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 528dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block NSPoint contentLocal = [view convertPoint:windowLocal fromView:nil]; 529dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block result->x = contentLocal.x; 530dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block result->y = [view frame].size.height - contentLocal.y; // Flip y. 531dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 532dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block result->windowX = result->x; 533dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block result->windowY = result->y; 534dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} 535dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 536643ca7872b450ea4efacab6188849e5aac2ba161Steve BlockWebKeyboardEvent WebInputEventFactory::keyboardEvent(NSEvent* event) 537643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{ 538643ca7872b450ea4efacab6188849e5aac2ba161Steve Block WebKeyboardEvent result; 539643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 540643ca7872b450ea4efacab6188849e5aac2ba161Steve Block result.type = 541643ca7872b450ea4efacab6188849e5aac2ba161Steve Block isKeyUpEvent(event) ? WebInputEvent::KeyUp : WebInputEvent::RawKeyDown; 542643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 543643ca7872b450ea4efacab6188849e5aac2ba161Steve Block result.modifiers = modifiersFromEvent(event); 544643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 545643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if (isKeypadEvent(event)) 546643ca7872b450ea4efacab6188849e5aac2ba161Steve Block result.modifiers |= WebInputEvent::IsKeyPad; 547643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 548643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if (([event type] != NSFlagsChanged) && [event isARepeat]) 549643ca7872b450ea4efacab6188849e5aac2ba161Steve Block result.modifiers |= WebInputEvent::IsAutoRepeat; 550643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 551643ca7872b450ea4efacab6188849e5aac2ba161Steve Block result.windowsKeyCode = windowsKeyCodeForKeyEvent(event); 552643ca7872b450ea4efacab6188849e5aac2ba161Steve Block result.nativeKeyCode = [event keyCode]; 553643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 554643ca7872b450ea4efacab6188849e5aac2ba161Steve Block NSString* textStr = textFromEvent(event); 555643ca7872b450ea4efacab6188849e5aac2ba161Steve Block NSString* unmodifiedStr = unmodifiedTextFromEvent(event); 556643ca7872b450ea4efacab6188849e5aac2ba161Steve Block NSString* identifierStr = keyIdentifierForKeyEvent(event); 557643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 558643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // Begin Apple code, copied from KeyEventMac.mm 559643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 560643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // Always use 13 for Enter/Return -- we don't want to use AppKit's 561643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // different character for Enter. 562643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if (result.windowsKeyCode == '\r') { 563643ca7872b450ea4efacab6188849e5aac2ba161Steve Block textStr = @"\r"; 564643ca7872b450ea4efacab6188849e5aac2ba161Steve Block unmodifiedStr = @"\r"; 565643ca7872b450ea4efacab6188849e5aac2ba161Steve Block } 566643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 567643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // The adjustments below are only needed in backward compatibility mode, 568643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // but we cannot tell what mode we are in from here. 569643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 570643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // Turn 0x7F into 8, because backspace needs to always be 8. 571643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if ([textStr isEqualToString:@"\x7F"]) 572643ca7872b450ea4efacab6188849e5aac2ba161Steve Block textStr = @"\x8"; 573643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if ([unmodifiedStr isEqualToString:@"\x7F"]) 574643ca7872b450ea4efacab6188849e5aac2ba161Steve Block unmodifiedStr = @"\x8"; 575643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // Always use 9 for tab -- we don't want to use AppKit's different character 576643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // for shift-tab. 577643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if (result.windowsKeyCode == 9) { 578643ca7872b450ea4efacab6188849e5aac2ba161Steve Block textStr = @"\x9"; 579643ca7872b450ea4efacab6188849e5aac2ba161Steve Block unmodifiedStr = @"\x9"; 580643ca7872b450ea4efacab6188849e5aac2ba161Steve Block } 581643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 582643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // End Apple code. 583643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 584643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if ([textStr length] < WebKeyboardEvent::textLengthCap && 585643ca7872b450ea4efacab6188849e5aac2ba161Steve Block [unmodifiedStr length] < WebKeyboardEvent::textLengthCap) { 586643ca7872b450ea4efacab6188849e5aac2ba161Steve Block [textStr getCharacters:&result.text[0]]; 587643ca7872b450ea4efacab6188849e5aac2ba161Steve Block [unmodifiedStr getCharacters:&result.unmodifiedText[0]]; 588643ca7872b450ea4efacab6188849e5aac2ba161Steve Block } else 589643ca7872b450ea4efacab6188849e5aac2ba161Steve Block ASSERT_NOT_REACHED(); 590643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 591643ca7872b450ea4efacab6188849e5aac2ba161Steve Block [identifierStr getCString:&result.keyIdentifier[0] 592643ca7872b450ea4efacab6188849e5aac2ba161Steve Block maxLength:sizeof(result.keyIdentifier) 593643ca7872b450ea4efacab6188849e5aac2ba161Steve Block encoding:NSASCIIStringEncoding]; 594643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 595643ca7872b450ea4efacab6188849e5aac2ba161Steve Block result.timeStampSeconds = [event timestamp]; 596643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 597643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // Windows and Linux set |isSystemKey| if alt is down. WebKit looks at this 598643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // flag to decide if it should handle a key or not. E.g. alt-left/right 599643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // shouldn't be used by WebKit to scroll the current page, because we want 600643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // to get that key back for it to do history navigation. Hence, the 601643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // corresponding situation on OS X is to set this for cmd key presses. 602643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if (result.modifiers & WebInputEvent::MetaKey) 603643ca7872b450ea4efacab6188849e5aac2ba161Steve Block result.isSystemKey = true; 604643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 605643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return result; 606643ca7872b450ea4efacab6188849e5aac2ba161Steve Block} 607643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 608643ca7872b450ea4efacab6188849e5aac2ba161Steve BlockWebKeyboardEvent WebInputEventFactory::keyboardEvent(wchar_t character, 609643ca7872b450ea4efacab6188849e5aac2ba161Steve Block int modifiers, 610643ca7872b450ea4efacab6188849e5aac2ba161Steve Block double timeStampSeconds) 611643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{ 612643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // keyboardEvent(NSEvent*) depends on the NSEvent object and 613643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // it is hard to use it from methods of the NSTextInput protocol. For 614643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // such methods, this function creates a WebInputEvent::Char event without 615643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // using a NSEvent object. 616643ca7872b450ea4efacab6188849e5aac2ba161Steve Block WebKeyboardEvent result; 617643ca7872b450ea4efacab6188849e5aac2ba161Steve Block result.type = WebKit::WebInputEvent::Char; 618643ca7872b450ea4efacab6188849e5aac2ba161Steve Block result.timeStampSeconds = timeStampSeconds; 619643ca7872b450ea4efacab6188849e5aac2ba161Steve Block result.modifiers = modifiers; 620643ca7872b450ea4efacab6188849e5aac2ba161Steve Block result.windowsKeyCode = character; 621643ca7872b450ea4efacab6188849e5aac2ba161Steve Block result.nativeKeyCode = character; 622643ca7872b450ea4efacab6188849e5aac2ba161Steve Block result.text[0] = character; 623643ca7872b450ea4efacab6188849e5aac2ba161Steve Block result.unmodifiedText[0] = character; 624643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 625643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // Windows and Linux set |isSystemKey| if alt is down. WebKit looks at this 626643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // flag to decide if it should handle a key or not. E.g. alt-left/right 627643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // shouldn't be used by WebKit to scroll the current page, because we want 628643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // to get that key back for it to do history navigation. Hence, the 629643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // corresponding situation on OS X is to set this for cmd key presses. 630643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if (result.modifiers & WebInputEvent::MetaKey) 631643ca7872b450ea4efacab6188849e5aac2ba161Steve Block result.isSystemKey = true; 632643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 633643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return result; 634643ca7872b450ea4efacab6188849e5aac2ba161Steve Block} 635643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 636643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// WebMouseEvent -------------------------------------------------------------- 637643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 638643ca7872b450ea4efacab6188849e5aac2ba161Steve BlockWebMouseEvent WebInputEventFactory::mouseEvent(NSEvent* event, NSView* view) 639643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{ 640643ca7872b450ea4efacab6188849e5aac2ba161Steve Block WebMouseEvent result; 641643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 642643ca7872b450ea4efacab6188849e5aac2ba161Steve Block result.clickCount = 0; 643643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 644643ca7872b450ea4efacab6188849e5aac2ba161Steve Block switch ([event type]) { 645643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSMouseExited: 646643ca7872b450ea4efacab6188849e5aac2ba161Steve Block result.type = WebInputEvent::MouseLeave; 647643ca7872b450ea4efacab6188849e5aac2ba161Steve Block result.button = WebMouseEvent::ButtonNone; 648643ca7872b450ea4efacab6188849e5aac2ba161Steve Block break; 649643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSLeftMouseDown: 650643ca7872b450ea4efacab6188849e5aac2ba161Steve Block result.type = WebInputEvent::MouseDown; 651643ca7872b450ea4efacab6188849e5aac2ba161Steve Block result.clickCount = [event clickCount]; 652643ca7872b450ea4efacab6188849e5aac2ba161Steve Block result.button = WebMouseEvent::ButtonLeft; 653643ca7872b450ea4efacab6188849e5aac2ba161Steve Block break; 654643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSOtherMouseDown: 655643ca7872b450ea4efacab6188849e5aac2ba161Steve Block result.type = WebInputEvent::MouseDown; 656643ca7872b450ea4efacab6188849e5aac2ba161Steve Block result.clickCount = [event clickCount]; 657643ca7872b450ea4efacab6188849e5aac2ba161Steve Block result.button = WebMouseEvent::ButtonMiddle; 658643ca7872b450ea4efacab6188849e5aac2ba161Steve Block break; 659643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSRightMouseDown: 660643ca7872b450ea4efacab6188849e5aac2ba161Steve Block result.type = WebInputEvent::MouseDown; 661643ca7872b450ea4efacab6188849e5aac2ba161Steve Block result.clickCount = [event clickCount]; 662643ca7872b450ea4efacab6188849e5aac2ba161Steve Block result.button = WebMouseEvent::ButtonRight; 663643ca7872b450ea4efacab6188849e5aac2ba161Steve Block break; 664643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSLeftMouseUp: 665643ca7872b450ea4efacab6188849e5aac2ba161Steve Block result.type = WebInputEvent::MouseUp; 6666b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner result.clickCount = [event clickCount]; 667643ca7872b450ea4efacab6188849e5aac2ba161Steve Block result.button = WebMouseEvent::ButtonLeft; 668643ca7872b450ea4efacab6188849e5aac2ba161Steve Block break; 669643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSOtherMouseUp: 670643ca7872b450ea4efacab6188849e5aac2ba161Steve Block result.type = WebInputEvent::MouseUp; 6716b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner result.clickCount = [event clickCount]; 672643ca7872b450ea4efacab6188849e5aac2ba161Steve Block result.button = WebMouseEvent::ButtonMiddle; 673643ca7872b450ea4efacab6188849e5aac2ba161Steve Block break; 674643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSRightMouseUp: 675643ca7872b450ea4efacab6188849e5aac2ba161Steve Block result.type = WebInputEvent::MouseUp; 6766b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner result.clickCount = [event clickCount]; 677643ca7872b450ea4efacab6188849e5aac2ba161Steve Block result.button = WebMouseEvent::ButtonRight; 678643ca7872b450ea4efacab6188849e5aac2ba161Steve Block break; 679643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSMouseMoved: 680643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSMouseEntered: 681643ca7872b450ea4efacab6188849e5aac2ba161Steve Block result.type = WebInputEvent::MouseMove; 682643ca7872b450ea4efacab6188849e5aac2ba161Steve Block break; 683643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSLeftMouseDragged: 684643ca7872b450ea4efacab6188849e5aac2ba161Steve Block result.type = WebInputEvent::MouseMove; 685643ca7872b450ea4efacab6188849e5aac2ba161Steve Block result.button = WebMouseEvent::ButtonLeft; 686643ca7872b450ea4efacab6188849e5aac2ba161Steve Block break; 687643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSOtherMouseDragged: 688643ca7872b450ea4efacab6188849e5aac2ba161Steve Block result.type = WebInputEvent::MouseMove; 689643ca7872b450ea4efacab6188849e5aac2ba161Steve Block result.button = WebMouseEvent::ButtonMiddle; 690643ca7872b450ea4efacab6188849e5aac2ba161Steve Block break; 691643ca7872b450ea4efacab6188849e5aac2ba161Steve Block case NSRightMouseDragged: 692643ca7872b450ea4efacab6188849e5aac2ba161Steve Block result.type = WebInputEvent::MouseMove; 693643ca7872b450ea4efacab6188849e5aac2ba161Steve Block result.button = WebMouseEvent::ButtonRight; 694643ca7872b450ea4efacab6188849e5aac2ba161Steve Block break; 695643ca7872b450ea4efacab6188849e5aac2ba161Steve Block default: 696643ca7872b450ea4efacab6188849e5aac2ba161Steve Block ASSERT_NOT_REACHED(); 697643ca7872b450ea4efacab6188849e5aac2ba161Steve Block } 698643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 699dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block setWebEventLocationFromEventInView(&result, event, view); 700643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 701643ca7872b450ea4efacab6188849e5aac2ba161Steve Block result.modifiers = modifiersFromEvent(event); 702643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 703643ca7872b450ea4efacab6188849e5aac2ba161Steve Block result.timeStampSeconds = [event timestamp]; 704643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 705643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return result; 706643ca7872b450ea4efacab6188849e5aac2ba161Steve Block} 707643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 708643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// WebMouseWheelEvent --------------------------------------------------------- 709643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 710643ca7872b450ea4efacab6188849e5aac2ba161Steve BlockWebMouseWheelEvent WebInputEventFactory::mouseWheelEvent(NSEvent* event, NSView* view) 711643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{ 712643ca7872b450ea4efacab6188849e5aac2ba161Steve Block WebMouseWheelEvent result; 713643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 714643ca7872b450ea4efacab6188849e5aac2ba161Steve Block result.type = WebInputEvent::MouseWheel; 715643ca7872b450ea4efacab6188849e5aac2ba161Steve Block result.button = WebMouseEvent::ButtonNone; 716643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 717643ca7872b450ea4efacab6188849e5aac2ba161Steve Block result.modifiers = modifiersFromEvent(event); 718643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 719dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block setWebEventLocationFromEventInView(&result, event, view); 720643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 721643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // Of Mice and Men 722643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // --------------- 723643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // 724643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // There are three types of scroll data available on a scroll wheel CGEvent. 725643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // Apple's documentation ([1]) is rather vague in their differences, and not 726643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // terribly helpful in deciding which to use. This is what's really going on. 727643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // 728643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // First, these events behave very differently depending on whether a standard 729643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // wheel mouse is used (one that scrolls in discrete units) or a 730643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // trackpad/Mighty Mouse is used (which both provide continuous scrolling). 731643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // You must check to see which was used for the event by testing the 732643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // kCGScrollWheelEventIsContinuous field. 733643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // 734643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // Second, these events refer to "axes". Axis 1 is the y-axis, and axis 2 is 735643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // the x-axis. 736643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // 737643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // Third, there is a concept of mouse acceleration. Scrolling the same amount 738643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // of physical distance will give you different results logically depending on 739643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // whether you scrolled a little at a time or in one continuous motion. Some 740643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // fields account for this while others do not. 741643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // 742643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // Fourth, for trackpads there is a concept of chunkiness. When scrolling 743643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // continuously, events can be delivered in chunks. That is to say, lots of 744643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // scroll events with delta 0 will be delivered, and every so often an event 745643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // with a non-zero delta will be delivered, containing the accumulated deltas 746643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // from all the intermediate moves. [2] 747643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // 748643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // For notchy wheel mice (kCGScrollWheelEventIsContinuous == 0) 749643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // ------------------------------------------------------------ 750643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // 751643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // kCGScrollWheelEventDeltaAxis* 752643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // This is the rawest of raw events. For each mouse notch you get a value of 753643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // +1/-1. This does not take acceleration into account and thus is less 754643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // useful for building UIs. 755643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // 756643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // kCGScrollWheelEventPointDeltaAxis* 757643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // This is smarter. In general, for each mouse notch you get a value of 758643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // +1/-1, but this _does_ take acceleration into account, so you will get 759643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // larger values on longer scrolls. This field would be ideal for building 760643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // UIs except for one nasty bug: when the shift key is pressed, this set of 761643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // fields fails to move the value into the axis2 field (the other two types 762643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // of data do). This wouldn't be so bad except for the fact that while the 763643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // number of axes is used in the creation of a CGScrollWheelEvent, there is 764643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // no way to get that information out of the event once created. 765643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // 766643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // kCGScrollWheelEventFixedPtDeltaAxis* 767643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // This is a fixed value, and for each mouse notch you get a value of 768643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // +0.1/-0.1 (but, like above, scaled appropriately for acceleration). This 769643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // value takes acceleration into account, and in fact is identical to the 770643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // results you get from -[NSEvent delta*]. (That is, if you linked on Tiger 771643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // or greater; see [2] for details.) 772643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // 773643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // A note about continuous devices 774643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // ------------------------------- 775643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // 776643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // There are two devices that provide continuous scrolling events (trackpads 777643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // and Mighty Mouses) and they behave rather differently. The Mighty Mouse 778643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // behaves a lot like a regular mouse. There is no chunking, and the 779643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // FixedPtDelta values are the PointDelta values multiplied by 0.1. With the 780643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // trackpad, though, there is chunking. While the FixedPtDelta values are 781643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // reasonable (they occur about every fifth event but have values five times 782643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // larger than usual) the Delta values are unreasonable. They don't appear to 783643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // accumulate properly. 784643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // 785643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // For continuous devices (kCGScrollWheelEventIsContinuous != 0) 786643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // ------------------------------------------------------------- 787643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // 788643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // kCGScrollWheelEventDeltaAxis* 789643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // This provides values with no acceleration. With a trackpad, these values 790643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // are chunked but each non-zero value does not appear to be cumulative. 791643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // This seems to be a bug. 792643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // 793643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // kCGScrollWheelEventPointDeltaAxis* 794643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // This provides values with acceleration. With a trackpad, these values are 795643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // not chunked and are highly accurate. 796643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // 797643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // kCGScrollWheelEventFixedPtDeltaAxis* 798643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // This provides values with acceleration. With a trackpad, these values are 799643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // chunked but unlike Delta events are properly cumulative. 800643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // 801643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // Summary 802643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // ------- 803643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // 804643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // In general the best approach to take is: determine if the event is 805643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // continuous. If it is not, then use the FixedPtDelta events (or just stick 806643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // with Cocoa events). They provide both acceleration and proper horizontal 807643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // scrolling. If the event is continuous, then doing pixel scrolling with the 808643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // PointDelta is the way to go. In general, avoid the Delta events. They're 809643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // the oldest (dating back to 10.4, before CGEvents were public) but they lack 810643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // acceleration and precision, making them useful only in specific edge cases. 811643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // 812643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // References 813643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // ---------- 814643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // 815643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // [1] <http://developer.apple.com/documentation/Carbon/Reference/QuartzEventServicesRef/Reference/reference.html> 816643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // [2] <http://developer.apple.com/releasenotes/Cocoa/AppKitOlderNotes.html> 817643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // Scroll to the section headed "NSScrollWheel events". 818643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // 819643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // P.S. The "smooth scrolling" option in the system preferences is utterly 820643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // unrelated to any of this. 821643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 822643ca7872b450ea4efacab6188849e5aac2ba161Steve Block CGEventRef cgEvent = [event CGEvent]; 823643ca7872b450ea4efacab6188849e5aac2ba161Steve Block ASSERT(cgEvent); 824643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 825643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // Wheel ticks are supposed to be raw, unaccelerated values, one per physical 826643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // mouse wheel notch. The delta event is perfect for this (being a good 827643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // "specific edge case" as mentioned above). Trackpads, unfortunately, do 828643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // event chunking, and sending mousewheel events with 0 ticks causes some 829643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // websites to malfunction. Therefore, for all continuous input devices we use 830643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // the point delta data instead, since we cannot distinguish trackpad data 831643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // from data from any other continuous device. 832643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 8335abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick // Conversion between wheel delta amounts and number of pixels to scroll. 8345abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick static const double scrollbarPixelsPerCocoaTick = 40.0; 8355abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick 836643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if (CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEventIsContinuous)) { 8375abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick result.deltaX = CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEventPointDeltaAxis2); 8385abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick result.deltaY = CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEventPointDeltaAxis1); 8395abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick result.wheelTicksX = result.deltaX / scrollbarPixelsPerCocoaTick; 8405abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick result.wheelTicksY = result.deltaY / scrollbarPixelsPerCocoaTick; 841643ca7872b450ea4efacab6188849e5aac2ba161Steve Block } else { 842643ca7872b450ea4efacab6188849e5aac2ba161Steve Block result.deltaX = [event deltaX] * scrollbarPixelsPerCocoaTick; 843643ca7872b450ea4efacab6188849e5aac2ba161Steve Block result.deltaY = [event deltaY] * scrollbarPixelsPerCocoaTick; 8445abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick result.wheelTicksY = CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEventDeltaAxis1); 8455abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick result.wheelTicksX = CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEventDeltaAxis2); 846643ca7872b450ea4efacab6188849e5aac2ba161Steve Block } 847643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 848643ca7872b450ea4efacab6188849e5aac2ba161Steve Block result.timeStampSeconds = [event timestamp]; 849643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 850643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return result; 851643ca7872b450ea4efacab6188849e5aac2ba161Steve Block} 852643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 853643ca7872b450ea4efacab6188849e5aac2ba161Steve Block} // namespace WebKit 854