1 /*
   2  * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 #import <JavaNativeFoundation/JavaNativeFoundation.h>
  27 #import <JavaRuntimeSupport/JavaRuntimeSupport.h>
  28 #import <sys/time.h>
  29 
  30 #import "LWCToolkit.h"
  31 #import "ThreadUtilities.h"
  32 
  33 #import "java_awt_event_InputEvent.h"
  34 #import "java_awt_event_KeyEvent.h"
  35 #import "java_awt_event_MouseEvent.h"
  36 
  37 /*
  38  * Table to map typed characters to their Java virtual key equivalent and back.
  39  * We use the incoming unichar (ignoring all modifiers) and try to figure out
  40  * which virtual key code is appropriate. A lot of them just have direct
  41  * mappings (the function keys, arrow keys, etc.) so they aren't a problem.
  42  * We had to do something a little funky to catch the keys on the numeric
  43  * key pad (i.e. using event mask to distinguish between period on regular
  44  * keyboard and decimal on keypad). We also have to do something incredibly
  45  * hokey with regards to the shifted punctuation characters. For examples,
  46  * consider '&' which is usually Shift-7.  For the Java key typed events,
  47  * that's no problem, we just say pass the unichar. But for the
  48  * KeyPressed/Released events, we need to identify the virtual key code
  49  * (which roughly correspond to hardware keys) which means we are supposed
  50  * to say the virtual 7 key was pressed.  But how are we supposed to know
  51  * when we get a punctuation char what was the real hardware key was that
  52  * was pressed?  Although '&' often comes from Shift-7 the keyboard can be
  53  * remapped!  I don't think there really is a good answer, and hopefully
  54  * all good applets are only interested in logical key typed events not
  55  * press/release.  Meanwhile, we are hard-coding the shifted punctuation
  56  * to trigger the virtual keys that are the expected ones under a standard
  57  * keymapping. Looking at Windows & Mac, they don't actually do this, the
  58  * Mac seems to just put the ascii code in for the shifted punctuation
  59  * (which means they actually end up with bogus key codes on the Java side),
  60  * Windows I can't even figure out what it's doing.
  61  */
  62 #define KL_STANDARD java_awt_event_KeyEvent_KEY_LOCATION_STANDARD
  63 #define KL_NUMPAD   java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD
  64 #define KL_UNKNOWN  java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN
  65 static struct _key
  66 {
  67     unsigned short keyCode;
  68     BOOL postsTyped;
  69     jint javaKeyLocation;
  70     jint javaKeyCode;
  71 }
  72 const keyTable[] =
  73 {
  74     {0x00, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_A},
  75     {0x01, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_S},
  76     {0x02, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_D},
  77     {0x03, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_F},
  78     {0x04, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_H},
  79     {0x05, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_G},
  80     {0x06, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_Z},
  81     {0x07, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_X},
  82     {0x08, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_C},
  83     {0x09, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_V},
  84     {0x0A, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_BACK_QUOTE},
  85     {0x0B, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_B},
  86     {0x0C, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_Q},
  87     {0x0D, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_W},
  88     {0x0E, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_E},
  89     {0x0F, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_R},
  90     {0x10, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_Y},
  91     {0x11, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_T},
  92     {0x12, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_1},
  93     {0x13, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_2},
  94     {0x14, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_3},
  95     {0x15, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_4},
  96     {0x16, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_6},
  97     {0x17, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_5},
  98     {0x18, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_EQUALS},
  99     {0x19, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_9},
 100     {0x1A, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_7},
 101     {0x1B, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_MINUS},
 102     {0x1C, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_8},
 103     {0x1D, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_0},
 104     {0x1E, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_CLOSE_BRACKET},
 105     {0x1F, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_O},
 106     {0x20, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_U},
 107     {0x21, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_OPEN_BRACKET},
 108     {0x22, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_I},
 109     {0x23, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_P},
 110     {0x24, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_ENTER},
 111     {0x25, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_L},
 112     {0x26, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_J},
 113     {0x27, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_QUOTE},
 114     {0x28, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_K},
 115     {0x29, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_SEMICOLON},
 116     {0x2A, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_BACK_SLASH},
 117     {0x2B, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_COMMA},
 118     {0x2C, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_SLASH},
 119     {0x2D, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_N},
 120     {0x2E, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_M},
 121     {0x2F, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_PERIOD},
 122     {0x30, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_TAB},
 123     {0x31, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_SPACE},
 124     {0x32, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_BACK_QUOTE},
 125     {0x33, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_BACK_SPACE},
 126     {0x34, YES, KL_NUMPAD,   java_awt_event_KeyEvent_VK_ENTER},
 127     {0x35, NO,  KL_STANDARD, java_awt_event_KeyEvent_VK_ESCAPE},
 128     {0x36, NO,  KL_UNKNOWN,  java_awt_event_KeyEvent_VK_UNDEFINED},
 129     {0x37, NO,  KL_UNKNOWN,  java_awt_event_KeyEvent_VK_META},      // ****
 130     {0x38, NO,  KL_UNKNOWN,  java_awt_event_KeyEvent_VK_SHIFT},     // ****
 131     {0x39, NO,  KL_STANDARD, java_awt_event_KeyEvent_VK_CAPS_LOCK},
 132     {0x3A, NO,  KL_UNKNOWN,  java_awt_event_KeyEvent_VK_ALT},       // ****
 133     {0x3B, NO,  KL_UNKNOWN,  java_awt_event_KeyEvent_VK_CONTROL},   // ****
 134     {0x3C, NO,  KL_UNKNOWN,  java_awt_event_KeyEvent_VK_UNDEFINED},
 135     {0x3D, NO,  KL_UNKNOWN,  java_awt_event_KeyEvent_VK_UNDEFINED},
 136     {0x3E, NO,  KL_UNKNOWN,  java_awt_event_KeyEvent_VK_UNDEFINED},
 137     {0x3F, NO,  KL_UNKNOWN,  java_awt_event_KeyEvent_VK_UNDEFINED}, // the 'fn' key on PowerBooks
 138     {0x40, NO,  KL_UNKNOWN,  java_awt_event_KeyEvent_VK_UNDEFINED},
 139     {0x41, YES, KL_NUMPAD,   java_awt_event_KeyEvent_VK_DECIMAL},
 140     {0x42, NO,  KL_UNKNOWN,  java_awt_event_KeyEvent_VK_UNDEFINED},
 141     {0x43, YES, KL_NUMPAD,   java_awt_event_KeyEvent_VK_MULTIPLY},
 142     {0x44, NO,  KL_UNKNOWN,  java_awt_event_KeyEvent_VK_UNDEFINED},
 143     {0x45, YES, KL_NUMPAD,   java_awt_event_KeyEvent_VK_ADD},
 144     {0x46, NO,  KL_UNKNOWN,  java_awt_event_KeyEvent_VK_UNDEFINED},
 145     {0x47, NO,  KL_NUMPAD,   java_awt_event_KeyEvent_VK_CLEAR},
 146     {0x48, NO,  KL_UNKNOWN,  java_awt_event_KeyEvent_VK_UNDEFINED},
 147     {0x49, NO,  KL_UNKNOWN,  java_awt_event_KeyEvent_VK_UNDEFINED},
 148     {0x4A, NO,  KL_UNKNOWN,  java_awt_event_KeyEvent_VK_UNDEFINED},
 149     {0x4B, YES, KL_NUMPAD,   java_awt_event_KeyEvent_VK_DIVIDE},
 150     {0x4C, YES, KL_NUMPAD,   java_awt_event_KeyEvent_VK_ENTER},
 151     {0x4D, NO,  KL_UNKNOWN,  java_awt_event_KeyEvent_VK_UNDEFINED},
 152     {0x4E, YES, KL_NUMPAD,   java_awt_event_KeyEvent_VK_SUBTRACT},
 153     {0x4F, NO,  KL_UNKNOWN,  java_awt_event_KeyEvent_VK_UNDEFINED},
 154     {0x50, NO,  KL_UNKNOWN,  java_awt_event_KeyEvent_VK_UNDEFINED},
 155     {0x51, YES, KL_NUMPAD,   java_awt_event_KeyEvent_VK_EQUALS},
 156     {0x52, YES, KL_NUMPAD,   java_awt_event_KeyEvent_VK_NUMPAD0},
 157     {0x53, YES, KL_NUMPAD,   java_awt_event_KeyEvent_VK_NUMPAD1},
 158     {0x54, YES, KL_NUMPAD,   java_awt_event_KeyEvent_VK_NUMPAD2},
 159     {0x55, YES, KL_NUMPAD,   java_awt_event_KeyEvent_VK_NUMPAD3},
 160     {0x56, YES, KL_NUMPAD,   java_awt_event_KeyEvent_VK_NUMPAD4},
 161     {0x57, YES, KL_NUMPAD,   java_awt_event_KeyEvent_VK_NUMPAD5},
 162     {0x58, YES, KL_NUMPAD,   java_awt_event_KeyEvent_VK_NUMPAD6},
 163     {0x59, YES, KL_NUMPAD,   java_awt_event_KeyEvent_VK_NUMPAD7},
 164     {0x5A, NO,  KL_UNKNOWN,  java_awt_event_KeyEvent_VK_UNDEFINED},
 165     {0x5B, YES, KL_NUMPAD,   java_awt_event_KeyEvent_VK_NUMPAD8},
 166     {0x5C, YES, KL_NUMPAD,   java_awt_event_KeyEvent_VK_NUMPAD9},
 167     {0x5D, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_BACK_SLASH}, // This is a combo yen/backslash on JIS keyboards.
 168     {0x5E, YES, KL_NUMPAD,   java_awt_event_KeyEvent_VK_UNDERSCORE},
 169     {0x5F, YES, KL_NUMPAD,   java_awt_event_KeyEvent_VK_COMMA},
 170     {0x60, NO,  KL_STANDARD, java_awt_event_KeyEvent_VK_F5},
 171     {0x61, NO,  KL_STANDARD, java_awt_event_KeyEvent_VK_F6},
 172     {0x62, NO,  KL_STANDARD, java_awt_event_KeyEvent_VK_F7},
 173     {0x63, NO,  KL_STANDARD, java_awt_event_KeyEvent_VK_F3},
 174     {0x64, NO,  KL_STANDARD, java_awt_event_KeyEvent_VK_F8},
 175     {0x65, NO,  KL_STANDARD, java_awt_event_KeyEvent_VK_F9},
 176     {0x66, NO,  KL_STANDARD, java_awt_event_KeyEvent_VK_ALPHANUMERIC},
 177     {0x67, NO,  KL_STANDARD, java_awt_event_KeyEvent_VK_F11},
 178     {0x68, NO,  KL_STANDARD, java_awt_event_KeyEvent_VK_KATAKANA},
 179     {0x69, NO,  KL_STANDARD, java_awt_event_KeyEvent_VK_F13},
 180     {0x6A, NO,  KL_STANDARD, java_awt_event_KeyEvent_VK_F16},
 181     {0x6B, NO,  KL_STANDARD, java_awt_event_KeyEvent_VK_F14},
 182     {0x6C, NO,  KL_UNKNOWN,  java_awt_event_KeyEvent_VK_UNDEFINED},
 183     {0x6D, NO,  KL_STANDARD, java_awt_event_KeyEvent_VK_F10},
 184     {0x6E, NO,  KL_UNKNOWN,  java_awt_event_KeyEvent_VK_UNDEFINED},
 185     {0x6F, NO,  KL_STANDARD, java_awt_event_KeyEvent_VK_F12},
 186     {0x70, NO,  KL_UNKNOWN,  java_awt_event_KeyEvent_VK_UNDEFINED},
 187     {0x71, NO,  KL_STANDARD, java_awt_event_KeyEvent_VK_F15},
 188     {0x72, NO,  KL_STANDARD, java_awt_event_KeyEvent_VK_HELP},
 189     {0x73, NO,  KL_STANDARD, java_awt_event_KeyEvent_VK_HOME},
 190     {0x74, NO,  KL_STANDARD, java_awt_event_KeyEvent_VK_PAGE_UP},
 191     {0x75, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_DELETE},
 192     {0x76, NO,  KL_STANDARD, java_awt_event_KeyEvent_VK_F4},
 193     {0x77, NO,  KL_STANDARD, java_awt_event_KeyEvent_VK_END},
 194     {0x78, NO,  KL_STANDARD, java_awt_event_KeyEvent_VK_F2},
 195     {0x79, NO,  KL_STANDARD, java_awt_event_KeyEvent_VK_PAGE_DOWN},
 196     {0x7A, NO,  KL_STANDARD, java_awt_event_KeyEvent_VK_F1},
 197     {0x7B, NO,  KL_STANDARD, java_awt_event_KeyEvent_VK_LEFT},
 198     {0x7C, NO,  KL_STANDARD, java_awt_event_KeyEvent_VK_RIGHT},
 199     {0x7D, NO,  KL_STANDARD, java_awt_event_KeyEvent_VK_DOWN},
 200     {0x7E, NO,  KL_STANDARD, java_awt_event_KeyEvent_VK_UP},
 201     {0x7F, NO,  KL_UNKNOWN,  java_awt_event_KeyEvent_VK_UNDEFINED},
 202 };
 203 
 204 /*
 205  * This table was stolen from the Windows implementation for mapping
 206  * Unicode values to VK codes for dead keys.  On Windows, some layouts
 207  * return ASCII punctuation for dead accents, while some return spacing
 208  * accent chars, so both should be listed.  However, in all of the
 209  * keyboard layouts I tried only the Unicode values are used.
 210  */
 211 struct CharToVKEntry {
 212     UniChar c;
 213     jint javaKey;
 214 };
 215 static const struct CharToVKEntry charToDeadVKTable[] = {
 216     {0x0060, java_awt_event_KeyEvent_VK_DEAD_GRAVE},
 217     {0x00B4, java_awt_event_KeyEvent_VK_DEAD_ACUTE},
 218     {0x0384, java_awt_event_KeyEvent_VK_DEAD_ACUTE}, // Unicode "GREEK TONOS" -- Greek keyboard, semicolon key
 219     {0x005E, java_awt_event_KeyEvent_VK_DEAD_CIRCUMFLEX},
 220     {0x007E, java_awt_event_KeyEvent_VK_DEAD_TILDE},
 221     {0x02DC, java_awt_event_KeyEvent_VK_DEAD_TILDE}, // Unicode "SMALL TILDE"
 222     {0x00AF, java_awt_event_KeyEvent_VK_DEAD_MACRON},
 223     {0x02D8, java_awt_event_KeyEvent_VK_DEAD_BREVE},
 224     {0x02D9, java_awt_event_KeyEvent_VK_DEAD_ABOVEDOT},
 225     {0x00A8, java_awt_event_KeyEvent_VK_DEAD_DIAERESIS},
 226     {0x02DA, java_awt_event_KeyEvent_VK_DEAD_ABOVERING},
 227     {0x02DD, java_awt_event_KeyEvent_VK_DEAD_DOUBLEACUTE},
 228     {0x02C7, java_awt_event_KeyEvent_VK_DEAD_CARON},
 229     {0x00B8, java_awt_event_KeyEvent_VK_DEAD_CEDILLA},
 230     {0x02DB, java_awt_event_KeyEvent_VK_DEAD_OGONEK},
 231     {0x037A, java_awt_event_KeyEvent_VK_DEAD_IOTA},
 232     {0x309B, java_awt_event_KeyEvent_VK_DEAD_VOICED_SOUND},
 233     {0x309C, java_awt_event_KeyEvent_VK_DEAD_SEMIVOICED_SOUND},
 234     {0,0}
 235 };
 236 
 237 // TODO: some constants below are part of CGS (private interfaces)...
 238 // for now we will look at the raw key code to determine left/right status
 239 // but not sure this is foolproof...
 240 static struct _nsKeyToJavaModifier
 241 {
 242     NSUInteger nsMask;
 243     //NSUInteger cgsLeftMask;
 244     //NSUInteger cgsRightMask;
 245     unsigned short leftKeyCode;
 246     unsigned short rightKeyCode;
 247     jint javaMask;
 248     jint javaKey;
 249 }
 250 const nsKeyToJavaModifierTable[] =
 251 {
 252     {
 253         NSAlphaShiftKeyMask,
 254         0,
 255         0,
 256         0, // no Java equivalent
 257         java_awt_event_KeyEvent_VK_CAPS_LOCK
 258     },
 259     {
 260         NSShiftKeyMask,
 261         //kCGSFlagsMaskAppleShiftKey,
 262         //kCGSFlagsMaskAppleRightShiftKey,
 263         56,
 264         60,
 265         java_awt_event_InputEvent_SHIFT_DOWN_MASK,
 266         java_awt_event_KeyEvent_VK_SHIFT
 267     },
 268     {
 269         NSControlKeyMask,
 270         //kCGSFlagsMaskAppleControlKey,
 271         //kCGSFlagsMaskAppleRightControlKey,
 272         59,
 273         62,
 274         java_awt_event_InputEvent_CTRL_DOWN_MASK,
 275         java_awt_event_KeyEvent_VK_CONTROL
 276     },
 277     {
 278         NSAlternateKeyMask,
 279         //kCGSFlagsMaskAppleLeftAlternateKey,
 280         //kCGSFlagsMaskAppleRightAlternateKey,
 281         58,
 282         61,
 283         java_awt_event_InputEvent_ALT_DOWN_MASK,
 284         java_awt_event_KeyEvent_VK_ALT
 285     },
 286     {
 287         NSCommandKeyMask,
 288         //kCGSFlagsMaskAppleLeftCommandKey,
 289         //kCGSFlagsMaskAppleRightCommandKey,
 290         55,
 291         54,
 292         java_awt_event_InputEvent_META_DOWN_MASK,
 293         java_awt_event_KeyEvent_VK_META
 294     },
 295     // NSNumericPadKeyMask
 296     {
 297         NSHelpKeyMask,
 298         0,
 299         0,
 300         0, // no Java equivalent
 301         java_awt_event_KeyEvent_VK_HELP
 302     },
 303     // NSFunctionKeyMask
 304     {0, 0, 0, 0, 0}
 305 };
 306 
 307 /*
 308  * Almost all unicode characters just go from NS to Java with no translation.
 309  *  For the few exceptions, we handle it here with this small table.
 310  */



 311 static struct _char {
 312     NSUInteger modifier;
 313     unichar nsChar;
 314     unichar javaChar;
 315 }
 316 const charTable[] = {
 317     // map enter on keypad to same as return key
 318     {0,              NSEnterCharacter,          NSNewlineCharacter},
 319 
 320     // [3134616] return newline instead of carriage return
 321     {0,              NSCarriageReturnCharacter, NSNewlineCharacter},
 322 
 323     // "delete" means backspace in Java
 324     {0,              NSDeleteCharacter,         NSBackspaceCharacter},
 325     {0,              NSDeleteFunctionKey,     NSDeleteCharacter},
 326 
 327     // back-tab is only differentiated from tab by Shift flag
 328     {NSShiftKeyMask, NSBackTabCharacter,     NSTabCharacter},
 329 
 330     {0, 0, 0}
 331 };
 332 
 333 static unichar
 334 NsCharToJavaChar(unichar nsChar, NSUInteger modifiers)
 335 {
 336     const struct _char *cur;
 337     NSUInteger keyModifierFlags =
 338         NSShiftKeyMask | NSControlKeyMask |
 339         NSAlternateKeyMask | NSCommandKeyMask;
 340 
 341     // Mask off just the keyboard modifiers from the event modifier mask.
 342     NSUInteger testableFlags = (modifiers & keyModifierFlags);
 343 
 344     // walk through table & find the match
 345     for (cur = charTable; cur->nsChar != 0 ; cur++) {
 346         // <rdar://Problem/3476426> Need to determine if we are looking at
 347         // a plain keypress or a modified keypress.  Don't adjust the
 348         // character of a keypress with a modifier.
 349         if (cur->nsChar == nsChar) {
 350             if (cur->modifier == 0 && testableFlags == 0) {
 351                 // If the modifier field is 0, that means to transform
 352                 // this character if no additional keyboard modifiers are set.
 353                 // This lets ctrl-C be reported as ctrl-C and not transformed
 354                 // into Newline.
 355                 return cur->javaChar;
 356             } else if (cur->modifier != 0 &&
 357                        (testableFlags & cur->modifier) == testableFlags)
 358             {
 359                 // Likewise, if the modifier field is nonzero, that means
 360                 // transform this character if only these modifiers are
 361                 // set in the testable flags.
 362                 return cur->javaChar;
 363             }
 364         }
 365     }
 366 
 367     if (nsChar >= NSUpArrowFunctionKey && nsChar <= NSModeSwitchFunctionKey) {
 368         return java_awt_event_KeyEvent_CHAR_UNDEFINED;
 369     }
 370 
 371     // otherwise return character unchanged
 372     return nsChar;
 373 }
 374 
 375 /*
 376  * This is the function that uses the table above to take incoming
 377  * NSEvent keyCodes and translate to the Java virtual key code.
 378  */
 379 static void
 380 NsCharToJavaVirtualKeyCode(unichar ch, unichar deadChar,
 381                            NSUInteger flags, unsigned short key,
 382                            jint *keyCode, jint *keyLocation, BOOL *postsTyped)
 383 {
 384     static size_t size = sizeof(keyTable) / sizeof(struct _key);
 385     NSInteger offset;
 386 
 387     if (deadChar) {
 388         const struct CharToVKEntry *map;
 389         for (map = charToDeadVKTable; map->c != 0; ++map) {
 390             if (deadChar == map->c) {
 391                 *keyCode = map->javaKey;
 392                 *postsTyped = NO;
 393                 // TODO: use UNKNOWN here?
 394                 *keyLocation = java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN;
 395                 return;
 396             }
 397         }
 398         // If we got here, we keep looking for a normal key.
 399     }
 400 
 401     if ([[NSCharacterSet letterCharacterSet] characterIsMember:ch]) {
 402         // key is an alphabetic character
 403         unichar lower;
 404         lower = tolower(ch);
 405         offset = lower - 'a';
 406         if (offset >= 0 && offset <= 25) {
 407             // some chars in letter set are NOT actually A-Z characters?!
 408             // skip them...
 409             *postsTyped = YES;
 410             // do quick conversion
 411             *keyCode = java_awt_event_KeyEvent_VK_A + offset;
 412             *keyLocation = java_awt_event_KeyEvent_KEY_LOCATION_STANDARD;
 413             return;
 414         }
 415     }
 416 
 417     if ([[NSCharacterSet decimalDigitCharacterSet] characterIsMember:ch]) {
 418         // key is a digit
 419         offset = ch - '0';
 420         // make sure in range for decimal digits
 421         if (offset >= 0 && offset <= 9)    {
 422             jboolean numpad = (flags & NSNumericPadKeyMask) != 0;
 423             *postsTyped = YES;
 424             if (numpad) {
 425                 *keyCode = offset + java_awt_event_KeyEvent_VK_NUMPAD0;
 426                 *keyLocation = java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD;
 427             } else {
 428                 *keyCode = offset + java_awt_event_KeyEvent_VK_0;
 429                 *keyLocation = java_awt_event_KeyEvent_KEY_LOCATION_STANDARD;
 430             }
 431             return;
 432         }
 433     }
 434 
 435     if (key < size) {
 436         *postsTyped = keyTable[key].postsTyped;
 437         *keyCode = keyTable[key].javaKeyCode;
 438         *keyLocation = keyTable[key].javaKeyLocation;
 439     } else {
 440         // Should we report this? This means we've got a keyboard
 441         // we don't know about...
 442         *postsTyped = NO;
 443         *keyCode = java_awt_event_KeyEvent_VK_UNDEFINED;
 444         *keyLocation = java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN;
 445     }
 446 }
 447 
 448 /*
 449  * This returns the java key data for the key NSEvent modifiers
 450  * (after NSFlagChanged).
 451  */
 452 static void
 453 NsKeyModifiersToJavaKeyInfo(NSUInteger nsFlags, unsigned short eventKeyCode,
 454                             jint *javaKeyCode,
 455                             jint *javaKeyLocation,
 456                             jint *javaKeyType)
 457 {
 458     static NSUInteger sPreviousNSFlags = 0;
 459 
 460     const struct _nsKeyToJavaModifier* cur;
 461     NSUInteger oldNSFlags = sPreviousNSFlags;
 462     NSUInteger changedNSFlags = oldNSFlags ^ nsFlags;
 463     sPreviousNSFlags = nsFlags;
 464 
 465     *javaKeyCode = java_awt_event_KeyEvent_VK_UNDEFINED;
 466     *javaKeyLocation = java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN;
 467     *javaKeyType = java_awt_event_KeyEvent_KEY_PRESSED;
 468 
 469     for (cur = nsKeyToJavaModifierTable; cur->nsMask != 0; ++cur) {
 470         if (changedNSFlags & cur->nsMask) {
 471             *javaKeyCode = cur->javaKey;
 472             *javaKeyLocation = java_awt_event_KeyEvent_KEY_LOCATION_STANDARD;
 473             // TODO: uses SPI...
 474             //if (changedNSFlags & cur->cgsLeftMask) {
 475             //    *javaKeyLocation = java_awt_event_KeyEvent_KEY_LOCATION_LEFT;
 476             //} else if (changedNSFlags & cur->cgsRightMask) {
 477             //    *javaKeyLocation = java_awt_event_KeyEvent_KEY_LOCATION_RIGHT;
 478             //}
 479             if (eventKeyCode == cur->leftKeyCode) {
 480                 *javaKeyLocation = java_awt_event_KeyEvent_KEY_LOCATION_LEFT;
 481             } else if (eventKeyCode == cur->rightKeyCode) {
 482                 *javaKeyLocation = java_awt_event_KeyEvent_KEY_LOCATION_RIGHT;
 483             }
 484             *javaKeyType = (cur->nsMask & nsFlags) ?
 485                 java_awt_event_KeyEvent_KEY_PRESSED :
 486                 java_awt_event_KeyEvent_KEY_RELEASED;
 487             break;
 488         }
 489     }
 490 }
 491 
 492 /*
 493  * This returns the java modifiers for a key NSEvent.
 494  */
 495 static jint
 496 NsKeyModifiersToJavaModifiers(NSUInteger nsFlags)
 497 {
 498     jint javaModifiers = 0;
 499     const struct _nsKeyToJavaModifier* cur;
 500 
 501     for (cur = nsKeyToJavaModifierTable; cur->nsMask != 0; ++cur) {
 502         if ((cur->nsMask & nsFlags) != 0) {
 503             javaModifiers |= cur->javaMask;
 504         }
 505     }
 506 
 507     return javaModifiers;
 508 }
 509 
 510 /*
 511  * Returns the correct java character for a key event.  Most unicode
 512  * characters don't require any fussing, but a few seem to need adjusting,
 513  * see nsCharToJavaChar.
 514  */
 515 static unichar
 516 GetJavaCharacter(NSEvent *event, unsigned int index)
 517 {
 518     unichar returnValue = java_awt_event_KeyEvent_CHAR_UNDEFINED;
 519     NSString *chars = nil;
 520     unichar testChar = 0, testDeadChar = 0;
 521     jint javaModifiers = NsKeyModifiersToJavaModifiers([event modifierFlags]);
 522 
 523     switch ([event type]) {
 524     case NSFlagsChanged:
 525         // no character for modifier keys
 526         returnValue = java_awt_event_KeyEvent_CHAR_UNDEFINED;
 527         break;
 528 
 529     case NSKeyDown:
 530     case NSKeyUp:
 531         chars = [event characters];
 532         if ([chars length] > 0) {
 533             testChar = [chars characterAtIndex:index];
 534         }
 535 
 536         if (javaModifiers == 0) {
 537             // TODO: uses SPI...
 538             //if (TSMGetDeadKeyState() != 0) {
 539             //    testDeadChar = [self deadKeyCharacter];
 540             //}
 541         }
 542 
 543         if (testChar != 0) {
 544             returnValue = NsCharToJavaChar(testChar, [event modifierFlags]);
 545         } else if (testDeadChar != 0) {
 546             returnValue = NsCharToJavaChar(testDeadChar, [event modifierFlags]);
 547         } else {
 548             returnValue = java_awt_event_KeyEvent_CHAR_UNDEFINED;
 549         }
 550         break;
 551 
 552     default:
 553         //[NSException raise:@"AWT error" format:@"Attempt to get character code from non-key event!"];
 554         break;
 555     }
 556 
 557     return returnValue;
 558 }
 559 
 560 /*
 561 static jchar
 562 GetDeadKeyCharacter(NSEvent *event)
 563 {
 564     // If the current event is not a dead key, return 0.
 565     // TODO: this uses SPI; it's an optimization but not strictly necessary
 566     //if (TSMGetDeadKeyState() == 0) {
 567     //    return 0;
 568     //}
 569 
 570     // AppKit does not track dead-key states directly, but TSM does. Even then,
 571     // it's not necessarily all that accurate, because the dead key can change
 572     // given some combination of modifier keys on certain layouts.
 573     // As a result, finding the unicode value for the front end of the dead
 574     // key is a bit of a heuristic.
 575 
 576     // This algorithm was suggested by Aki Inoue.
 577     // When you get a dead key, you need to simiulate what would happen in
 578     // the current dead-key and modifier state if the user hit the spacebar.
 579     // That will tell you the front end of the dead-key combination.
 580 
 581     unichar returnValue = 0;
 582     const UInt16 VIRTUAL_KEY_SPACE = 49;
 583     UInt32 deadKeyState = 0;
 584     UInt32 appkitFlags = [event modifierFlags];
 585     UniCharCount actualStringLength;
 586     UniChar unicodeInputString[16];
 587     TISInputSourceRef keyLayout;
 588     const void *chrData;
 589 
 590     keyLayout = TISCopyCurrentKeyboardLayoutInputSource();
 591     CFDataRef cfUchrData =
 592         TISGetInputSourceProperty(keyLayout, kTISPropertyUnicodeKeyLayoutData);
 593 
 594     if (cfUchrData == NULL) {
 595         return returnValue;
 596     }
 597 
 598     // The actual 'uchr' table is inside the CFDataRef.
 599     chrData = CFDataGetBytePtr(cfUchrData);
 600 
 601     UInt8 keyboardType = LMGetKbdType();
 602     UInt32 keyEventModifiers = 0;
 603     if (appkitFlags & NSShiftKeyMask)      keyEventModifiers |= shiftKey;
 604     if (appkitFlags & NSCommandKeyMask)    keyEventModifiers |= cmdKey;
 605     if (appkitFlags & NSAlphaShiftKeyMask) keyEventModifiers |= alphaLock;
 606     if (appkitFlags & NSControlKeyMask)    keyEventModifiers |= controlKey;
 607     if (appkitFlags & NSAlternateKeyMask)  keyEventModifiers |= optionKey;
 608 
 609     if (noErr == UCKeyTranslate(chrData,
 610         VIRTUAL_KEY_SPACE,
 611         ([event type] == NSKeyDown ? kUCKeyActionDown : kUCKeyActionUp),
 612         keyEventModifiers,
 613         keyboardType,
 614         kUCKeyTranslateNoDeadKeysMask,
 615         &deadKeyState,
 616         16,
 617         &actualStringLength,
 618         unicodeInputString))
 619     {
 620         if (actualStringLength > 0) {
 621             returnValue = unicodeInputString[0];
 622         }
 623     }
 624 
 625     return returnValue;
 626 }
 627 */
 628 
 629 
 630 // REMIND: The fix for MACOSX_PORT-539 introduces Java-level implementation
 631 // of the function below (see CPlatformResponder). Consider removing this code.
 632 
 633 void
 634 DeliverJavaKeyEvent(JNIEnv *env, NSEvent *event, jobject peer)
 635 {
 636     jint javaKeyType = java_awt_event_KeyEvent_KEY_PRESSED;
 637     jint javaKeyCode = java_awt_event_KeyEvent_VK_UNDEFINED;
 638     jint javaKeyLocation = java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN;
 639     NSString *chars = nil;
 640     BOOL postsTyped;
 641     unichar testChar = java_awt_event_KeyEvent_CHAR_UNDEFINED;
 642     unichar testDeadChar = 0;
 643     jint javaModifiers = 0;
 644 
 645     switch ([event type]) {
 646     case NSFlagsChanged:
 647         NsKeyModifiersToJavaKeyInfo([event modifierFlags],
 648                                     [event keyCode],
 649                                     &javaKeyCode,
 650                                     &javaKeyLocation,
 651                                     &javaKeyType);
 652         break;
 653 
 654     case NSKeyDown:
 655     case NSKeyUp:
 656         chars = [event charactersIgnoringModifiers];
 657         if ([chars length] > 0) {
 658             testChar = [chars characterAtIndex:0];
 659         }
 660 
 661         javaModifiers = NsKeyModifiersToJavaModifiers([event modifierFlags]);
 662         if (javaModifiers == 0) {
 663       // TODO: dead key chars
 664 //            testDeadChar = GetDeadKeyCharacter(event);
 665         }
 666 
 667         NsCharToJavaVirtualKeyCode(testChar, testDeadChar,
 668                                    [event modifierFlags], [event keyCode],
 669                                    &javaKeyCode, &javaKeyLocation, &postsTyped);
 670         if( !postsTyped ) {
 671             testChar = java_awt_event_KeyEvent_CHAR_UNDEFINED;
 672         }
 673 
 674         javaKeyType = ([event type] == NSKeyDown) ?
 675             java_awt_event_KeyEvent_KEY_PRESSED :
 676             java_awt_event_KeyEvent_KEY_RELEASED;
 677         break;
 678 
 679     default:
 680         //[NSException raise:@"AWT error" format:@"Attempt to get virtual key code from non-key event!"];
 681         break;
 682     }
 683 
 684     if (env != NULL) {
 685         static JNF_CLASS_CACHE(jc_CPlatformView, "sun/lwawt/macosx/CPlatformView");
 686         static JNF_MEMBER_CACHE(jm_deliverKeyEvent, jc_CPlatformView, "deliverKeyEvent", "(IICII)V");
 687         JNFCallVoidMethod(env, peer, jm_deliverKeyEvent,
 688                           javaKeyType, javaModifiers,
 689                           testChar, javaKeyCode, javaKeyLocation);
 690     }
 691 }
 692 
 693 jint GetJavaMouseModifiers(NSInteger button, NSUInteger modifierFlags)
 694 {
 695     // Mousing needs the key modifiers
 696     jint modifiers = NsKeyModifiersToJavaModifiers(modifierFlags);
 697 
 698 
 699     /*
 700      * Ask Quartz about mouse buttons state
 701      */
 702 
 703     if (CGEventSourceButtonState(kCGEventSourceStateCombinedSessionState,
 704                                  kCGMouseButtonLeft)) {
 705         modifiers |= java_awt_event_InputEvent_BUTTON1_DOWN_MASK;
 706     }
 707 
 708     if (CGEventSourceButtonState(kCGEventSourceStateCombinedSessionState,
 709                                  kCGMouseButtonRight)) {
 710         modifiers |= java_awt_event_InputEvent_BUTTON3_DOWN_MASK;
 711     }
 712 
 713     if (CGEventSourceButtonState(kCGEventSourceStateCombinedSessionState,
 714                                  kCGMouseButtonCenter)) {
 715         modifiers |= java_awt_event_InputEvent_BUTTON2_DOWN_MASK;
 716     }
 717 
 718     NSInteger extraButton = 3;
 719     for (; extraButton < gNumberOfButtons; extraButton++) {
 720         if (CGEventSourceButtonState(kCGEventSourceStateCombinedSessionState,
 721                                  extraButton)) {
 722             modifiers |= gButtonDownMasks[extraButton];
 723         }
 724     }
 725 
 726     return modifiers;
 727 }
 728 
 729 /*
 730  * Converts an NSEvent button number to a MouseEvent constant.
 731  */
 732 static jint
 733 NSButtonToJavaButton(NSInteger nsButtonNumber)
 734 {
 735     jint jbutton = java_awt_event_MouseEvent_NOBUTTON;
 736 
 737     if (nsButtonNumber == 0) { // left
 738         jbutton = java_awt_event_MouseEvent_BUTTON1;
 739     } else if (nsButtonNumber == 1) { // right
 740         jbutton = java_awt_event_MouseEvent_BUTTON3;
 741     } else if (nsButtonNumber == 2) { // middle
 742         jbutton = java_awt_event_MouseEvent_BUTTON2;
 743     }
 744 
 745     return jbutton;
 746 }
 747 
 748 
 749 static BOOL isDragging = NO;
 750 
 751 void
 752 DeliverMouseClickedEvent(JNIEnv *env, NSEvent *event, jobject peer)
 753 {
 754     NSPoint pt = [event locationInWindow];
 755     NSPoint pOnScreen = [NSEvent mouseLocation];
 756     jint etype = java_awt_event_MouseEvent_MOUSE_CLICKED;
 757     jint modifiers = GetJavaMouseModifiers([event buttonNumber], [event modifierFlags]);
 758     jint clickCount = [event clickCount];
 759     jint button = NSButtonToJavaButton([event buttonNumber]);
 760 
 761     if (env != NULL) {
 762         static JNF_CLASS_CACHE(jc_CPlatformView, "sun/lwawt/macosx/CPlatformView");
 763         static JNF_MEMBER_CACHE(jm_deliverMouseEvent, jc_CPlatformView,
 764                                 "deliverMouseEvent", "(IIIIFFFF)V");
 765         JNFCallVoidMethod(env, peer, jm_deliverMouseEvent,
 766                           etype, modifiers,
 767                           clickCount, button,
 768                           pt.x, pt.y,
 769                           pOnScreen.x, pOnScreen.y);
 770     }
 771 }
 772 
 773 /*
 774  * After every key down event, this is called to make the matching
 775  * KEY_TYPED (if this key posts those).  We use the same NSEvent for it,
 776  * but create a KEY_TYPED java event this time.
 777  * If this key doesn't post typed, we don't post the event.
 778  *
 779  * TODO: some duplicated effort here; could just fold it
 780  * into DeliverJavaKeyEvent...
 781  */
 782 static void
 783 DeliverKeyTypedEvents(JNIEnv *env, NSEvent *nsEvent, jobject peer)
 784 {
 785     if (peer == NULL) {
 786         return;
 787     }
 788 
 789     jint javaKeyCode, javaKeyLocation;
 790     BOOL postsTyped = NO;
 791     unichar testChar, testDeadChar = 0;
 792     jint javaModifiers = NsKeyModifiersToJavaModifiers([nsEvent modifierFlags]);
 793 
 794     if (javaModifiers == 0) {
 795         testDeadChar = [nsEvent deadKeyCharacter];
 796     }
 797 
 798     NSString *theChars = [nsEvent characters];
 799     unsigned i, stringLength = [theChars length];
 800 
 801     for (i = 0; i < stringLength; i++) {
 802         testChar = [theChars characterAtIndex:i];
 803         NsCharToJavaVirtualKeyCode(testChar, testDeadChar,
 804                                    [nsEvent modifierFlags], [nsEvent keyCode],
 805                                    &javaKeyCode, &javaKeyLocation, &postsTyped);
 806 
 807         if (postsTyped) {
 808             // Some keys may generate a KEY_TYPED, but we can't determine
 809             // what that character is. That's likely a bug, but for now we
 810             // just check for CHAR_UNDEFINED.
 811             unichar theChar = GetJavaCharacter(nsEvent, i);
 812             if (theChar != java_awt_event_KeyEvent_CHAR_UNDEFINED) {
 813                 if (env != NULL) {
 814                     static JNF_CLASS_CACHE(jc_CPlatformView,
 815                                            "sun/lwawt/macosx/CPlatformView");
 816                     static JNF_MEMBER_CACHE(jm_deliverKeyEvent, jc_CPlatformView,
 817                                             "deliverKeyEvent", "(IICII)V");
 818                     JNFCallVoidMethod(env, peer, jm_deliverKeyEvent,
 819                                       java_awt_event_KeyEvent_KEY_TYPED,
 820                                       javaModifiers,
 821                                       theChar,
 822                                       java_awt_event_KeyEvent_VK_UNDEFINED,
 823                                       java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN);
 824                 }
 825             }
 826         }
 827     }
 828 }
 829 
 830 /*
 831  * There are a couple of extra events that Java expects to get that don't
 832  * actually correspond to a direct NSEvent, KEY_TYPED and MOUSE_CLICKED are
 833  * both extra events that are sort of redundant with ordinary
 834  * key downs and mouse ups.  In this extra message, we take the original
 835  * input event and if necessary, cons up a special follow-on event which
 836  * we dispatch over to Java.
 837  *
 838  * For Java, keyDown's generate a KeyPressed (for each hardware key as it
 839  * goes down) and then a "logical KeyTyped" event for the key event. (So
 840  * a shift-a generates two presses, one keytyped of "A", and then two
 841  * releases).  The standard event utility function converts a key down to
 842  * a key pressed. When appropriate, we need to cons up another event
 843  * (KEY_TYPED) to follow a keyDown.
 844  *
 845  * Java expects you to send a clicked event if you got a down & up, with no
 846  * intervening drag. So in addition to the MOUSE_RELEASED event that a
 847  * mouseUp is translated to, we also have to cons up a MOUSE_CLICKED event
 848  * for that case. Mike Paquette, god of Window Server event handling,
 849  * confirmed this fact about how to determine if a mouse up event had an
 850  * intervening drag:
 851  * An initial mouse-down gets a click count of 1. Subsequent left or right
 852  * mouse-downs within the space/time tolerance limits increment the click
 853  * count.  A mouse-up will have the clickCount of the last mouseDown if
 854  * mouse is not outside the tolerance limits, but 0 otherwise.  Thus, a
 855  * down-up sequence without any intervening drag will have a click count
 856  * of 0 in the mouse-up event.  NOTE: The problem with this is that
 857  * clickCount goes to zero after some point in time. So a long, click &
 858  * hold without moving and then release the mouse doesn't create a
 859  * MOUSE_CLICK event as it should. Java AWT now tracks the drag state itself.
 860  *
 861  * As another add-on, we also check for the status of mouse-motion events
 862  * after a mouse-down, so we know whether to generate mouse-dragged events
 863  * during this down sequence.
 864  */
 865 void
 866 SendAdditionalJavaEvents(JNIEnv *env, NSEvent *nsEvent, jobject peer)
 867 {
 868     AWT_ASSERT_APPKIT_THREAD;
 869 
 870     NSEventType type = [nsEvent type];
 871     switch (type) {
 872     case NSKeyDown:
 873         break;
 874 
 875     case NSLeftMouseUp:
 876     case NSRightMouseUp:
 877     case NSOtherMouseUp:
 878         // TODO: we may need to pull in changedDragToMove here...
 879         //if (!isDragging && ([NSViewAWT changedDragToMove]==NO)) {
 880         if (!isDragging) {
 881             // got down/up pair with no dragged in between; ignores drag events
 882             // that have been morphed to move events
 883             DeliverMouseClickedEvent(env, nsEvent, peer);
 884         }
 885         break;
 886 
 887 // TODO: to be implemented...
 888 #if 0
 889     case NSLeftMouseDragged:
 890     case NSRightMouseDragged:
 891     case NSOtherMouseDragged:
 892         //
 893         // During a drag, the AppKit does not send mouseEnter and mouseExit
 894         // events.  It turns out that doing a hitTest causes the window's
 895         // view hierarchy to be locked from drawing and that, of course,
 896         // slows everything way down.  Synthesize mouseEnter and mouseExit
 897         // then forward.
 898         //
 899         NSView *hitView = [[source model] hitTest:[nsEvent locationInWindow]];
 900 
 901         if ((hitView != nil) &&
 902             ([hitView conformsToProtocol:@protocol(AWTPeerControl)]))
 903         {
 904             if (sLastMouseDraggedView == nil) {
 905                 sLastMouseDraggedView = hitView;
 906             }
 907             else if (hitView != sLastMouseDraggedView) {
 908                 // We know sLastMouseDraggedView is a AWTPeerControl.
 909                 jobject lastPeer =
 910                     [(id <AWTPeerControl>)sLastMouseDraggedView peer];
 911 
 912                 // Send mouseExit to sLastMouseDraggedView
 913                 jobject exitEvent =
 914                     makeMouseEvent(env, nsEvent, lastPeer,
 915                                    sLastMouseDraggedView,
 916                                    java_awt_event_MouseEvent_MOUSE_EXITED);
 917                 pushEventForward(exitEvent, env);
 918                 (*env)->DeleteLocalRef(env, exitEvent);
 919 
 920                 // Send mouseEnter to hitView
 921                 jobject enterEvent =
 922                     makeMouseEvent(env, nsEvent, peer, hitView,
 923                                    java_awt_event_MouseEvent_MOUSE_ENTERED);
 924                 pushEventForward(enterEvent, env);
 925 
 926                 (*env)->DeleteLocalRef(env, enterEvent);
 927 
 928                 // Set sLastMouseDraggedView = hitView
 929                 sLastMouseDraggedView = hitView;
 930             }
 931         }
 932         break;
 933 #endif
 934 
 935     default:
 936         break;
 937     }
 938 }
 939 
 940 jlong UTC(NSEvent *event) {
 941     struct timeval tv;
 942     if (gettimeofday(&tv, NULL) == 0) {
 943         long long sec = (long long)tv.tv_sec;
 944         return (sec*1000) + (tv.tv_usec/1000);
 945     }
 946     return 0;
 947 }
 948 
 949 JNIEXPORT void JNICALL
 950 Java_java_awt_AWTEvent_nativeSetSource
 951     (JNIEnv *env, jobject self, jobject newSource)
 952 {
 953 }
 954 
 955 /*
 956  * Class:     sun_lwawt_macosx_event_NSEvent
 957  * Method:    nsToJavaMouseModifiers
 958  * Signature: (II)I
 959  */
 960 JNIEXPORT jint JNICALL
 961 Java_sun_lwawt_macosx_event_NSEvent_nsToJavaMouseModifiers
 962 (JNIEnv *env, jclass cls, jint buttonNumber, jint modifierFlags)
 963 {
 964     jint jmodifiers = 0;
 965 
 966 JNF_COCOA_ENTER(env);
 967 
 968     jmodifiers = GetJavaMouseModifiers(buttonNumber, modifierFlags);
 969 
 970 JNF_COCOA_EXIT(env);
 971 
 972     return jmodifiers;
 973 }
 974 
 975 /*
 976  * Class:     sun_lwawt_macosx_event_NSEvent
 977  * Method:    nsToJavaKeyModifiers
 978  * Signature: (I)I
 979  */
 980 JNIEXPORT jint JNICALL
 981 Java_sun_lwawt_macosx_event_NSEvent_nsToJavaKeyModifiers
 982 (JNIEnv *env, jclass cls, jint modifierFlags)
 983 {
 984     jint jmodifiers = 0;
 985 
 986 JNF_COCOA_ENTER(env);
 987 
 988     jmodifiers = NsKeyModifiersToJavaModifiers(modifierFlags);
 989 
 990 JNF_COCOA_EXIT(env);
 991 
 992     return jmodifiers;
 993 }
 994 
 995 /*
 996  * Class:     sun_lwawt_macosx_event_NSEvent
 997  * Method:    nsToJavaKeyInfo
 998  * Signature: ([I[I)Z
 999  */
1000 JNIEXPORT jboolean JNICALL
1001 Java_sun_lwawt_macosx_event_NSEvent_nsToJavaKeyInfo
1002 (JNIEnv *env, jclass cls, jintArray inData, jintArray outData)
1003 {
1004     BOOL postsTyped = NO;
1005 
1006 JNF_COCOA_ENTER(env);
1007 
1008     jboolean copy = JNI_FALSE;
1009     jint *data = (*env)->GetIntArrayElements(env, inData, &copy);
1010 
1011     // in  = [testChar, testDeadChar, modifierFlags, keyCode]
1012     jchar testChar = (jchar)data[0];
1013     jchar testDeadChar = (jchar)data[1];
1014     jint modifierFlags = data[2];
1015     jshort keyCode = (jshort)data[3];
1016 
1017     jint jkeyCode = java_awt_event_KeyEvent_VK_UNDEFINED;
1018     jint jkeyLocation = java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN;
1019 
1020     NsCharToJavaVirtualKeyCode((unichar)testChar, (unichar)testDeadChar,
1021                                (NSUInteger)modifierFlags, (unsigned short)keyCode,
1022                                &jkeyCode, &jkeyLocation, &postsTyped);
1023 
1024     // out = [jkeyCode, jkeyLocation];
1025     (*env)->SetIntArrayRegion(env, outData, 0, 1, &jkeyCode);
1026     (*env)->SetIntArrayRegion(env, outData, 1, 1, &jkeyLocation);
1027 
1028     (*env)->ReleaseIntArrayElements(env, inData, data, 0);
1029 
1030 JNF_COCOA_EXIT(env);
1031 
1032     return postsTyped;
1033 }
1034 
1035 /*
1036  * Class:     sun_lwawt_macosx_event_NSEvent
1037  * Method:    nsKeyModifiersToJavaKeyInfo
1038  * Signature: ([I[I)V
1039  */
1040 JNIEXPORT void JNICALL
1041 Java_sun_lwawt_macosx_event_NSEvent_nsKeyModifiersToJavaKeyInfo
1042 (JNIEnv *env, jclass cls, jintArray inData, jintArray outData)
1043 {
1044 JNF_COCOA_ENTER(env);
1045 
1046     jboolean copy = JNI_FALSE;
1047     jint *data = (*env)->GetIntArrayElements(env, inData, &copy);
1048 
1049     // in  = [modifierFlags, keyCode]
1050     jint modifierFlags = data[0];
1051     jshort keyCode = (jshort)data[1];
1052 
1053     jint jkeyCode = java_awt_event_KeyEvent_VK_UNDEFINED;
1054     jint jkeyLocation = java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN;
1055     jint jkeyType = java_awt_event_KeyEvent_KEY_PRESSED;
1056 
1057     NsKeyModifiersToJavaKeyInfo(modifierFlags,
1058                                 keyCode,
1059                                 &jkeyCode,
1060                                 &jkeyLocation,
1061                                 &jkeyType);
1062 
1063     // out = [jkeyCode, jkeyLocation, jkeyType];
1064     (*env)->SetIntArrayRegion(env, outData, 0, 1, &jkeyCode);
1065     (*env)->SetIntArrayRegion(env, outData, 1, 1, &jkeyLocation);
1066     (*env)->SetIntArrayRegion(env, outData, 2, 1, &jkeyType);
1067 
1068     (*env)->ReleaseIntArrayElements(env, inData, data, 0);
1069 
1070 JNF_COCOA_EXIT(env);
1071 }




















--- EOF ---