4632N/A/*
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 *
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 *
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 * accompanied this code).
4632N/A *
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 *
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 * questions.
4632N/A */
4632N/A
4632N/A#import <JavaNativeFoundation/JavaNativeFoundation.h>
4632N/A#import <JavaRuntimeSupport/JavaRuntimeSupport.h>
4632N/A#import <sys/time.h>
5368N/A#include <Carbon/Carbon.h>
4632N/A
4632N/A#import "LWCToolkit.h"
4632N/A#import "ThreadUtilities.h"
4632N/A
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
4632N/A/*
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 * KeyPressed/Released events, we need to identify the virtual key code
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 * press/release. Meanwhile, we are hard-coding the shifted punctuation
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 */
4632N/A#define KL_STANDARD java_awt_event_KeyEvent_KEY_LOCATION_STANDARD
4632N/A#define KL_NUMPAD java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD
4632N/A#define KL_UNKNOWN java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN
4632N/Astatic struct _key
4632N/A{
4632N/A unsigned short keyCode;
4632N/A BOOL postsTyped;
4632N/A jint javaKeyLocation;
4632N/A jint javaKeyCode;
4632N/A}
4632N/Aconst keyTable[] =
4632N/A{
4632N/A {0x00, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_A},
4632N/A {0x01, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_S},
4632N/A {0x02, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_D},
4632N/A {0x03, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_F},
4632N/A {0x04, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_H},
4632N/A {0x05, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_G},
4632N/A {0x06, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_Z},
4632N/A {0x07, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_X},
4632N/A {0x08, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_C},
4632N/A {0x09, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_V},
4632N/A {0x0A, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_BACK_QUOTE},
4632N/A {0x0B, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_B},
4632N/A {0x0C, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_Q},
4632N/A {0x0D, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_W},
4632N/A {0x0E, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_E},
4632N/A {0x0F, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_R},
4632N/A {0x10, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_Y},
4632N/A {0x11, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_T},
4632N/A {0x12, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_1},
4632N/A {0x13, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_2},
4632N/A {0x14, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_3},
4632N/A {0x15, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_4},
4632N/A {0x16, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_6},
4632N/A {0x17, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_5},
4632N/A {0x18, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_EQUALS},
4632N/A {0x19, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_9},
4632N/A {0x1A, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_7},
4632N/A {0x1B, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_MINUS},
4632N/A {0x1C, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_8},
4632N/A {0x1D, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_0},
4632N/A {0x1E, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_CLOSE_BRACKET},
4632N/A {0x1F, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_O},
4632N/A {0x20, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_U},
4632N/A {0x21, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_OPEN_BRACKET},
4632N/A {0x22, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_I},
4632N/A {0x23, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_P},
4632N/A {0x24, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_ENTER},
4632N/A {0x25, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_L},
4632N/A {0x26, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_J},
4632N/A {0x27, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_QUOTE},
4632N/A {0x28, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_K},
4632N/A {0x29, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_SEMICOLON},
4632N/A {0x2A, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_BACK_SLASH},
4632N/A {0x2B, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_COMMA},
4632N/A {0x2C, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_SLASH},
4632N/A {0x2D, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_N},
4632N/A {0x2E, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_M},
4632N/A {0x2F, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_PERIOD},
4632N/A {0x30, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_TAB},
4632N/A {0x31, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_SPACE},
4632N/A {0x32, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_BACK_QUOTE},
4632N/A {0x33, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_BACK_SPACE},
4632N/A {0x34, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_ENTER},
5042N/A {0x35, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_ESCAPE},
4632N/A {0x36, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED},
4632N/A {0x37, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_META}, // ****
4632N/A {0x38, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_SHIFT}, // ****
4632N/A {0x39, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_CAPS_LOCK},
4632N/A {0x3A, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_ALT}, // ****
4632N/A {0x3B, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_CONTROL}, // ****
4632N/A {0x3C, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED},
4632N/A {0x3D, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED},
4632N/A {0x3E, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED},
4632N/A {0x3F, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED}, // the 'fn' key on PowerBooks
4632N/A {0x40, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED},
4632N/A {0x41, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_DECIMAL},
4632N/A {0x42, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED},
4632N/A {0x43, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_MULTIPLY},
4632N/A {0x44, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED},
4632N/A {0x45, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_ADD},
4632N/A {0x46, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED},
4632N/A {0x47, NO, KL_NUMPAD, java_awt_event_KeyEvent_VK_CLEAR},
4632N/A {0x48, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED},
4632N/A {0x49, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED},
4632N/A {0x4A, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED},
4632N/A {0x4B, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_DIVIDE},
4632N/A {0x4C, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_ENTER},
4632N/A {0x4D, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED},
4632N/A {0x4E, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_SUBTRACT},
4632N/A {0x4F, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED},
4632N/A {0x50, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED},
4632N/A {0x51, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_EQUALS},
4632N/A {0x52, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD0},
4632N/A {0x53, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD1},
4632N/A {0x54, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD2},
4632N/A {0x55, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD3},
4632N/A {0x56, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD4},
4632N/A {0x57, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD5},
4632N/A {0x58, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD6},
4632N/A {0x59, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD7},
4632N/A {0x5A, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED},
4632N/A {0x5B, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD8},
4632N/A {0x5C, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD9},
4632N/A {0x5D, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_BACK_SLASH}, // This is a combo yen/backslash on JIS keyboards.
4632N/A {0x5E, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_UNDERSCORE},
4632N/A {0x5F, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_COMMA},
4632N/A {0x60, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F5},
4632N/A {0x61, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F6},
4632N/A {0x62, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F7},
4632N/A {0x63, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F3},
4632N/A {0x64, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F8},
4632N/A {0x65, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F9},
4632N/A {0x66, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_ALPHANUMERIC},
4632N/A {0x67, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F11},
4632N/A {0x68, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_KATAKANA},
4632N/A {0x69, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F13},
4632N/A {0x6A, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F16},
4632N/A {0x6B, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F14},
4632N/A {0x6C, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED},
4632N/A {0x6D, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F10},
4632N/A {0x6E, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED},
4632N/A {0x6F, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F12},
4632N/A {0x70, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED},
4632N/A {0x71, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F15},
4632N/A {0x72, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_HELP},
4632N/A {0x73, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_HOME},
4632N/A {0x74, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_PAGE_UP},
4632N/A {0x75, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_DELETE},
4632N/A {0x76, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F4},
4632N/A {0x77, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_END},
4632N/A {0x78, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F2},
4632N/A {0x79, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_PAGE_DOWN},
4632N/A {0x7A, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F1},
4632N/A {0x7B, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_LEFT},
4632N/A {0x7C, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_RIGHT},
4632N/A {0x7D, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_DOWN},
4632N/A {0x7E, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_UP},
4632N/A {0x7F, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED},
4632N/A};
4632N/A
4632N/A/*
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 */
4632N/Astruct CharToVKEntry {
4632N/A UniChar c;
4632N/A jint javaKey;
4632N/A};
4632N/Astatic const struct CharToVKEntry charToDeadVKTable[] = {
4632N/A {0x0060, java_awt_event_KeyEvent_VK_DEAD_GRAVE},
4632N/A {0x00B4, java_awt_event_KeyEvent_VK_DEAD_ACUTE},
4632N/A {0x0384, java_awt_event_KeyEvent_VK_DEAD_ACUTE}, // Unicode "GREEK TONOS" -- Greek keyboard, semicolon key
4632N/A {0x005E, java_awt_event_KeyEvent_VK_DEAD_CIRCUMFLEX},
4632N/A {0x007E, java_awt_event_KeyEvent_VK_DEAD_TILDE},
4632N/A {0x02DC, java_awt_event_KeyEvent_VK_DEAD_TILDE}, // Unicode "SMALL TILDE"
4632N/A {0x00AF, java_awt_event_KeyEvent_VK_DEAD_MACRON},
4632N/A {0x02D8, java_awt_event_KeyEvent_VK_DEAD_BREVE},
4632N/A {0x02D9, java_awt_event_KeyEvent_VK_DEAD_ABOVEDOT},
4632N/A {0x00A8, java_awt_event_KeyEvent_VK_DEAD_DIAERESIS},
4632N/A {0x02DA, java_awt_event_KeyEvent_VK_DEAD_ABOVERING},
4632N/A {0x02DD, java_awt_event_KeyEvent_VK_DEAD_DOUBLEACUTE},
4632N/A {0x02C7, java_awt_event_KeyEvent_VK_DEAD_CARON},
4632N/A {0x00B8, java_awt_event_KeyEvent_VK_DEAD_CEDILLA},
4632N/A {0x02DB, java_awt_event_KeyEvent_VK_DEAD_OGONEK},
4632N/A {0x037A, java_awt_event_KeyEvent_VK_DEAD_IOTA},
4632N/A {0x309B, java_awt_event_KeyEvent_VK_DEAD_VOICED_SOUND},
4632N/A {0x309C, java_awt_event_KeyEvent_VK_DEAD_SEMIVOICED_SOUND},
4632N/A {0,0}
4632N/A};
4632N/A
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/Astatic struct _nsKeyToJavaModifier
4632N/A{
4632N/A NSUInteger nsMask;
4632N/A //NSUInteger cgsLeftMask;
4632N/A //NSUInteger cgsRightMask;
4632N/A unsigned short leftKeyCode;
4632N/A unsigned short rightKeyCode;
5337N/A jint javaExtMask;
4632N/A jint javaMask;
4632N/A jint javaKey;
4632N/A}
4632N/Aconst nsKeyToJavaModifierTable[] =
4632N/A{
4632N/A {
4632N/A NSAlphaShiftKeyMask,
4632N/A 0,
4632N/A 0,
4632N/A 0, // no Java equivalent
5337N/A 0, // no Java equivalent
4632N/A java_awt_event_KeyEvent_VK_CAPS_LOCK
4632N/A },
4632N/A {
4632N/A NSShiftKeyMask,
4632N/A //kCGSFlagsMaskAppleShiftKey,
4632N/A //kCGSFlagsMaskAppleRightShiftKey,
4632N/A 56,
4632N/A 60,
4632N/A java_awt_event_InputEvent_SHIFT_DOWN_MASK,
5337N/A java_awt_event_InputEvent_SHIFT_MASK,
4632N/A java_awt_event_KeyEvent_VK_SHIFT
4632N/A },
4632N/A {
4632N/A NSControlKeyMask,
4632N/A //kCGSFlagsMaskAppleControlKey,
4632N/A //kCGSFlagsMaskAppleRightControlKey,
4632N/A 59,
4632N/A 62,
4632N/A java_awt_event_InputEvent_CTRL_DOWN_MASK,
5337N/A java_awt_event_InputEvent_CTRL_MASK,
4632N/A java_awt_event_KeyEvent_VK_CONTROL
4632N/A },
4632N/A {
4632N/A NSAlternateKeyMask,
4632N/A //kCGSFlagsMaskAppleLeftAlternateKey,
4632N/A //kCGSFlagsMaskAppleRightAlternateKey,
4632N/A 58,
4632N/A 61,
4632N/A java_awt_event_InputEvent_ALT_DOWN_MASK,
5337N/A java_awt_event_InputEvent_ALT_MASK,
4632N/A java_awt_event_KeyEvent_VK_ALT
4632N/A },
4632N/A {
4632N/A NSCommandKeyMask,
4632N/A //kCGSFlagsMaskAppleLeftCommandKey,
4632N/A //kCGSFlagsMaskAppleRightCommandKey,
4632N/A 55,
4632N/A 54,
4632N/A java_awt_event_InputEvent_META_DOWN_MASK,
5337N/A java_awt_event_InputEvent_META_MASK,
4632N/A java_awt_event_KeyEvent_VK_META
4632N/A },
4632N/A // NSNumericPadKeyMask
4632N/A {
4632N/A NSHelpKeyMask,
4632N/A 0,
4632N/A 0,
4632N/A 0, // no Java equivalent
5337N/A 0, // no Java equivalent
4632N/A java_awt_event_KeyEvent_VK_HELP
4632N/A },
4632N/A // NSFunctionKeyMask
5337N/A {0, 0, 0, 0, 0, 0}
4632N/A};
4632N/A
4632N/A/*
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 */
4790N/A#define ALL_NS_KEY_MODIFIERS_MASK \
4790N/A (NSShiftKeyMask | NSControlKeyMask | NSAlternateKeyMask | NSCommandKeyMask)
4790N/A
4632N/Astatic struct _char {
4632N/A NSUInteger modifier;
4632N/A unichar nsChar;
4632N/A unichar javaChar;
4632N/A}
4632N/Aconst charTable[] = {
4632N/A // map enter on keypad to same as return key
4790N/A {0, NSEnterCharacter, NSNewlineCharacter},
4632N/A
4632N/A // [3134616] return newline instead of carriage return
4790N/A {0, NSCarriageReturnCharacter, NSNewlineCharacter},
4632N/A
4632N/A // "delete" means backspace in Java
4790N/A {ALL_NS_KEY_MODIFIERS_MASK, NSDeleteCharacter, NSBackspaceCharacter},
4790N/A {ALL_NS_KEY_MODIFIERS_MASK, NSDeleteFunctionKey, NSDeleteCharacter},
4632N/A
4632N/A // back-tab is only differentiated from tab by Shift flag
4790N/A {NSShiftKeyMask, NSBackTabCharacter, NSTabCharacter},
4632N/A
4632N/A {0, 0, 0}
4632N/A};
4632N/A
6072N/Aunichar NsCharToJavaChar(unichar nsChar, NSUInteger modifiers)
4632N/A{
4632N/A const struct _char *cur;
4632N/A // Mask off just the keyboard modifiers from the event modifier mask.
4790N/A NSUInteger testableFlags = (modifiers & ALL_NS_KEY_MODIFIERS_MASK);
4632N/A
4632N/A // walk through table & find the match
4632N/A for (cur = charTable; cur->nsChar != 0 ; cur++) {
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 (cur->nsChar == nsChar) {
4632N/A if (cur->modifier == 0 && testableFlags == 0) {
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 // into Newline.
4632N/A return cur->javaChar;
4632N/A } else if (cur->modifier != 0 &&
4632N/A (testableFlags & cur->modifier) == testableFlags)
4632N/A {
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 return cur->javaChar;
4632N/A }
4632N/A }
4632N/A }
4632N/A
4632N/A if (nsChar >= NSUpArrowFunctionKey && nsChar <= NSModeSwitchFunctionKey) {
4632N/A return java_awt_event_KeyEvent_CHAR_UNDEFINED;
4632N/A }
4632N/A
4632N/A // otherwise return character unchanged
4632N/A return nsChar;
4632N/A}
4632N/A
5368N/Astatic unichar NsGetDeadKeyChar(unsigned short keyCode)
5368N/A{
5368N/A TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource();
5368N/A CFDataRef uchr = (CFDataRef)TISGetInputSourceProperty(currentKeyboard, kTISPropertyUnicodeKeyLayoutData);
5369N/A if (uchr == nil) { return; }
5368N/A const UCKeyboardLayout *keyboardLayout = (const UCKeyboardLayout*)CFDataGetBytePtr(uchr);
5368N/A // Carbon modifiers should be used instead of NSEvent modifiers
5368N/A UInt32 modifierKeyState = (GetCurrentEventKeyModifiers() >> 8) & 0xFF;
5368N/A
5368N/A if (keyboardLayout) {
5368N/A UInt32 deadKeyState = 0;
5368N/A UniCharCount maxStringLength = 255;
5368N/A UniCharCount actualStringLength = 0;
5368N/A UniChar unicodeString[maxStringLength];
5368N/A
5368N/A // get the deadKeyState
5368N/A OSStatus status = UCKeyTranslate(keyboardLayout,
5368N/A keyCode, kUCKeyActionDown, modifierKeyState,
5368N/A LMGetKbdType(), kUCKeyTranslateNoDeadKeysBit,
5368N/A &deadKeyState,
5368N/A maxStringLength,
5368N/A &actualStringLength, unicodeString);
5368N/A
5368N/A if (status == noErr && deadKeyState != 0) {
5368N/A // Press SPACE to get the dead key char
5368N/A status = UCKeyTranslate(keyboardLayout,
5368N/A kVK_Space, kUCKeyActionDown, 0,
5368N/A LMGetKbdType(), 0,
5368N/A &deadKeyState,
5368N/A maxStringLength,
5368N/A &actualStringLength, unicodeString);
5368N/A
5368N/A if (status == noErr && actualStringLength > 0) {
5368N/A return unicodeString[0];
5368N/A }
5368N/A }
5368N/A }
5368N/A return 0;
5368N/A}
5368N/A
4632N/A/*
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 */
4632N/Astatic void
5368N/ANsCharToJavaVirtualKeyCode(unichar ch, BOOL isDeadChar,
4632N/A NSUInteger flags, unsigned short key,
5368N/A jint *keyCode, jint *keyLocation, BOOL *postsTyped, unichar *deadChar)
4632N/A{
4632N/A static size_t size = sizeof(keyTable) / sizeof(struct _key);
4632N/A NSInteger offset;
4632N/A
5368N/A if (isDeadChar) {
5368N/A unichar testDeadChar = NsGetDeadKeyChar(key);
4632N/A const struct CharToVKEntry *map;
4632N/A for (map = charToDeadVKTable; map->c != 0; ++map) {
5368N/A if (testDeadChar == map->c) {
4632N/A *keyCode = map->javaKey;
4632N/A *postsTyped = NO;
4632N/A // TODO: use UNKNOWN here?
4632N/A *keyLocation = java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN;
5368N/A *deadChar = testDeadChar;
4632N/A return;
4632N/A }
4632N/A }
4632N/A // If we got here, we keep looking for a normal key.
4632N/A }
4632N/A
4632N/A if ([[NSCharacterSet letterCharacterSet] characterIsMember:ch]) {
4632N/A // key is an alphabetic character
4632N/A unichar lower;
4632N/A lower = tolower(ch);
4632N/A offset = lower - 'a';
4632N/A if (offset >= 0 && offset <= 25) {
4632N/A // some chars in letter set are NOT actually A-Z characters?!
4632N/A // skip them...
4632N/A *postsTyped = YES;
4632N/A // do quick conversion
4632N/A *keyCode = java_awt_event_KeyEvent_VK_A + offset;
4632N/A *keyLocation = java_awt_event_KeyEvent_KEY_LOCATION_STANDARD;
4632N/A return;
4632N/A }
4632N/A }
4632N/A
4632N/A if ([[NSCharacterSet decimalDigitCharacterSet] characterIsMember:ch]) {
4632N/A // key is a digit
4632N/A offset = ch - '0';
4632N/A // make sure in range for decimal digits
4632N/A if (offset >= 0 && offset <= 9) {
4632N/A jboolean numpad = (flags & NSNumericPadKeyMask) != 0;
4632N/A *postsTyped = YES;
4632N/A if (numpad) {
4632N/A *keyCode = offset + java_awt_event_KeyEvent_VK_NUMPAD0;
4632N/A *keyLocation = java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD;
4632N/A } else {
4632N/A *keyCode = offset + java_awt_event_KeyEvent_VK_0;
4632N/A *keyLocation = java_awt_event_KeyEvent_KEY_LOCATION_STANDARD;
4632N/A }
4632N/A return;
4632N/A }
4632N/A }
4632N/A
4632N/A if (key < size) {
4632N/A *postsTyped = keyTable[key].postsTyped;
4632N/A *keyCode = keyTable[key].javaKeyCode;
4632N/A *keyLocation = keyTable[key].javaKeyLocation;
4632N/A } else {
4632N/A // Should we report this? This means we've got a keyboard
4632N/A // we don't know about...
4632N/A *postsTyped = NO;
4632N/A *keyCode = java_awt_event_KeyEvent_VK_UNDEFINED;
4632N/A *keyLocation = java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN;
4632N/A }
4632N/A}
4632N/A
4632N/A/*
4632N/A * This returns the java key data for the key NSEvent modifiers
4632N/A * (after NSFlagChanged).
4632N/A */
4632N/Astatic void
4632N/ANsKeyModifiersToJavaKeyInfo(NSUInteger nsFlags, unsigned short eventKeyCode,
4632N/A jint *javaKeyCode,
4632N/A jint *javaKeyLocation,
4632N/A jint *javaKeyType)
4632N/A{
4632N/A static NSUInteger sPreviousNSFlags = 0;
4632N/A
4632N/A const struct _nsKeyToJavaModifier* cur;
4632N/A NSUInteger oldNSFlags = sPreviousNSFlags;
4632N/A NSUInteger changedNSFlags = oldNSFlags ^ nsFlags;
4632N/A sPreviousNSFlags = nsFlags;
4632N/A
4632N/A *javaKeyCode = java_awt_event_KeyEvent_VK_UNDEFINED;
4632N/A *javaKeyLocation = java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN;
4632N/A *javaKeyType = java_awt_event_KeyEvent_KEY_PRESSED;
4632N/A
4632N/A for (cur = nsKeyToJavaModifierTable; cur->nsMask != 0; ++cur) {
4632N/A if (changedNSFlags & cur->nsMask) {
4632N/A *javaKeyCode = cur->javaKey;
4632N/A *javaKeyLocation = java_awt_event_KeyEvent_KEY_LOCATION_STANDARD;
4632N/A // TODO: uses SPI...
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 //}
4632N/A if (eventKeyCode == cur->leftKeyCode) {
4632N/A *javaKeyLocation = java_awt_event_KeyEvent_KEY_LOCATION_LEFT;
4632N/A } else if (eventKeyCode == cur->rightKeyCode) {
4632N/A *javaKeyLocation = java_awt_event_KeyEvent_KEY_LOCATION_RIGHT;
4632N/A }
4632N/A *javaKeyType = (cur->nsMask & nsFlags) ?
4632N/A java_awt_event_KeyEvent_KEY_PRESSED :
4632N/A java_awt_event_KeyEvent_KEY_RELEASED;
4632N/A break;
4632N/A }
4632N/A }
4632N/A}
4632N/A
4632N/A/*
4632N/A * This returns the java modifiers for a key NSEvent.
4632N/A */
5337N/Ajint NsKeyModifiersToJavaModifiers(NSUInteger nsFlags, BOOL isExtMods)
4632N/A{
4632N/A jint javaModifiers = 0;
4632N/A const struct _nsKeyToJavaModifier* cur;
4632N/A
4632N/A for (cur = nsKeyToJavaModifierTable; cur->nsMask != 0; ++cur) {
4632N/A if ((cur->nsMask & nsFlags) != 0) {
5337N/A javaModifiers |= isExtMods? cur->javaExtMask : cur->javaMask;
4632N/A }
4632N/A }
4632N/A
4632N/A return javaModifiers;
4632N/A}
4632N/A
4632N/A/*
5337N/A * This returns the NSEvent flags for java key modifiers.
5337N/A */
5337N/ANSUInteger JavaModifiersToNsKeyModifiers(jint javaModifiers, BOOL isExtMods)
5337N/A{
5337N/A NSUInteger nsFlags = 0;
5337N/A const struct _nsKeyToJavaModifier* cur;
5337N/A
5337N/A for (cur = nsKeyToJavaModifierTable; cur->nsMask != 0; ++cur) {
5368N/A jint mask = isExtMods? cur->javaExtMask : cur->javaMask;
5337N/A if ((mask & javaModifiers) != 0) {
5337N/A nsFlags |= cur->nsMask;
5337N/A }
5337N/A }
5337N/A
5337N/A // special case
5368N/A jint mask = isExtMods? java_awt_event_InputEvent_ALT_GRAPH_DOWN_MASK :
5337N/A java_awt_event_InputEvent_ALT_GRAPH_MASK;
5337N/A
5337N/A if ((mask & javaModifiers) != 0) {
5368N/A nsFlags |= NSAlternateKeyMask;
5337N/A }
5337N/A
5337N/A return nsFlags;
5337N/A}
5337N/A
5337N/A
5337N/A/*
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 * see nsCharToJavaChar.
4632N/A */
4632N/Astatic unichar
4632N/AGetJavaCharacter(NSEvent *event, unsigned int index)
4632N/A{
4632N/A unichar returnValue = java_awt_event_KeyEvent_CHAR_UNDEFINED;
4632N/A NSString *chars = nil;
4632N/A unichar testChar = 0, testDeadChar = 0;
5337N/A jint javaModifiers = NsKeyModifiersToJavaModifiers([event modifierFlags], TRUE);
4632N/A
4632N/A switch ([event type]) {
4632N/A case NSFlagsChanged:
4632N/A // no character for modifier keys
4632N/A returnValue = java_awt_event_KeyEvent_CHAR_UNDEFINED;
4632N/A break;
4632N/A
4632N/A case NSKeyDown:
4632N/A case NSKeyUp:
4632N/A chars = [event characters];
4632N/A if ([chars length] > 0) {
4632N/A testChar = [chars characterAtIndex:index];
4632N/A }
4632N/A
4632N/A if (javaModifiers == 0) {
4632N/A // TODO: uses SPI...
4632N/A //if (TSMGetDeadKeyState() != 0) {
4632N/A // testDeadChar = [self deadKeyCharacter];
4632N/A //}
4632N/A }
4632N/A
4632N/A if (testChar != 0) {
4632N/A returnValue = NsCharToJavaChar(testChar, [event modifierFlags]);
4632N/A } else if (testDeadChar != 0) {
4632N/A returnValue = NsCharToJavaChar(testDeadChar, [event modifierFlags]);
4632N/A } else {
4632N/A returnValue = java_awt_event_KeyEvent_CHAR_UNDEFINED;
4632N/A }
4632N/A break;
4632N/A
4632N/A default:
4632N/A //[NSException raise:@"AWT error" format:@"Attempt to get character code from non-key event!"];
4632N/A break;
4632N/A }
4632N/A
4632N/A return returnValue;
4632N/A}
4632N/A
4632N/A/*
4632N/Astatic jchar
4632N/AGetDeadKeyCharacter(NSEvent *event)
4632N/A{
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 // return 0;
4632N/A //}
4632N/A
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
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
4632N/A unichar returnValue = 0;
4632N/A const UInt16 VIRTUAL_KEY_SPACE = 49;
4632N/A UInt32 deadKeyState = 0;
4632N/A UInt32 appkitFlags = [event modifierFlags];
4632N/A UniCharCount actualStringLength;
4632N/A UniChar unicodeInputString[16];
4632N/A TISInputSourceRef keyLayout;
4632N/A const void *chrData;
4632N/A
4632N/A keyLayout = TISCopyCurrentKeyboardLayoutInputSource();
4632N/A CFDataRef cfUchrData =
4632N/A TISGetInputSourceProperty(keyLayout, kTISPropertyUnicodeKeyLayoutData);
4632N/A
4632N/A if (cfUchrData == NULL) {
4632N/A return returnValue;
4632N/A }
4632N/A
4632N/A // The actual 'uchr' table is inside the CFDataRef.
4632N/A chrData = CFDataGetBytePtr(cfUchrData);
4632N/A
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
4632N/A if (noErr == UCKeyTranslate(chrData,
4632N/A VIRTUAL_KEY_SPACE,
4632N/A ([event type] == NSKeyDown ? kUCKeyActionDown : kUCKeyActionUp),
4632N/A keyEventModifiers,
4632N/A keyboardType,
4632N/A kUCKeyTranslateNoDeadKeysMask,
4632N/A &deadKeyState,
4632N/A 16,
4632N/A &actualStringLength,
4632N/A unicodeInputString))
4632N/A {
4632N/A if (actualStringLength > 0) {
4632N/A returnValue = unicodeInputString[0];
4632N/A }
4632N/A }
4632N/A
4632N/A return returnValue;
4632N/A}
4632N/A*/
4632N/A
4655N/A
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.
4655N/A
4632N/Avoid
4632N/ADeliverJavaKeyEvent(JNIEnv *env, NSEvent *event, jobject peer)
4632N/A{
4632N/A jint javaKeyType = java_awt_event_KeyEvent_KEY_PRESSED;
4632N/A jint javaKeyCode = java_awt_event_KeyEvent_VK_UNDEFINED;
4632N/A jint javaKeyLocation = java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN;
4632N/A NSString *chars = nil;
4632N/A BOOL postsTyped;
4632N/A unichar testChar = java_awt_event_KeyEvent_CHAR_UNDEFINED;
4632N/A unichar testDeadChar = 0;
4632N/A jint javaModifiers = 0;
4632N/A
4632N/A switch ([event type]) {
4632N/A case NSFlagsChanged:
4632N/A NsKeyModifiersToJavaKeyInfo([event modifierFlags],
4632N/A [event keyCode],
4632N/A &javaKeyCode,
4632N/A &javaKeyLocation,
4632N/A &javaKeyType);
4632N/A break;
4632N/A
4632N/A case NSKeyDown:
4632N/A case NSKeyUp:
4632N/A chars = [event charactersIgnoringModifiers];
4632N/A if ([chars length] > 0) {
4632N/A testChar = [chars characterAtIndex:0];
4632N/A }
4632N/A
5337N/A javaModifiers = NsKeyModifiersToJavaModifiers([event modifierFlags], TRUE);
4632N/A
5368N/A NsCharToJavaVirtualKeyCode(testChar, NO,
4632N/A [event modifierFlags], [event keyCode],
5368N/A &javaKeyCode, &javaKeyLocation, &postsTyped, &testDeadChar);
4632N/A if( !postsTyped ) {
4632N/A testChar = java_awt_event_KeyEvent_CHAR_UNDEFINED;
4632N/A }
4632N/A
4632N/A javaKeyType = ([event type] == NSKeyDown) ?
4632N/A java_awt_event_KeyEvent_KEY_PRESSED :
4632N/A java_awt_event_KeyEvent_KEY_RELEASED;
4632N/A break;
4632N/A
4632N/A default:
4632N/A //[NSException raise:@"AWT error" format:@"Attempt to get virtual key code from non-key event!"];
4632N/A break;
4632N/A }
4632N/A
4632N/A if (env != NULL) {
4632N/A static JNF_CLASS_CACHE(jc_CPlatformView, "sun/lwawt/macosx/CPlatformView");
4632N/A static JNF_MEMBER_CACHE(jm_deliverKeyEvent, jc_CPlatformView, "deliverKeyEvent", "(IICII)V");
4632N/A JNFCallVoidMethod(env, peer, jm_deliverKeyEvent,
4632N/A javaKeyType, javaModifiers,
4632N/A testChar, javaKeyCode, javaKeyLocation);
4632N/A }
4632N/A}
4632N/A
4655N/Ajint GetJavaMouseModifiers(NSInteger button, NSUInteger modifierFlags)
4632N/A{
4632N/A // Mousing needs the key modifiers
5337N/A jint modifiers = NsKeyModifiersToJavaModifiers(modifierFlags, TRUE);
4632N/A
4632N/A
4632N/A /*
4632N/A * Ask Quartz about mouse buttons state
4632N/A */
4632N/A
4632N/A if (CGEventSourceButtonState(kCGEventSourceStateCombinedSessionState,
4632N/A kCGMouseButtonLeft)) {
4632N/A modifiers |= java_awt_event_InputEvent_BUTTON1_DOWN_MASK;
4632N/A }
4632N/A
4632N/A if (CGEventSourceButtonState(kCGEventSourceStateCombinedSessionState,
4632N/A kCGMouseButtonRight)) {
4632N/A modifiers |= java_awt_event_InputEvent_BUTTON3_DOWN_MASK;
4632N/A }
4632N/A
4632N/A if (CGEventSourceButtonState(kCGEventSourceStateCombinedSessionState,
4632N/A kCGMouseButtonCenter)) {
4632N/A modifiers |= java_awt_event_InputEvent_BUTTON2_DOWN_MASK;
4632N/A }
4632N/A
4734N/A NSInteger extraButton = 3;
4734N/A for (; extraButton < gNumberOfButtons; extraButton++) {
4632N/A if (CGEventSourceButtonState(kCGEventSourceStateCombinedSessionState,
4734N/A extraButton)) {
4734N/A modifiers |= gButtonDownMasks[extraButton];
4632N/A }
4632N/A }
4632N/A
4632N/A return modifiers;
4632N/A}
4632N/A
4632N/A/*
4632N/A * Converts an NSEvent button number to a MouseEvent constant.
4632N/A */
4632N/Astatic jint
4632N/ANSButtonToJavaButton(NSInteger nsButtonNumber)
4632N/A{
4632N/A jint jbutton = java_awt_event_MouseEvent_NOBUTTON;
4632N/A
4632N/A if (nsButtonNumber == 0) { // left
4632N/A jbutton = java_awt_event_MouseEvent_BUTTON1;
4632N/A } else if (nsButtonNumber == 1) { // right
4632N/A jbutton = java_awt_event_MouseEvent_BUTTON3;
4632N/A } else if (nsButtonNumber == 2) { // middle
4632N/A jbutton = java_awt_event_MouseEvent_BUTTON2;
4632N/A }
4632N/A
4632N/A return jbutton;
4632N/A}
4632N/A
4632N/A
4632N/Astatic BOOL isDragging = NO;
4632N/A
4632N/Avoid
4632N/ADeliverMouseClickedEvent(JNIEnv *env, NSEvent *event, jobject peer)
4632N/A{
4632N/A NSPoint pt = [event locationInWindow];
4632N/A NSPoint pOnScreen = [NSEvent mouseLocation];
4632N/A jint etype = java_awt_event_MouseEvent_MOUSE_CLICKED;
4655N/A jint modifiers = GetJavaMouseModifiers([event buttonNumber], [event modifierFlags]);
4632N/A jint clickCount = [event clickCount];
4632N/A jint button = NSButtonToJavaButton([event buttonNumber]);
4632N/A
4632N/A if (env != NULL) {
4632N/A static JNF_CLASS_CACHE(jc_CPlatformView, "sun/lwawt/macosx/CPlatformView");
4632N/A static JNF_MEMBER_CACHE(jm_deliverMouseEvent, jc_CPlatformView,
4632N/A "deliverMouseEvent", "(IIIIFFFF)V");
4632N/A JNFCallVoidMethod(env, peer, jm_deliverMouseEvent,
4632N/A etype, modifiers,
4632N/A clickCount, button,
4632N/A pt.x, pt.y,
4632N/A pOnScreen.x, pOnScreen.y);
4632N/A }
4632N/A}
4632N/A
4632N/A/*
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 *
4632N/A * TODO: some duplicated effort here; could just fold it
4632N/A * into DeliverJavaKeyEvent...
4632N/A */
4632N/Astatic void
4632N/ADeliverKeyTypedEvents(JNIEnv *env, NSEvent *nsEvent, jobject peer)
4632N/A{
4632N/A if (peer == NULL) {
4632N/A return;
4632N/A }
4632N/A
4632N/A jint javaKeyCode, javaKeyLocation;
4632N/A BOOL postsTyped = NO;
4632N/A unichar testChar, testDeadChar = 0;
5337N/A jint javaModifiers = NsKeyModifiersToJavaModifiers([nsEvent modifierFlags], TRUE);
4632N/A
4632N/A NSString *theChars = [nsEvent characters];
4632N/A unsigned i, stringLength = [theChars length];
4632N/A
4632N/A for (i = 0; i < stringLength; i++) {
4632N/A testChar = [theChars characterAtIndex:i];
5368N/A NsCharToJavaVirtualKeyCode(testChar, NO,
4632N/A [nsEvent modifierFlags], [nsEvent keyCode],
5368N/A &javaKeyCode, &javaKeyLocation, &postsTyped, &testDeadChar);
4632N/A
4632N/A if (postsTyped) {
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 unichar theChar = GetJavaCharacter(nsEvent, i);
4632N/A if (theChar != java_awt_event_KeyEvent_CHAR_UNDEFINED) {
4632N/A if (env != NULL) {
4632N/A static JNF_CLASS_CACHE(jc_CPlatformView,
4632N/A "sun/lwawt/macosx/CPlatformView");
4632N/A static JNF_MEMBER_CACHE(jm_deliverKeyEvent, jc_CPlatformView,
4632N/A "deliverKeyEvent", "(IICII)V");
4632N/A JNFCallVoidMethod(env, peer, jm_deliverKeyEvent,
4632N/A java_awt_event_KeyEvent_KEY_TYPED,
4632N/A javaModifiers,
4632N/A theChar,
4632N/A java_awt_event_KeyEvent_VK_UNDEFINED,
4632N/A java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN);
4632N/A }
4632N/A }
4632N/A }
4632N/A }
4632N/A}
4632N/A
4632N/A/*
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 *
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 *
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 * intervening drag:
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 *
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 */
4632N/Avoid
4632N/ASendAdditionalJavaEvents(JNIEnv *env, NSEvent *nsEvent, jobject peer)
4632N/A{
4632N/A AWT_ASSERT_APPKIT_THREAD;
4632N/A
4632N/A NSEventType type = [nsEvent type];
4632N/A switch (type) {
4632N/A case NSKeyDown:
4632N/A break;
4632N/A
4632N/A case NSLeftMouseUp:
4632N/A case NSRightMouseUp:
4632N/A case NSOtherMouseUp:
4632N/A // TODO: we may need to pull in changedDragToMove here...
4632N/A //if (!isDragging && ([NSViewAWT changedDragToMove]==NO)) {
4632N/A if (!isDragging) {
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 DeliverMouseClickedEvent(env, nsEvent, peer);
4632N/A }
4632N/A break;
4632N/A
4632N/A// TODO: to be implemented...
4632N/A#if 0
4632N/A case NSLeftMouseDragged:
4632N/A case NSRightMouseDragged:
4632N/A case NSOtherMouseDragged:
4632N/A //
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 // then forward.
4632N/A //
4632N/A NSView *hitView = [[source model] hitTest:[nsEvent locationInWindow]];
4632N/A
4632N/A if ((hitView != nil) &&
4632N/A ([hitView conformsToProtocol:@protocol(AWTPeerControl)]))
4632N/A {
4632N/A if (sLastMouseDraggedView == nil) {
4632N/A sLastMouseDraggedView = hitView;
4632N/A }
4632N/A else if (hitView != sLastMouseDraggedView) {
4632N/A // We know sLastMouseDraggedView is a AWTPeerControl.
4632N/A jobject lastPeer =
4632N/A [(id <AWTPeerControl>)sLastMouseDraggedView peer];
4632N/A
4632N/A // Send mouseExit to sLastMouseDraggedView
4632N/A jobject exitEvent =
4632N/A makeMouseEvent(env, nsEvent, lastPeer,
4632N/A sLastMouseDraggedView,
4632N/A java_awt_event_MouseEvent_MOUSE_EXITED);
4632N/A pushEventForward(exitEvent, env);
4632N/A (*env)->DeleteLocalRef(env, exitEvent);
4632N/A
4632N/A // Send mouseEnter to hitView
4632N/A jobject enterEvent =
4632N/A makeMouseEvent(env, nsEvent, peer, hitView,
4632N/A java_awt_event_MouseEvent_MOUSE_ENTERED);
4632N/A pushEventForward(enterEvent, env);
4632N/A
4632N/A (*env)->DeleteLocalRef(env, enterEvent);
4632N/A
4632N/A // Set sLastMouseDraggedView = hitView
4632N/A sLastMouseDraggedView = hitView;
4632N/A }
4632N/A }
4632N/A break;
4632N/A#endif
4632N/A
4632N/A default:
4632N/A break;
4632N/A }
4632N/A}
4632N/A
4632N/Ajlong UTC(NSEvent *event) {
4632N/A struct timeval tv;
4632N/A if (gettimeofday(&tv, NULL) == 0) {
4632N/A long long sec = (long long)tv.tv_sec;
4632N/A return (sec*1000) + (tv.tv_usec/1000);
4632N/A }
4632N/A return 0;
4632N/A}
4632N/A
4632N/AJNIEXPORT void JNICALL
4632N/AJava_java_awt_AWTEvent_nativeSetSource
4632N/A (JNIEnv *env, jobject self, jobject newSource)
4632N/A{
4632N/A}
4655N/A
4655N/A/*
4655N/A * Class: sun_lwawt_macosx_event_NSEvent
4781N/A * Method: nsToJavaMouseModifiers
4655N/A * Signature: (II)I
4655N/A */
4655N/AJNIEXPORT jint JNICALL
4781N/AJava_sun_lwawt_macosx_event_NSEvent_nsToJavaMouseModifiers
4655N/A(JNIEnv *env, jclass cls, jint buttonNumber, jint modifierFlags)
4655N/A{
4655N/A jint jmodifiers = 0;
4655N/A
4655N/AJNF_COCOA_ENTER(env);
4730N/A
4655N/A jmodifiers = GetJavaMouseModifiers(buttonNumber, modifierFlags);
4730N/A
4655N/AJNF_COCOA_EXIT(env);
4655N/A
4655N/A return jmodifiers;
4655N/A}
4655N/A
4655N/A/*
4655N/A * Class: sun_lwawt_macosx_event_NSEvent
4781N/A * Method: nsToJavaKeyModifiers
4655N/A * Signature: (I)I
4655N/A */
4655N/AJNIEXPORT jint JNICALL
4781N/AJava_sun_lwawt_macosx_event_NSEvent_nsToJavaKeyModifiers
4655N/A(JNIEnv *env, jclass cls, jint modifierFlags)
4655N/A{
4655N/A jint jmodifiers = 0;
4655N/A
4655N/AJNF_COCOA_ENTER(env);
4730N/A
5337N/A jmodifiers = NsKeyModifiersToJavaModifiers(modifierFlags, TRUE);
4730N/A
4655N/AJNF_COCOA_EXIT(env);
4730N/A
4655N/A return jmodifiers;
4655N/A}
4655N/A
4655N/A/*
4655N/A * Class: sun_lwawt_macosx_event_NSEvent
4781N/A * Method: nsToJavaKeyInfo
4655N/A * Signature: ([I[I)Z
4655N/A */
4655N/AJNIEXPORT jboolean JNICALL
4781N/AJava_sun_lwawt_macosx_event_NSEvent_nsToJavaKeyInfo
4655N/A(JNIEnv *env, jclass cls, jintArray inData, jintArray outData)
4655N/A{
4655N/A BOOL postsTyped = NO;
4730N/A
4655N/AJNF_COCOA_ENTER(env);
4730N/A
4655N/A jboolean copy = JNI_FALSE;
4655N/A jint *data = (*env)->GetIntArrayElements(env, inData, &copy);
4655N/A
4655N/A // in = [testChar, testDeadChar, modifierFlags, keyCode]
4655N/A jchar testChar = (jchar)data[0];
5368N/A BOOL isDeadChar = (data[1] != 0);
4655N/A jint modifierFlags = data[2];
4655N/A jshort keyCode = (jshort)data[3];
4655N/A
4655N/A jint jkeyCode = java_awt_event_KeyEvent_VK_UNDEFINED;
4655N/A jint jkeyLocation = java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN;
5368N/A jchar testDeadChar = 0;
4730N/A
5368N/A NsCharToJavaVirtualKeyCode((unichar)testChar, isDeadChar,
4655N/A (NSUInteger)modifierFlags, (unsigned short)keyCode,
5368N/A &jkeyCode, &jkeyLocation, &postsTyped, &testDeadChar);
4655N/A
5368N/A // out = [jkeyCode, jkeyLocation, deadKeyChar];
4655N/A (*env)->SetIntArrayRegion(env, outData, 0, 1, &jkeyCode);
4655N/A (*env)->SetIntArrayRegion(env, outData, 1, 1, &jkeyLocation);
5368N/A (*env)->SetIntArrayRegion(env, outData, 2, 1, (jint *)&testDeadChar);
5368N/A
4734N/A (*env)->ReleaseIntArrayElements(env, inData, data, 0);
5368N/A
4655N/AJNF_COCOA_EXIT(env);
4655N/A
4655N/A return postsTyped;
4655N/A}
4655N/A
4655N/A/*
4655N/A * Class: sun_lwawt_macosx_event_NSEvent
4655N/A * Method: nsKeyModifiersToJavaKeyInfo
4655N/A * Signature: ([I[I)V
4655N/A */
4655N/AJNIEXPORT void JNICALL
4655N/AJava_sun_lwawt_macosx_event_NSEvent_nsKeyModifiersToJavaKeyInfo
4655N/A(JNIEnv *env, jclass cls, jintArray inData, jintArray outData)
4655N/A{
4655N/AJNF_COCOA_ENTER(env);
4730N/A
4655N/A jboolean copy = JNI_FALSE;
4655N/A jint *data = (*env)->GetIntArrayElements(env, inData, &copy);
4730N/A
4655N/A // in = [modifierFlags, keyCode]
4655N/A jint modifierFlags = data[0];
4655N/A jshort keyCode = (jshort)data[1];
4655N/A
4655N/A jint jkeyCode = java_awt_event_KeyEvent_VK_UNDEFINED;
4655N/A jint jkeyLocation = java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN;
4655N/A jint jkeyType = java_awt_event_KeyEvent_KEY_PRESSED;
4730N/A
4655N/A NsKeyModifiersToJavaKeyInfo(modifierFlags,
4655N/A keyCode,
4655N/A &jkeyCode,
4655N/A &jkeyLocation,
4655N/A &jkeyType);
4655N/A
4655N/A // out = [jkeyCode, jkeyLocation, jkeyType];
4655N/A (*env)->SetIntArrayRegion(env, outData, 0, 1, &jkeyCode);
4730N/A (*env)->SetIntArrayRegion(env, outData, 1, 1, &jkeyLocation);
4655N/A (*env)->SetIntArrayRegion(env, outData, 2, 1, &jkeyType);
4730N/A
4734N/A (*env)->ReleaseIntArrayElements(env, inData, data, 0);
5368N/A
4655N/AJNF_COCOA_EXIT(env);
4655N/A}
4790N/A
4790N/A/*
4790N/A * Class: sun_lwawt_macosx_event_NSEvent
4790N/A * Method: nsToJavaChar
4790N/A * Signature: (CI)C
4790N/A */
4790N/AJNIEXPORT jint JNICALL
4790N/AJava_sun_lwawt_macosx_event_NSEvent_nsToJavaChar
4790N/A(JNIEnv *env, jclass cls, char nsChar, jint modifierFlags)
4790N/A{
4790N/A jchar javaChar = 0;
5368N/A
4790N/AJNF_COCOA_ENTER(env);
5368N/A
4790N/A javaChar = NsCharToJavaChar(nsChar, modifierFlags);
4790N/A
4790N/AJNF_COCOA_EXIT(env);
5368N/A
4790N/A return javaChar;
4790N/A}