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