Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/macosx/native_NOTIOS/sun/awt/AWTEvent.m
38829 views
/*1* Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425#import <JavaNativeFoundation/JavaNativeFoundation.h>26#import <JavaRuntimeSupport/JavaRuntimeSupport.h>27#import <sys/time.h>28#include <Carbon/Carbon.h>2930#import "jni_util.h"31#import "LWCToolkit.h"32#import "ThreadUtilities.h"3334#import "java_awt_event_InputEvent.h"35#import "java_awt_event_KeyEvent.h"36#import "java_awt_event_MouseEvent.h"3738/*39* Table to map typed characters to their Java virtual key equivalent and back.40* We use the incoming unichar (ignoring all modifiers) and try to figure out41* which virtual key code is appropriate. A lot of them just have direct42* mappings (the function keys, arrow keys, etc.) so they aren't a problem.43* We had to do something a little funky to catch the keys on the numeric44* key pad (i.e. using event mask to distinguish between period on regular45* keyboard and decimal on keypad). We also have to do something incredibly46* hokey with regards to the shifted punctuation characters. For examples,47* consider '&' which is usually Shift-7. For the Java key typed events,48* that's no problem, we just say pass the unichar. But for the49* KeyPressed/Released events, we need to identify the virtual key code50* (which roughly correspond to hardware keys) which means we are supposed51* to say the virtual 7 key was pressed. But how are we supposed to know52* when we get a punctuation char what was the real hardware key was that53* was pressed? Although '&' often comes from Shift-7 the keyboard can be54* remapped! I don't think there really is a good answer, and hopefully55* all good applets are only interested in logical key typed events not56* press/release. Meanwhile, we are hard-coding the shifted punctuation57* to trigger the virtual keys that are the expected ones under a standard58* keymapping. Looking at Windows & Mac, they don't actually do this, the59* Mac seems to just put the ascii code in for the shifted punctuation60* (which means they actually end up with bogus key codes on the Java side),61* Windows I can't even figure out what it's doing.62*/63#define KL_STANDARD java_awt_event_KeyEvent_KEY_LOCATION_STANDARD64#define KL_NUMPAD java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD65#define KL_UNKNOWN java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN66static struct _key67{68unsigned short keyCode;69BOOL postsTyped;70jint javaKeyLocation;71jint javaKeyCode;72}73const keyTable[] =74{75{0x00, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_A},76{0x01, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_S},77{0x02, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_D},78{0x03, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_F},79{0x04, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_H},80{0x05, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_G},81{0x06, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_Z},82{0x07, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_X},83{0x08, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_C},84{0x09, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_V},85{0x0A, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_BACK_QUOTE},86{0x0B, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_B},87{0x0C, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_Q},88{0x0D, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_W},89{0x0E, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_E},90{0x0F, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_R},91{0x10, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_Y},92{0x11, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_T},93{0x12, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_1},94{0x13, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_2},95{0x14, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_3},96{0x15, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_4},97{0x16, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_6},98{0x17, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_5},99{0x18, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_EQUALS},100{0x19, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_9},101{0x1A, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_7},102{0x1B, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_MINUS},103{0x1C, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_8},104{0x1D, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_0},105{0x1E, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_CLOSE_BRACKET},106{0x1F, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_O},107{0x20, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_U},108{0x21, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_OPEN_BRACKET},109{0x22, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_I},110{0x23, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_P},111{0x24, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_ENTER},112{0x25, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_L},113{0x26, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_J},114{0x27, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_QUOTE},115{0x28, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_K},116{0x29, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_SEMICOLON},117{0x2A, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_BACK_SLASH},118{0x2B, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_COMMA},119{0x2C, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_SLASH},120{0x2D, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_N},121{0x2E, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_M},122{0x2F, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_PERIOD},123{0x30, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_TAB},124{0x31, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_SPACE},125{0x32, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_BACK_QUOTE},126{0x33, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_BACK_SPACE},127{0x34, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_ENTER},128{0x35, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_ESCAPE},129{0x36, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED},130{0x37, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_META}, // ****131{0x38, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_SHIFT}, // ****132{0x39, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_CAPS_LOCK},133{0x3A, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_ALT}, // ****134{0x3B, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_CONTROL}, // ****135{0x3C, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED},136{0x3D, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED},137{0x3E, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED},138{0x3F, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED}, // the 'fn' key on PowerBooks139{0x40, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED},140{0x41, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_DECIMAL},141{0x42, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED},142{0x43, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_MULTIPLY},143{0x44, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED},144{0x45, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_ADD},145{0x46, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED},146{0x47, NO, KL_NUMPAD, java_awt_event_KeyEvent_VK_CLEAR},147{0x48, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED},148{0x49, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED},149{0x4A, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED},150{0x4B, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_DIVIDE},151{0x4C, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_ENTER},152{0x4D, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED},153{0x4E, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_SUBTRACT},154{0x4F, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED},155{0x50, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED},156{0x51, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_EQUALS},157{0x52, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD0},158{0x53, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD1},159{0x54, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD2},160{0x55, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD3},161{0x56, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD4},162{0x57, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD5},163{0x58, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD6},164{0x59, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD7},165{0x5A, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED},166{0x5B, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD8},167{0x5C, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD9},168{0x5D, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_BACK_SLASH}, // This is a combo yen/backslash on JIS keyboards.169{0x5E, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_UNDERSCORE},170{0x5F, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_COMMA},171{0x60, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F5},172{0x61, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F6},173{0x62, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F7},174{0x63, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F3},175{0x64, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F8},176{0x65, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F9},177{0x66, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_ALPHANUMERIC},178{0x67, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F11},179{0x68, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_KATAKANA},180{0x69, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F13},181{0x6A, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F16},182{0x6B, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F14},183{0x6C, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED},184{0x6D, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F10},185{0x6E, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED},186{0x6F, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F12},187{0x70, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED},188{0x71, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F15},189{0x72, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_HELP},190{0x73, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_HOME},191{0x74, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_PAGE_UP},192{0x75, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_DELETE},193{0x76, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F4},194{0x77, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_END},195{0x78, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F2},196{0x79, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_PAGE_DOWN},197{0x7A, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F1},198{0x7B, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_LEFT},199{0x7C, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_RIGHT},200{0x7D, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_DOWN},201{0x7E, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_UP},202{0x7F, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED},203};204205/*206* This table was stolen from the Windows implementation for mapping207* Unicode values to VK codes for dead keys. On Windows, some layouts208* return ASCII punctuation for dead accents, while some return spacing209* accent chars, so both should be listed. However, in all of the210* keyboard layouts I tried only the Unicode values are used.211*/212struct CharToVKEntry {213UniChar c;214jint javaKey;215};216static const struct CharToVKEntry charToDeadVKTable[] = {217{0x0060, java_awt_event_KeyEvent_VK_DEAD_GRAVE},218{0x00B4, java_awt_event_KeyEvent_VK_DEAD_ACUTE},219{0x0384, java_awt_event_KeyEvent_VK_DEAD_ACUTE}, // Unicode "GREEK TONOS" -- Greek keyboard, semicolon key220{0x005E, java_awt_event_KeyEvent_VK_DEAD_CIRCUMFLEX},221{0x007E, java_awt_event_KeyEvent_VK_DEAD_TILDE},222{0x02DC, java_awt_event_KeyEvent_VK_DEAD_TILDE}, // Unicode "SMALL TILDE"223{0x00AF, java_awt_event_KeyEvent_VK_DEAD_MACRON},224{0x02D8, java_awt_event_KeyEvent_VK_DEAD_BREVE},225{0x02D9, java_awt_event_KeyEvent_VK_DEAD_ABOVEDOT},226{0x00A8, java_awt_event_KeyEvent_VK_DEAD_DIAERESIS},227{0x02DA, java_awt_event_KeyEvent_VK_DEAD_ABOVERING},228{0x02DD, java_awt_event_KeyEvent_VK_DEAD_DOUBLEACUTE},229{0x02C7, java_awt_event_KeyEvent_VK_DEAD_CARON},230{0x00B8, java_awt_event_KeyEvent_VK_DEAD_CEDILLA},231{0x02DB, java_awt_event_KeyEvent_VK_DEAD_OGONEK},232{0x037A, java_awt_event_KeyEvent_VK_DEAD_IOTA},233{0x309B, java_awt_event_KeyEvent_VK_DEAD_VOICED_SOUND},234{0x309C, java_awt_event_KeyEvent_VK_DEAD_SEMIVOICED_SOUND},235{0,0}236};237238// TODO: some constants below are part of CGS (private interfaces)...239// for now we will look at the raw key code to determine left/right status240// but not sure this is foolproof...241static struct _nsKeyToJavaModifier242{243NSUInteger nsMask;244//NSUInteger cgsLeftMask;245//NSUInteger cgsRightMask;246unsigned short leftKeyCode;247unsigned short rightKeyCode;248jint javaExtMask;249jint javaMask;250jint javaKey;251}252const nsKeyToJavaModifierTable[] =253{254{255NSAlphaShiftKeyMask,2560,2570,2580, // no Java equivalent2590, // no Java equivalent260java_awt_event_KeyEvent_VK_CAPS_LOCK261},262{263NSShiftKeyMask,264//kCGSFlagsMaskAppleShiftKey,265//kCGSFlagsMaskAppleRightShiftKey,26656,26760,268java_awt_event_InputEvent_SHIFT_DOWN_MASK,269java_awt_event_InputEvent_SHIFT_MASK,270java_awt_event_KeyEvent_VK_SHIFT271},272{273NSControlKeyMask,274//kCGSFlagsMaskAppleControlKey,275//kCGSFlagsMaskAppleRightControlKey,27659,27762,278java_awt_event_InputEvent_CTRL_DOWN_MASK,279java_awt_event_InputEvent_CTRL_MASK,280java_awt_event_KeyEvent_VK_CONTROL281},282{283NSAlternateKeyMask,284//kCGSFlagsMaskAppleLeftAlternateKey,285//kCGSFlagsMaskAppleRightAlternateKey,28658,28761,288java_awt_event_InputEvent_ALT_DOWN_MASK,289java_awt_event_InputEvent_ALT_MASK,290java_awt_event_KeyEvent_VK_ALT291},292{293NSCommandKeyMask,294//kCGSFlagsMaskAppleLeftCommandKey,295//kCGSFlagsMaskAppleRightCommandKey,29655,29754,298java_awt_event_InputEvent_META_DOWN_MASK,299java_awt_event_InputEvent_META_MASK,300java_awt_event_KeyEvent_VK_META301},302// NSNumericPadKeyMask303{304NSHelpKeyMask,3050,3060,3070, // no Java equivalent3080, // no Java equivalent309java_awt_event_KeyEvent_VK_HELP310},311// NSFunctionKeyMask312{0, 0, 0, 0, 0, 0}313};314315/*316* Almost all unicode characters just go from NS to Java with no translation.317* For the few exceptions, we handle it here with this small table.318*/319#define ALL_NS_KEY_MODIFIERS_MASK \320(NSShiftKeyMask | NSControlKeyMask | NSAlternateKeyMask | NSCommandKeyMask)321322static struct _char {323NSUInteger modifier;324unichar nsChar;325unichar javaChar;326}327const charTable[] = {328// map enter on keypad to same as return key329{0, NSEnterCharacter, NSNewlineCharacter},330331// [3134616] return newline instead of carriage return332{0, NSCarriageReturnCharacter, NSNewlineCharacter},333334// "delete" means backspace in Java335{ALL_NS_KEY_MODIFIERS_MASK, NSDeleteCharacter, NSBackspaceCharacter},336{ALL_NS_KEY_MODIFIERS_MASK, NSDeleteFunctionKey, NSDeleteCharacter},337338// back-tab is only differentiated from tab by Shift flag339{NSShiftKeyMask, NSBackTabCharacter, NSTabCharacter},340341{0, 0, 0}342};343344unichar NsCharToJavaChar(unichar nsChar, NSUInteger modifiers)345{346const struct _char *cur;347// Mask off just the keyboard modifiers from the event modifier mask.348NSUInteger testableFlags = (modifiers & ALL_NS_KEY_MODIFIERS_MASK);349350// walk through table & find the match351for (cur = charTable; cur->nsChar != 0 ; cur++) {352// <rdar://Problem/3476426> Need to determine if we are looking at353// a plain keypress or a modified keypress. Don't adjust the354// character of a keypress with a modifier.355if (cur->nsChar == nsChar) {356if (cur->modifier == 0 && testableFlags == 0) {357// If the modifier field is 0, that means to transform358// this character if no additional keyboard modifiers are set.359// This lets ctrl-C be reported as ctrl-C and not transformed360// into Newline.361return cur->javaChar;362} else if (cur->modifier != 0 &&363(testableFlags & cur->modifier) == testableFlags)364{365// Likewise, if the modifier field is nonzero, that means366// transform this character if only these modifiers are367// set in the testable flags.368return cur->javaChar;369}370}371}372373if (nsChar >= NSUpArrowFunctionKey && nsChar <= NSModeSwitchFunctionKey) {374return java_awt_event_KeyEvent_CHAR_UNDEFINED;375}376377// otherwise return character unchanged378return nsChar;379}380381static unichar NsGetDeadKeyChar(unsigned short keyCode)382{383TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource();384CFDataRef uchr = (CFDataRef)TISGetInputSourceProperty(currentKeyboard, kTISPropertyUnicodeKeyLayoutData);385if (uchr == nil) { return 0; }386const UCKeyboardLayout *keyboardLayout = (const UCKeyboardLayout*)CFDataGetBytePtr(uchr);387// Carbon modifiers should be used instead of NSEvent modifiers388UInt32 modifierKeyState = (GetCurrentEventKeyModifiers() >> 8) & 0xFF;389390if (keyboardLayout) {391UInt32 deadKeyState = 0;392UniCharCount maxStringLength = 255;393UniCharCount actualStringLength = 0;394UniChar unicodeString[maxStringLength];395396// get the deadKeyState397OSStatus status = UCKeyTranslate(keyboardLayout,398keyCode, kUCKeyActionDown, modifierKeyState,399LMGetKbdType(), kUCKeyTranslateNoDeadKeysBit,400&deadKeyState,401maxStringLength,402&actualStringLength, unicodeString);403404if (status == noErr && deadKeyState != 0) {405// Press SPACE to get the dead key char406status = UCKeyTranslate(keyboardLayout,407kVK_Space, kUCKeyActionDown, 0,408LMGetKbdType(), 0,409&deadKeyState,410maxStringLength,411&actualStringLength, unicodeString);412413if (status == noErr && actualStringLength > 0) {414return unicodeString[0];415}416}417}418return 0;419}420421/*422* This is the function that uses the table above to take incoming423* NSEvent keyCodes and translate to the Java virtual key code.424*/425static void426NsCharToJavaVirtualKeyCode(unichar ch, BOOL isDeadChar,427NSUInteger flags, unsigned short key,428jint *keyCode, jint *keyLocation, BOOL *postsTyped, unichar *deadChar)429{430static size_t size = sizeof(keyTable) / sizeof(struct _key);431NSInteger offset;432433if (isDeadChar) {434unichar testDeadChar = NsGetDeadKeyChar(key);435const struct CharToVKEntry *map;436for (map = charToDeadVKTable; map->c != 0; ++map) {437if (testDeadChar == map->c) {438*keyCode = map->javaKey;439*postsTyped = NO;440// TODO: use UNKNOWN here?441*keyLocation = java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN;442*deadChar = testDeadChar;443return;444}445}446// If we got here, we keep looking for a normal key.447}448449if ([[NSCharacterSet letterCharacterSet] characterIsMember:ch]) {450// key is an alphabetic character451unichar lower;452lower = tolower(ch);453offset = lower - 'a';454if (offset >= 0 && offset <= 25) {455// some chars in letter set are NOT actually A-Z characters?!456// skip them...457*postsTyped = YES;458// do quick conversion459*keyCode = java_awt_event_KeyEvent_VK_A + offset;460*keyLocation = java_awt_event_KeyEvent_KEY_LOCATION_STANDARD;461return;462}463}464465if ([[NSCharacterSet decimalDigitCharacterSet] characterIsMember:ch]) {466// key is a digit467offset = ch - '0';468// make sure in range for decimal digits469if (offset >= 0 && offset <= 9) {470jboolean numpad = (flags & NSNumericPadKeyMask) != 0;471*postsTyped = YES;472if (numpad) {473*keyCode = offset + java_awt_event_KeyEvent_VK_NUMPAD0;474*keyLocation = java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD;475} else {476*keyCode = offset + java_awt_event_KeyEvent_VK_0;477*keyLocation = java_awt_event_KeyEvent_KEY_LOCATION_STANDARD;478}479return;480}481}482483if (key < size) {484*postsTyped = keyTable[key].postsTyped;485*keyCode = keyTable[key].javaKeyCode;486*keyLocation = keyTable[key].javaKeyLocation;487} else {488// Should we report this? This means we've got a keyboard489// we don't know about...490*postsTyped = NO;491*keyCode = java_awt_event_KeyEvent_VK_UNDEFINED;492*keyLocation = java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN;493}494}495496/*497* This returns the java key data for the key NSEvent modifiers498* (after NSFlagChanged).499*/500static void501NsKeyModifiersToJavaKeyInfo(NSUInteger nsFlags, unsigned short eventKeyCode,502jint *javaKeyCode,503jint *javaKeyLocation,504jint *javaKeyType)505{506static NSUInteger sPreviousNSFlags = 0;507508const struct _nsKeyToJavaModifier* cur;509NSUInteger oldNSFlags = sPreviousNSFlags;510NSUInteger changedNSFlags = oldNSFlags ^ nsFlags;511sPreviousNSFlags = nsFlags;512513*javaKeyCode = java_awt_event_KeyEvent_VK_UNDEFINED;514*javaKeyLocation = java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN;515*javaKeyType = java_awt_event_KeyEvent_KEY_PRESSED;516517for (cur = nsKeyToJavaModifierTable; cur->nsMask != 0; ++cur) {518if (changedNSFlags & cur->nsMask) {519*javaKeyCode = cur->javaKey;520*javaKeyLocation = java_awt_event_KeyEvent_KEY_LOCATION_STANDARD;521// TODO: uses SPI...522//if (changedNSFlags & cur->cgsLeftMask) {523// *javaKeyLocation = java_awt_event_KeyEvent_KEY_LOCATION_LEFT;524//} else if (changedNSFlags & cur->cgsRightMask) {525// *javaKeyLocation = java_awt_event_KeyEvent_KEY_LOCATION_RIGHT;526//}527if (eventKeyCode == cur->leftKeyCode) {528*javaKeyLocation = java_awt_event_KeyEvent_KEY_LOCATION_LEFT;529} else if (eventKeyCode == cur->rightKeyCode) {530*javaKeyLocation = java_awt_event_KeyEvent_KEY_LOCATION_RIGHT;531}532*javaKeyType = (cur->nsMask & nsFlags) ?533java_awt_event_KeyEvent_KEY_PRESSED :534java_awt_event_KeyEvent_KEY_RELEASED;535break;536}537}538}539540/*541* This returns the java modifiers for a key NSEvent.542*/543jint NsKeyModifiersToJavaModifiers(NSUInteger nsFlags, BOOL isExtMods)544{545jint javaModifiers = 0;546const struct _nsKeyToJavaModifier* cur;547548for (cur = nsKeyToJavaModifierTable; cur->nsMask != 0; ++cur) {549if ((cur->nsMask & nsFlags) != 0) {550javaModifiers |= isExtMods? cur->javaExtMask : cur->javaMask;551}552}553554return javaModifiers;555}556557/*558* This returns the NSEvent flags for java key modifiers.559*/560NSUInteger JavaModifiersToNsKeyModifiers(jint javaModifiers, BOOL isExtMods)561{562NSUInteger nsFlags = 0;563const struct _nsKeyToJavaModifier* cur;564565for (cur = nsKeyToJavaModifierTable; cur->nsMask != 0; ++cur) {566jint mask = isExtMods? cur->javaExtMask : cur->javaMask;567if ((mask & javaModifiers) != 0) {568nsFlags |= cur->nsMask;569}570}571572// special case573jint mask = isExtMods? java_awt_event_InputEvent_ALT_GRAPH_DOWN_MASK :574java_awt_event_InputEvent_ALT_GRAPH_MASK;575576if ((mask & javaModifiers) != 0) {577nsFlags |= NSAlternateKeyMask;578}579580return nsFlags;581}582583584jint GetJavaMouseModifiers(NSInteger button, NSUInteger modifierFlags)585{586// Mousing needs the key modifiers587jint modifiers = NsKeyModifiersToJavaModifiers(modifierFlags, YES);588589590/*591* Ask Quartz about mouse buttons state592*/593594if (CGEventSourceButtonState(kCGEventSourceStateCombinedSessionState,595kCGMouseButtonLeft)) {596modifiers |= java_awt_event_InputEvent_BUTTON1_DOWN_MASK;597}598599if (CGEventSourceButtonState(kCGEventSourceStateCombinedSessionState,600kCGMouseButtonRight)) {601modifiers |= java_awt_event_InputEvent_BUTTON3_DOWN_MASK;602}603604if (CGEventSourceButtonState(kCGEventSourceStateCombinedSessionState,605kCGMouseButtonCenter)) {606modifiers |= java_awt_event_InputEvent_BUTTON2_DOWN_MASK;607}608609NSInteger extraButton = 3;610for (; extraButton < gNumberOfButtons; extraButton++) {611if (CGEventSourceButtonState(kCGEventSourceStateCombinedSessionState,612extraButton)) {613modifiers |= gButtonDownMasks[extraButton];614}615}616617return modifiers;618}619620jlong UTC(NSEvent *event) {621struct timeval tv;622if (gettimeofday(&tv, NULL) == 0) {623long long sec = (long long)tv.tv_sec;624return (sec*1000) + (tv.tv_usec/1000);625}626return 0;627}628629JNIEXPORT void JNICALL630Java_java_awt_AWTEvent_nativeSetSource631(JNIEnv *env, jobject self, jobject newSource)632{633}634635/*636* Class: sun_lwawt_macosx_NSEvent637* Method: nsToJavaMouseModifiers638* Signature: (II)I639*/640JNIEXPORT jint JNICALL641Java_sun_lwawt_macosx_NSEvent_nsToJavaMouseModifiers642(JNIEnv *env, jclass cls, jint buttonNumber, jint modifierFlags)643{644jint jmodifiers = 0;645646JNF_COCOA_ENTER(env);647648jmodifiers = GetJavaMouseModifiers(buttonNumber, modifierFlags);649650JNF_COCOA_EXIT(env);651652return jmodifiers;653}654655/*656* Class: sun_lwawt_macosx_NSEvent657* Method: nsToJavaKeyModifiers658* Signature: (I)I659*/660JNIEXPORT jint JNICALL661Java_sun_lwawt_macosx_NSEvent_nsToJavaKeyModifiers662(JNIEnv *env, jclass cls, jint modifierFlags)663{664jint jmodifiers = 0;665666JNF_COCOA_ENTER(env);667668jmodifiers = NsKeyModifiersToJavaModifiers(modifierFlags, YES);669670JNF_COCOA_EXIT(env);671672return jmodifiers;673}674675/*676* Class: sun_lwawt_macosx_NSEvent677* Method: nsToJavaKeyInfo678* Signature: ([I[I)Z679*/680JNIEXPORT jboolean JNICALL681Java_sun_lwawt_macosx_NSEvent_nsToJavaKeyInfo682(JNIEnv *env, jclass cls, jintArray inData, jintArray outData)683{684BOOL postsTyped = NO;685686JNF_COCOA_ENTER(env);687688jboolean copy = JNI_FALSE;689jint *data = (*env)->GetIntArrayElements(env, inData, ©);690CHECK_NULL_RETURN(data, postsTyped);691692// in = [testChar, testDeadChar, modifierFlags, keyCode]693jchar testChar = (jchar)data[0];694BOOL isDeadChar = (data[1] != 0);695jint modifierFlags = data[2];696jshort keyCode = (jshort)data[3];697698jint jkeyCode = java_awt_event_KeyEvent_VK_UNDEFINED;699jint jkeyLocation = java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN;700jchar testDeadChar = 0;701702NsCharToJavaVirtualKeyCode((unichar)testChar, isDeadChar,703(NSUInteger)modifierFlags, (unsigned short)keyCode,704&jkeyCode, &jkeyLocation, &postsTyped, &testDeadChar);705706// out = [jkeyCode, jkeyLocation];707(*env)->SetIntArrayRegion(env, outData, 0, 1, &jkeyCode);708(*env)->SetIntArrayRegion(env, outData, 1, 1, &jkeyLocation);709(*env)->SetIntArrayRegion(env, outData, 2, 1, (jint *)&testDeadChar);710711(*env)->ReleaseIntArrayElements(env, inData, data, 0);712713JNF_COCOA_EXIT(env);714715return postsTyped;716}717718/*719* Class: sun_lwawt_macosx_NSEvent720* Method: nsKeyModifiersToJavaKeyInfo721* Signature: ([I[I)V722*/723JNIEXPORT void JNICALL724Java_sun_lwawt_macosx_NSEvent_nsKeyModifiersToJavaKeyInfo725(JNIEnv *env, jclass cls, jintArray inData, jintArray outData)726{727JNF_COCOA_ENTER(env);728729jboolean copy = JNI_FALSE;730jint *data = (*env)->GetIntArrayElements(env, inData, ©);731CHECK_NULL(data);732733// in = [modifierFlags, keyCode]734jint modifierFlags = data[0];735jshort keyCode = (jshort)data[1];736737jint jkeyCode = java_awt_event_KeyEvent_VK_UNDEFINED;738jint jkeyLocation = java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN;739jint jkeyType = java_awt_event_KeyEvent_KEY_PRESSED;740741NsKeyModifiersToJavaKeyInfo(modifierFlags,742keyCode,743&jkeyCode,744&jkeyLocation,745&jkeyType);746747// out = [jkeyCode, jkeyLocation, jkeyType];748(*env)->SetIntArrayRegion(env, outData, 0, 1, &jkeyCode);749(*env)->SetIntArrayRegion(env, outData, 1, 1, &jkeyLocation);750(*env)->SetIntArrayRegion(env, outData, 2, 1, &jkeyType);751752(*env)->ReleaseIntArrayElements(env, inData, data, 0);753754JNF_COCOA_EXIT(env);755}756757/*758* Class: sun_lwawt_macosx_NSEvent759* Method: nsToJavaChar760* Signature: (CI)C761*/762JNIEXPORT jint JNICALL763Java_sun_lwawt_macosx_NSEvent_nsToJavaChar764(JNIEnv *env, jclass cls, jchar nsChar, jint modifierFlags)765{766jchar javaChar = 0;767768JNF_COCOA_ENTER(env);769770javaChar = NsCharToJavaChar(nsChar, modifierFlags);771772JNF_COCOA_EXIT(env);773774return javaChar;775}776777778