6072N/A * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. 4632N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4632N/A * This code is free software; you can redistribute it and/or modify it 4632N/A * under the terms of the GNU General Public License version 2 only, as 4632N/A * published by the Free Software Foundation. Oracle designates this 4632N/A * particular file as subject to the "Classpath" exception as provided 4632N/A * by Oracle in the LICENSE file that accompanied this code. 4632N/A * This code is distributed in the hope that it will be useful, but WITHOUT 4632N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 4632N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 4632N/A * version 2 for more details (a copy is included in the LICENSE file that 4632N/A * You should have received a copy of the GNU General Public License version 4632N/A * 2 along with this work; if not, write to the Free Software Foundation, 4632N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 4632N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 4632N/A * or visit www.oracle.com if you need additional information or have any 4632N/A#
import "java_awt_event_InputEvent.h" 4632N/A#
import "java_awt_event_KeyEvent.h" 4632N/A#
import "java_awt_event_MouseEvent.h" 4632N/A * Table to map typed characters to their Java virtual key equivalent and back. 4632N/A * We use the incoming unichar (ignoring all modifiers) and try to figure out 4632N/A * which virtual key code is appropriate. A lot of them just have direct 4632N/A * mappings (the function keys, arrow keys, etc.) so they aren't a problem. 4632N/A * We had to do something a little funky to catch the keys on the numeric 4632N/A * key pad (i.e. using event mask to distinguish between period on regular 4632N/A * keyboard and decimal on keypad). We also have to do something incredibly 4632N/A * hokey with regards to the shifted punctuation characters. For examples, 4632N/A * consider '&' which is usually Shift-7. For the Java key typed events, 4632N/A * that's no problem, we just say pass the unichar. But for the 4632N/A * (which roughly correspond to hardware keys) which means we are supposed 4632N/A * to say the virtual 7 key was pressed. But how are we supposed to know 4632N/A * when we get a punctuation char what was the real hardware key was that 4632N/A * was pressed? Although '&' often comes from Shift-7 the keyboard can be 4632N/A * remapped! I don't think there really is a good answer, and hopefully 4632N/A * all good applets are only interested in logical key typed events not 4632N/A * to trigger the virtual keys that are the expected ones under a standard 4632N/A * keymapping. Looking at Windows & Mac, they don't actually do this, the 4632N/A * Mac seems to just put the ascii code in for the shifted punctuation 4632N/A * (which means they actually end up with bogus key codes on the Java side), 4632N/A * Windows I can't even figure out what it's doing. 4632N/A * This table was stolen from the Windows implementation for mapping 4632N/A * Unicode values to VK codes for dead keys. On Windows, some layouts 4632N/A * return ASCII punctuation for dead accents, while some return spacing 4632N/A * accent chars, so both should be listed. However, in all of the 4632N/A * keyboard layouts I tried only the Unicode values are used. 4632N/A// TODO: some constants below are part of CGS (private interfaces)... 4632N/A// for now we will look at the raw key code to determine left/right status 4632N/A// but not sure this is foolproof... 4632N/A //kCGSFlagsMaskAppleShiftKey, 4632N/A //kCGSFlagsMaskAppleRightShiftKey, 4632N/A //kCGSFlagsMaskAppleControlKey, 4632N/A //kCGSFlagsMaskAppleRightControlKey, 4632N/A //kCGSFlagsMaskAppleLeftAlternateKey, 4632N/A //kCGSFlagsMaskAppleRightAlternateKey, 4632N/A //kCGSFlagsMaskAppleLeftCommandKey, 4632N/A //kCGSFlagsMaskAppleRightCommandKey, 4632N/A * Almost all unicode characters just go from NS to Java with no translation. 4632N/A * For the few exceptions, we handle it here with this small table. 4632N/A // map enter on keypad to same as return key 4632N/A // [3134616] return newline instead of carriage return 4632N/A // "delete" means backspace in Java 4632N/A // back-tab is only differentiated from tab by Shift flag 4632N/A // Mask off just the keyboard modifiers from the event modifier mask. 4632N/A // walk through table & find the match 4632N/A // <rdar://Problem/3476426> Need to determine if we are looking at 4632N/A // a plain keypress or a modified keypress. Don't adjust the 4632N/A // character of a keypress with a modifier. 4632N/A // If the modifier field is 0, that means to transform 4632N/A // this character if no additional keyboard modifiers are set. 4632N/A // This lets ctrl-C be reported as ctrl-C and not transformed 4632N/A // Likewise, if the modifier field is nonzero, that means 4632N/A // transform this character if only these modifiers are 4632N/A // set in the testable flags. 4632N/A // otherwise return character unchanged 5368N/A // Carbon modifiers should be used instead of NSEvent modifiers 5368N/A // Press SPACE to get the dead key char 4632N/A * This is the function that uses the table above to take incoming 4632N/A * NSEvent keyCodes and translate to the Java virtual key code. 4632N/A // If we got here, we keep looking for a normal key. 4632N/A // key is an alphabetic character 4632N/A // some chars in letter set are NOT actually A-Z characters?! 4632N/A // make sure in range for decimal digits 4632N/A // Should we report this? This means we've got a keyboard 4632N/A * This returns the java key data for the key NSEvent modifiers 4632N/A //if (changedNSFlags & cur->cgsLeftMask) { 4632N/A // *javaKeyLocation = java_awt_event_KeyEvent_KEY_LOCATION_LEFT; 4632N/A //} else if (changedNSFlags & cur->cgsRightMask) { 4632N/A // *javaKeyLocation = java_awt_event_KeyEvent_KEY_LOCATION_RIGHT; 4632N/A * This returns the java modifiers for a key NSEvent. 5337N/A * This returns the NSEvent flags for java key modifiers. 4632N/A * Returns the correct java character for a key event. Most unicode 4632N/A * characters don't require any fussing, but a few seem to need adjusting, 4632N/A // no character for modifier keys 4632N/A //if (TSMGetDeadKeyState() != 0) { 4632N/A // testDeadChar = [self deadKeyCharacter]; 4632N/A //[NSException raise:@"AWT error" format:@"Attempt to get character code from non-key event!"]; 4632N/AGetDeadKeyCharacter(NSEvent *event) 4632N/A // If the current event is not a dead key, return 0. 4632N/A // TODO: this uses SPI; it's an optimization but not strictly necessary 4632N/A //if (TSMGetDeadKeyState() == 0) { 4632N/A // AppKit does not track dead-key states directly, but TSM does. Even then, 4632N/A // it's not necessarily all that accurate, because the dead key can change 4632N/A // given some combination of modifier keys on certain layouts. 4632N/A // As a result, finding the unicode value for the front end of the dead 4632N/A // key is a bit of a heuristic. 4632N/A // This algorithm was suggested by Aki Inoue. 4632N/A // When you get a dead key, you need to simiulate what would happen in 4632N/A // the current dead-key and modifier state if the user hit the spacebar. 4632N/A // That will tell you the front end of the dead-key combination. 4632N/A const UInt16 VIRTUAL_KEY_SPACE = 49; 4632N/A UInt32 appkitFlags = [event modifierFlags]; 4632N/A UniCharCount actualStringLength; 4632N/A UniChar unicodeInputString[16]; 4632N/A TISInputSourceRef keyLayout; 4632N/A keyLayout = TISCopyCurrentKeyboardLayoutInputSource(); 4632N/A TISGetInputSourceProperty(keyLayout, kTISPropertyUnicodeKeyLayoutData); 4632N/A // The actual 'uchr' table is inside the CFDataRef. 4632N/A chrData = CFDataGetBytePtr(cfUchrData); 4632N/A UInt8 keyboardType = LMGetKbdType(); 4632N/A UInt32 keyEventModifiers = 0; 4632N/A if (appkitFlags & NSShiftKeyMask) keyEventModifiers |= shiftKey; 4632N/A if (appkitFlags & NSCommandKeyMask) keyEventModifiers |= cmdKey; 4632N/A if (appkitFlags & NSAlphaShiftKeyMask) keyEventModifiers |= alphaLock; 4632N/A if (appkitFlags & NSControlKeyMask) keyEventModifiers |= controlKey; 4632N/A if (appkitFlags & NSAlternateKeyMask) keyEventModifiers |= optionKey; 4632N/A if (noErr == UCKeyTranslate(chrData, 4632N/A ([event type] == NSKeyDown ? kUCKeyActionDown : kUCKeyActionUp), 4632N/A kUCKeyTranslateNoDeadKeysMask, 4632N/A if (actualStringLength > 0) { 4632N/A returnValue = unicodeInputString[0]; 4655N/A// REMIND: The fix for MACOSX_PORT-539 introduces Java-level implementation 4655N/A// of the function below (see CPlatformResponder). Consider removing this code. 4632N/A //[NSException raise:@"AWT error" format:@"Attempt to get virtual key code from non-key event!"]; 4632N/A // Mousing needs the key modifiers 4632N/A * Ask Quartz about mouse buttons state 4632N/A * Converts an NSEvent button number to a MouseEvent constant. 4632N/A "deliverMouseEvent",
"(IIIIFFFF)V");
4632N/A * After every key down event, this is called to make the matching 4632N/A * KEY_TYPED (if this key posts those). We use the same NSEvent for it, 4632N/A * but create a KEY_TYPED java event this time. 4632N/A * If this key doesn't post typed, we don't post the event. 4632N/A * TODO: some duplicated effort here; could just fold it 4632N/A * into DeliverJavaKeyEvent... 4632N/A // Some keys may generate a KEY_TYPED, but we can't determine 4632N/A // what that character is. That's likely a bug, but for now we 4632N/A // just check for CHAR_UNDEFINED. 4632N/A "deliverKeyEvent",
"(IICII)V");
4632N/A * There are a couple of extra events that Java expects to get that don't 4632N/A * actually correspond to a direct NSEvent, KEY_TYPED and MOUSE_CLICKED are 4632N/A * both extra events that are sort of redundant with ordinary 4632N/A * key downs and mouse ups. In this extra message, we take the original 4632N/A * input event and if necessary, cons up a special follow-on event which 4632N/A * we dispatch over to Java. 4632N/A * For Java, keyDown's generate a KeyPressed (for each hardware key as it 4632N/A * goes down) and then a "logical KeyTyped" event for the key event. (So 4632N/A * a shift-a generates two presses, one keytyped of "A", and then two 4632N/A * releases). The standard event utility function converts a key down to 4632N/A * a key pressed. When appropriate, we need to cons up another event 4632N/A * (KEY_TYPED) to follow a keyDown. 4632N/A * Java expects you to send a clicked event if you got a down & up, with no 4632N/A * intervening drag. So in addition to the MOUSE_RELEASED event that a 4632N/A * mouseUp is translated to, we also have to cons up a MOUSE_CLICKED event 4632N/A * for that case. Mike Paquette, god of Window Server event handling, 4632N/A * confirmed this fact about how to determine if a mouse up event had an 4632N/A * An initial mouse-down gets a click count of 1. Subsequent left or right 4632N/A * mouse-downs within the space/time tolerance limits increment the click 4632N/A * count. A mouse-up will have the clickCount of the last mouseDown if 4632N/A * mouse is not outside the tolerance limits, but 0 otherwise. Thus, a 4632N/A * down-up sequence without any intervening drag will have a click count 4632N/A * of 0 in the mouse-up event. NOTE: The problem with this is that 4632N/A * clickCount goes to zero after some point in time. So a long, click & 4632N/A * hold without moving and then release the mouse doesn't create a 4632N/A * MOUSE_CLICK event as it should. Java AWT now tracks the drag state itself. 4632N/A * As another add-on, we also check for the status of mouse-motion events 4632N/A * after a mouse-down, so we know whether to generate mouse-dragged events 4632N/A * during this down sequence. 4632N/A // TODO: we may need to pull in changedDragToMove here... 4632N/A //if (!isDragging && ([NSViewAWT changedDragToMove]==NO)) { 4632N/A // got down/up pair with no dragged in between; ignores drag events 4632N/A // that have been morphed to move events 4632N/A// TODO: to be implemented... 4632N/A // During a drag, the AppKit does not send mouseEnter and mouseExit 4632N/A // events. It turns out that doing a hitTest causes the window's 4632N/A // view hierarchy to be locked from drawing and that, of course, 4632N/A // slows everything way down. Synthesize mouseEnter and mouseExit 4632N/A // We know sLastMouseDraggedView is a AWTPeerControl. 4632N/A // Send mouseExit to sLastMouseDraggedView 4632N/A // Send mouseEnter to hitView 4632N/A // Set sLastMouseDraggedView = hitView 4655N/A * Class: sun_lwawt_macosx_event_NSEvent 4781N/A * Method: nsToJavaMouseModifiers 4655N/A * Class: sun_lwawt_macosx_event_NSEvent 4781N/A * Method: nsToJavaKeyModifiers 4655N/A * Class: sun_lwawt_macosx_event_NSEvent 4655N/A // in = [testChar, testDeadChar, modifierFlags, keyCode] 5368N/A // out = [jkeyCode, jkeyLocation, deadKeyChar]; 4655N/A * Class: sun_lwawt_macosx_event_NSEvent 4655N/A * Method: nsKeyModifiersToJavaKeyInfo 4655N/A // in = [modifierFlags, keyCode] 4655N/A // out = [jkeyCode, jkeyLocation, jkeyType]; 4790N/A * Class: sun_lwawt_macosx_event_NSEvent