1 /*
   2  * Copyright (c) 2011, 2015, 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 "common.h"
  27 #import "com_sun_glass_events_KeyEvent.h"
  28 #import "com_sun_glass_ui_mac_MacApplication.h"
  29 
  30 #import "GlassApplication.h"
  31 #import "GlassMacros.h"
  32 #import "GlassKey.h"
  33 
  34 //#define VERBOSE
  35 #ifndef VERBOSE
  36     #define LOG(MSG, ...)
  37 #else
  38     #define LOG(MSG, ...) GLASS_LOG(MSG, ## __VA_ARGS__);
  39 #endif
  40 
  41 struct KeyMapEntry
  42 {
  43     unsigned short        keyCode;
  44     jint                  jKeyCode;
  45     BOOL                  sendJavaChars;            
  46 };
  47 
  48 static const struct KeyMapEntry gKeyMap[] =
  49 {
  50     {0x00, com_sun_glass_events_KeyEvent_VK_A, YES},
  51     {0x01, com_sun_glass_events_KeyEvent_VK_S, YES},
  52     {0x02, com_sun_glass_events_KeyEvent_VK_D, YES},
  53     {0x03, com_sun_glass_events_KeyEvent_VK_F, YES},
  54     {0x04, com_sun_glass_events_KeyEvent_VK_H, YES},
  55     {0x05, com_sun_glass_events_KeyEvent_VK_G, YES},
  56     {0x06, com_sun_glass_events_KeyEvent_VK_Z, YES},
  57     {0x07, com_sun_glass_events_KeyEvent_VK_X, YES},
  58     {0x08, com_sun_glass_events_KeyEvent_VK_C, YES},
  59     {0x09, com_sun_glass_events_KeyEvent_VK_V, YES},
  60     {0x0A, com_sun_glass_events_KeyEvent_VK_BACK_QUOTE, YES},
  61     {0x0B, com_sun_glass_events_KeyEvent_VK_B, YES},
  62     {0x0C, com_sun_glass_events_KeyEvent_VK_Q, YES},
  63     {0x0D, com_sun_glass_events_KeyEvent_VK_W, YES},
  64     {0x0E, com_sun_glass_events_KeyEvent_VK_E, YES},
  65     {0x0F, com_sun_glass_events_KeyEvent_VK_R, YES},
  66     {0x10, com_sun_glass_events_KeyEvent_VK_Y, YES},
  67     {0x11, com_sun_glass_events_KeyEvent_VK_T, YES},
  68     {0x12, com_sun_glass_events_KeyEvent_VK_1, YES},
  69     {0x13, com_sun_glass_events_KeyEvent_VK_2, YES},
  70     {0x14, com_sun_glass_events_KeyEvent_VK_3, YES},
  71     {0x15, com_sun_glass_events_KeyEvent_VK_4, YES},
  72     {0x16, com_sun_glass_events_KeyEvent_VK_6, YES},
  73     {0x17, com_sun_glass_events_KeyEvent_VK_5, YES},
  74     {0x18, com_sun_glass_events_KeyEvent_VK_EQUALS, YES},
  75     {0x19, com_sun_glass_events_KeyEvent_VK_9, YES},
  76     {0x1A, com_sun_glass_events_KeyEvent_VK_7, YES},
  77     {0x1B, com_sun_glass_events_KeyEvent_VK_MINUS, YES},
  78     {0x1C, com_sun_glass_events_KeyEvent_VK_8, YES},
  79     {0x1D, com_sun_glass_events_KeyEvent_VK_0, YES},
  80     {0x1E, com_sun_glass_events_KeyEvent_VK_CLOSE_BRACKET, YES},
  81     {0x1F, com_sun_glass_events_KeyEvent_VK_O, YES},
  82     {0x20, com_sun_glass_events_KeyEvent_VK_U, YES},
  83     {0x21, com_sun_glass_events_KeyEvent_VK_OPEN_BRACKET, YES},
  84     {0x22, com_sun_glass_events_KeyEvent_VK_I, YES},
  85     {0x23, com_sun_glass_events_KeyEvent_VK_P, YES},
  86     {0x24, com_sun_glass_events_KeyEvent_VK_ENTER, YES},
  87     {0x25, com_sun_glass_events_KeyEvent_VK_L, YES},
  88     {0x26, com_sun_glass_events_KeyEvent_VK_J, YES},
  89     {0x27, com_sun_glass_events_KeyEvent_VK_QUOTE, YES},
  90     {0x28, com_sun_glass_events_KeyEvent_VK_K, YES},
  91     {0x29, com_sun_glass_events_KeyEvent_VK_SEMICOLON, YES},
  92     {0x2A, com_sun_glass_events_KeyEvent_VK_BACK_SLASH, YES},
  93     {0x2B, com_sun_glass_events_KeyEvent_VK_COMMA, YES},
  94     {0x2C, com_sun_glass_events_KeyEvent_VK_SLASH, YES},
  95     {0x2D, com_sun_glass_events_KeyEvent_VK_N, YES},
  96     {0x2E, com_sun_glass_events_KeyEvent_VK_M, YES},
  97     {0x2F, com_sun_glass_events_KeyEvent_VK_PERIOD, YES},
  98     {0x30, com_sun_glass_events_KeyEvent_VK_TAB, YES},
  99     {0x31, com_sun_glass_events_KeyEvent_VK_SPACE, YES},
 100     {0x32, com_sun_glass_events_KeyEvent_VK_BACK_QUOTE, YES},
 101     {0x33, com_sun_glass_events_KeyEvent_VK_BACKSPACE, NO},
 102     {0x34, com_sun_glass_events_KeyEvent_VK_ENTER, YES},
 103     {0x35, com_sun_glass_events_KeyEvent_VK_ESCAPE, NO},
 104     {0x36, com_sun_glass_events_KeyEvent_VK_UNDEFINED, NO},
 105     {0x37, com_sun_glass_events_KeyEvent_VK_COMMAND, NO},
 106     {0x38, com_sun_glass_events_KeyEvent_VK_SHIFT, NO},
 107     {0x39, com_sun_glass_events_KeyEvent_VK_CAPS_LOCK, NO},
 108     {0x3A, com_sun_glass_events_KeyEvent_VK_ALT, NO},
 109     {0x3B, com_sun_glass_events_KeyEvent_VK_CONTROL, NO},
 110     {0x3C, com_sun_glass_events_KeyEvent_VK_UNDEFINED, NO},
 111     {0x3D, com_sun_glass_events_KeyEvent_VK_UNDEFINED, NO},
 112     {0x3E, com_sun_glass_events_KeyEvent_VK_UNDEFINED, NO},
 113     {0x3F, com_sun_glass_events_KeyEvent_VK_UNDEFINED, NO},
 114     {0x40, com_sun_glass_events_KeyEvent_VK_UNDEFINED, NO},
 115     {0x41, com_sun_glass_events_KeyEvent_VK_DECIMAL, YES},
 116     {0x42, com_sun_glass_events_KeyEvent_VK_UNDEFINED, NO},
 117     {0x43, com_sun_glass_events_KeyEvent_VK_MULTIPLY, YES},
 118     {0x44, com_sun_glass_events_KeyEvent_VK_UNDEFINED, NO},
 119     {0x45, com_sun_glass_events_KeyEvent_VK_ADD, YES},
 120     {0x46, com_sun_glass_events_KeyEvent_VK_UNDEFINED, NO},
 121     {0x47, com_sun_glass_events_KeyEvent_VK_CLEAR, NO},
 122     {0x48, com_sun_glass_events_KeyEvent_VK_UNDEFINED, NO},
 123     {0x49, com_sun_glass_events_KeyEvent_VK_UNDEFINED, NO},
 124     {0x4A, com_sun_glass_events_KeyEvent_VK_UNDEFINED, NO},
 125     {0x4B, com_sun_glass_events_KeyEvent_VK_DIVIDE, YES},
 126     {0x4C, com_sun_glass_events_KeyEvent_VK_ENTER, YES},
 127     {0x4D, com_sun_glass_events_KeyEvent_VK_UNDEFINED, NO},
 128     {0x4E, com_sun_glass_events_KeyEvent_VK_SUBTRACT, YES},
 129     {0x4F, com_sun_glass_events_KeyEvent_VK_UNDEFINED, NO},
 130     {0x50, com_sun_glass_events_KeyEvent_VK_UNDEFINED, NO},
 131     {0x51, com_sun_glass_events_KeyEvent_VK_EQUALS, YES},
 132     {0x52, com_sun_glass_events_KeyEvent_VK_NUMPAD0, YES},
 133     {0x53, com_sun_glass_events_KeyEvent_VK_NUMPAD1, YES},
 134     {0x54, com_sun_glass_events_KeyEvent_VK_NUMPAD2, YES},
 135     {0x55, com_sun_glass_events_KeyEvent_VK_NUMPAD3, YES},
 136     {0x56, com_sun_glass_events_KeyEvent_VK_NUMPAD4, YES},
 137     {0x57, com_sun_glass_events_KeyEvent_VK_NUMPAD5, YES},
 138     {0x58, com_sun_glass_events_KeyEvent_VK_NUMPAD6, YES},
 139     {0x59, com_sun_glass_events_KeyEvent_VK_NUMPAD7, YES},
 140     {0x5A, com_sun_glass_events_KeyEvent_VK_UNDEFINED, NO},
 141     {0x5B, com_sun_glass_events_KeyEvent_VK_NUMPAD8, YES},
 142     {0x5C, com_sun_glass_events_KeyEvent_VK_NUMPAD9, YES},
 143     {0x5D, com_sun_glass_events_KeyEvent_VK_BACK_SLASH, YES},
 144     {0x5E, com_sun_glass_events_KeyEvent_VK_UNDERSCORE, YES},
 145     {0x5F, com_sun_glass_events_KeyEvent_VK_COMMA, YES},
 146     {0x60, com_sun_glass_events_KeyEvent_VK_F5, NO},
 147     {0x61, com_sun_glass_events_KeyEvent_VK_F6, NO},
 148     {0x62, com_sun_glass_events_KeyEvent_VK_F7, NO},
 149     {0x63, com_sun_glass_events_KeyEvent_VK_F3, NO},
 150     {0x64, com_sun_glass_events_KeyEvent_VK_F8, NO},
 151     {0x65, com_sun_glass_events_KeyEvent_VK_F9, NO},
 152 //        {0x66, com_sun_glass_events_KeyEvent_VK_ALPHANUMERIC, NO},
 153     {0x67, com_sun_glass_events_KeyEvent_VK_F11, NO},
 154 //        {0x68, com_sun_glass_events_KeyEvent_VK_KATAKANA, NO},
 155 //        {0x69, com_sun_glass_events_KeyEvent_VK_F13, NO},
 156 //        {0x6A, com_sun_glass_events_KeyEvent_VK_F16, NO},
 157 //        {0x6B, com_sun_glass_events_KeyEvent_VK_F14, NO},
 158     {0x6C, com_sun_glass_events_KeyEvent_VK_UNDEFINED, NO},
 159     {0x6D, com_sun_glass_events_KeyEvent_VK_F10, NO},
 160     {0x6E, com_sun_glass_events_KeyEvent_VK_UNDEFINED, NO},
 161     {0x6F, com_sun_glass_events_KeyEvent_VK_F12, NO},
 162     {0x70, com_sun_glass_events_KeyEvent_VK_UNDEFINED, NO},
 163 //        {0x71, com_sun_glass_events_KeyEvent_VK_F15, NO},
 164     {0x72, com_sun_glass_events_KeyEvent_VK_HELP, NO},
 165     {0x73, com_sun_glass_events_KeyEvent_VK_HOME, NO},
 166     {0x74, com_sun_glass_events_KeyEvent_VK_PAGE_UP, NO},
 167     {0x75, com_sun_glass_events_KeyEvent_VK_DELETE, NO},
 168     {0x76, com_sun_glass_events_KeyEvent_VK_F4, NO},
 169     {0x77, com_sun_glass_events_KeyEvent_VK_END, NO},
 170     {0x78, com_sun_glass_events_KeyEvent_VK_F2, NO},
 171     {0x79, com_sun_glass_events_KeyEvent_VK_PAGE_DOWN, NO},
 172     {0x7A, com_sun_glass_events_KeyEvent_VK_F1, NO},
 173     {0x7B, com_sun_glass_events_KeyEvent_VK_LEFT, NO},
 174     {0x7C, com_sun_glass_events_KeyEvent_VK_RIGHT, NO},
 175     {0x7D, com_sun_glass_events_KeyEvent_VK_DOWN, NO},
 176     {0x7E, com_sun_glass_events_KeyEvent_VK_UP, NO},
 177     {0x7F, com_sun_glass_events_KeyEvent_VK_UNDEFINED, NO},
 178 };
 179 static const int gKeyMapSize = sizeof(gKeyMap) / sizeof(struct KeyMapEntry);
 180 
 181 jint GetJavaKeyModifiers(NSEvent *event)
 182 {
 183     jint jModifiers = 0;
 184 
 185     NSUInteger modifierFlags = ([event modifierFlags] & NSDeviceIndependentModifierFlagsMask);
 186     if (((modifierFlags & NSShiftKeyMask) != 0) == YES)
 187     {
 188         jModifiers |= com_sun_glass_events_KeyEvent_MODIFIER_SHIFT;
 189     }
 190     if (((modifierFlags & NSFunctionKeyMask) != 0) == YES)
 191     {
 192         jModifiers |= com_sun_glass_events_KeyEvent_MODIFIER_FUNCTION;
 193     }
 194     if (((modifierFlags & NSControlKeyMask) != 0) == YES)
 195     {
 196         jModifiers |= com_sun_glass_events_KeyEvent_MODIFIER_CONTROL;
 197     }
 198     if (((modifierFlags & NSAlternateKeyMask) != 0) == YES)
 199     {
 200         jModifiers |= com_sun_glass_events_KeyEvent_MODIFIER_OPTION;
 201     }
 202     if (((modifierFlags & NSCommandKeyMask) != 0) == YES)
 203     {
 204         jModifiers |= com_sun_glass_events_KeyEvent_MODIFIER_COMMAND;
 205     }
 206     return jModifiers;
 207 }
 208 
 209 jint GetJavaMouseModifiers(NSUInteger buttons)
 210 {
 211     jint jModifiers = 0;
 212     if (buttons & (1 << 0)) {
 213         jModifiers |= com_sun_glass_events_KeyEvent_MODIFIER_BUTTON_PRIMARY;
 214     }
 215     if (buttons & (1 << 1)) {
 216         jModifiers |= com_sun_glass_events_KeyEvent_MODIFIER_BUTTON_SECONDARY;
 217     }
 218     if (buttons & (1 << 2)) {
 219         jModifiers |= com_sun_glass_events_KeyEvent_MODIFIER_BUTTON_MIDDLE;
 220     }
 221     return jModifiers;
 222 }
 223 
 224 jint GetJavaModifiers(NSEvent *event)
 225 {
 226     return GetJavaKeyModifiers(event) | GetJavaMouseModifiers([NSEvent pressedMouseButtons]);
 227 }
 228 
 229 jint GetJavaKeyCodeFor(unsigned short keyCode)
 230 {
 231     // Not the fastest implementation...
 232     for (int i=0; i<gKeyMapSize; i++)
 233     {
 234         if (gKeyMap[i].keyCode == keyCode)
 235         {
 236             return gKeyMap[i].jKeyCode;
 237         }
 238     }
 239     return com_sun_glass_events_KeyEvent_VK_UNDEFINED;
 240 }
 241 
 242 jint GetJavaKeyCode(NSEvent *event)
 243 {
 244     return GetJavaKeyCodeFor([event keyCode]);
 245 }
 246 
 247 jcharArray GetJavaKeyChars(JNIEnv *env, NSEvent *event)
 248 {
 249     NSString *chars = [event characters];
 250     
 251     unsigned short keyCode = [event keyCode];
 252     BOOL needChars = NO;
 253     // Not the fastest implementation...
 254     for (int i=0; i<gKeyMapSize; i++)
 255     {
 256         if (gKeyMap[i].keyCode == keyCode)
 257         {
 258             needChars = gKeyMap[i].sendJavaChars;
 259             break;
 260         }
 261     }
 262     if (needChars == NO)
 263     {
 264         // Return an empty array instead of NULL
 265         return (*env)->NewCharArray(env, 0);
 266     }
 267     
 268     jchar jc[16];
 269     [chars getCharacters:jc range:NSMakeRange(0, [chars length])];
 270     jcharArray jChars = (*env)->NewCharArray(env, (jsize)[chars length]);
 271     (*env)->SetCharArrayRegion(env, jChars, 0, (jsize)[chars length], jc);
 272     GLASS_CHECK_EXCEPTION(env);
 273     return jChars;
 274 }
 275 
 276 BOOL GetMacKey(jint javaKeyCode, unsigned short *outMacKeyCode)
 277 {
 278     for (int index=0; index<gKeyMapSize; index++)
 279     {
 280         if (gKeyMap[index].jKeyCode == javaKeyCode)
 281         {
 282             *outMacKeyCode = gKeyMap[index].keyCode;
 283             return YES;
 284         }
 285     }
 286     
 287     // ??? unknown VK
 288     return NO;
 289 }
 290 
 291 NSString* GetStringForJavaKey(jchar jKeyCode) {
 292     if (jKeyCode == '\0')
 293       return @"";
 294 
 295     if (islower(jKeyCode))
 296     {
 297         return [[NSString stringWithFormat:@"%c", jKeyCode] lowercaseString];
 298     }
 299     
 300     unichar   unicode = 0;
 301     switch (jKeyCode)
 302     {
 303         case com_sun_glass_events_KeyEvent_VK_LEFT:
 304             unicode = 0x2190; break;
 305         case com_sun_glass_events_KeyEvent_VK_RIGHT:
 306             unicode = 0x2192; break;
 307         case com_sun_glass_events_KeyEvent_VK_UP:
 308             unicode = 0x2191; break;
 309         case com_sun_glass_events_KeyEvent_VK_DOWN:
 310             unicode = 0x2193; break;
 311         case com_sun_glass_events_KeyEvent_VK_ESCAPE:
 312             unicode = 0x238B; break;
 313         case com_sun_glass_events_KeyEvent_VK_LEFT_PARENTHESIS:
 314             unicode = 0x0028; break;
 315         case com_sun_glass_events_KeyEvent_VK_RIGHT_PARENTHESIS:
 316             unicode = 0x0029; break;
 317         case com_sun_glass_events_KeyEvent_VK_COLON:
 318             unicode = 0x003A; break;
 319         case com_sun_glass_events_KeyEvent_VK_DOLLAR:
 320             unicode = 0x0024; break;
 321         case com_sun_glass_events_KeyEvent_VK_EURO_SIGN:
 322             unicode = 0x20AC; break;
 323         case com_sun_glass_events_KeyEvent_VK_EXCLAMATION:
 324             unicode = 0x0021; break;
 325         case com_sun_glass_events_KeyEvent_VK_UNDERSCORE:
 326             unicode = 0x005F; break;
 327         case com_sun_glass_events_KeyEvent_VK_AT:
 328             unicode = 0x0040; break;
 329         case com_sun_glass_events_KeyEvent_VK_BRACELEFT:
 330             unicode = 0x007B; break;
 331         case com_sun_glass_events_KeyEvent_VK_BRACERIGHT:
 332             unicode = 0x007D; break;
 333         case com_sun_glass_events_KeyEvent_VK_LESS:
 334             unicode = 0x003C; break;
 335         case com_sun_glass_events_KeyEvent_VK_GREATER:
 336             unicode = 0x003E; break;
 337         case com_sun_glass_events_KeyEvent_VK_QUOTE:
 338             unicode = 0x0027; break;
 339         case com_sun_glass_events_KeyEvent_VK_BACK_QUOTE:
 340             unicode = 0x0060; break;
 341         case com_sun_glass_events_KeyEvent_VK_AMPERSAND:
 342             unicode = 0x0026; break;
 343         case com_sun_glass_events_KeyEvent_VK_MULTIPLY:
 344         case com_sun_glass_events_KeyEvent_VK_ASTERISK:
 345             unicode = 0x002A; break;
 346         case com_sun_glass_events_KeyEvent_VK_DOUBLE_QUOTE:
 347             unicode = 0x0022; break;
 348         case com_sun_glass_events_KeyEvent_VK_NUMBER_SIGN:
 349             unicode = 0x0023; break;
 350         case com_sun_glass_events_KeyEvent_VK_PLUS:
 351         case com_sun_glass_events_KeyEvent_VK_ADD:
 352             unicode = 0x002B; break;
 353         case com_sun_glass_events_KeyEvent_VK_MINUS:
 354         case com_sun_glass_events_KeyEvent_VK_SUBTRACT:
 355             unicode = 0x2013; break;
 356         case com_sun_glass_events_KeyEvent_VK_DIVIDE:
 357             unicode = 0x002F; break;
 358         case com_sun_glass_events_KeyEvent_VK_CIRCUMFLEX:
 359             unicode = 0x005E; break;
 360         case com_sun_glass_events_KeyEvent_VK_DECIMAL:
 361             unicode = 0x002E; break;
 362         case com_sun_glass_events_KeyEvent_VK_DELETE:
 363             unicode = 0x2326; break;
 364         default:
 365             break;
 366     }
 367     
 368     if (unicode != 0)
 369     {
 370         LOG("GetStringForJavaKey: unicode %x", unicode);
 371         return [NSString stringWithCharacters:&unicode length:1];
 372     }
 373     else
 374     {
 375         return [[NSString stringWithFormat:@"%c", jKeyCode] lowercaseString];
 376     }
 377 
 378 }
 379 
 380 /*
 381  * Class:     com_sun_glass_ui_mac_MacApplication
 382  * Method:    _getKeyCodeForChar
 383  * Signature: (C)I
 384  */
 385 JNIEXPORT jint JNICALL Java_com_sun_glass_ui_mac_MacApplication__1getKeyCodeForChar
 386 (JNIEnv * env, jobject jApplication, jchar c)
 387 {
 388     LOG("Java_com_sun_glass_ui_mac_MacApplication__1getKeyCodeForChar");
 389 
 390     return [GlassApplication getKeyCodeForChar:c];
 391 }
 392