src/video/cocoa/SDL_cocoakeyboard.m
author Jiang Jiang
Mon, 25 May 2009 02:42:45 +0000
branchgsoc2009_IME
changeset 3127 da6cbfa5b5f2
parent 2859 99210400e8b9
child 3129 e42873b9c6f1
permissions -rw-r--r--
Get basic text input support working for Cocoa
slouken@1931
     1
/*
slouken@1931
     2
    SDL - Simple DirectMedia Layer
slouken@2859
     3
    Copyright (C) 1997-2009 Sam Lantinga
slouken@1931
     4
slouken@1931
     5
    This library is free software; you can redistribute it and/or
slouken@1931
     6
    modify it under the terms of the GNU Lesser General Public
slouken@1931
     7
    License as published by the Free Software Foundation; either
slouken@1931
     8
    version 2.1 of the License, or (at your option) any later version.
slouken@1931
     9
slouken@1931
    10
    This library is distributed in the hope that it will be useful,
slouken@1931
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
slouken@1931
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@1931
    13
    Lesser General Public License for more details.
slouken@1931
    14
slouken@1931
    15
    You should have received a copy of the GNU Lesser General Public
slouken@1931
    16
    License along with this library; if not, write to the Free Software
slouken@1931
    17
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
slouken@1931
    18
slouken@1931
    19
    Sam Lantinga
slouken@1931
    20
    slouken@libsdl.org
slouken@1931
    21
*/
slouken@1931
    22
#include "SDL_config.h"
slouken@1931
    23
slouken@1931
    24
#include "SDL_cocoavideo.h"
slouken@1931
    25
slouken@1931
    26
#include "../../events/SDL_keyboard_c.h"
slouken@2305
    27
#include "../../events/scancodes_darwin.h"
slouken@1931
    28
slouken@2268
    29
#include <Carbon/Carbon.h>
slouken@2268
    30
slouken@1959
    31
slouken@1959
    32
#ifndef NX_DEVICERCTLKEYMASK
slouken@1959
    33
    #define NX_DEVICELCTLKEYMASK    0x00000001
slouken@1959
    34
#endif
slouken@1959
    35
#ifndef NX_DEVICELSHIFTKEYMASK
slouken@1959
    36
    #define NX_DEVICELSHIFTKEYMASK  0x00000002
slouken@1959
    37
#endif
slouken@1959
    38
#ifndef NX_DEVICERSHIFTKEYMASK
slouken@1959
    39
    #define NX_DEVICERSHIFTKEYMASK  0x00000004
slouken@1959
    40
#endif
slouken@1959
    41
#ifndef NX_DEVICELCMDKEYMASK
slouken@1959
    42
    #define NX_DEVICELCMDKEYMASK    0x00000008
slouken@1959
    43
#endif
slouken@1959
    44
#ifndef NX_DEVICERCMDKEYMASK
slouken@1959
    45
    #define NX_DEVICERCMDKEYMASK    0x00000010
slouken@1959
    46
#endif
slouken@1959
    47
#ifndef NX_DEVICELALTKEYMASK
slouken@1959
    48
    #define NX_DEVICELALTKEYMASK    0x00000020
slouken@1959
    49
#endif
slouken@1959
    50
#ifndef NX_DEVICERALTKEYMASK
slouken@1959
    51
    #define NX_DEVICERALTKEYMASK    0x00000040
slouken@1959
    52
#endif
slouken@1959
    53
#ifndef NX_DEVICERCTLKEYMASK
slouken@1959
    54
    #define NX_DEVICERCTLKEYMASK    0x00002000
slouken@1959
    55
#endif
slouken@1959
    56
slouken@2289
    57
@interface SDLTranslatorResponder : NSTextView
slouken@2289
    58
{
slouken@2289
    59
}
slouken@2289
    60
- (void) doCommandBySelector:(SEL)myselector;
slouken@2289
    61
@end
slouken@2289
    62
slouken@2289
    63
@implementation SDLTranslatorResponder
gzjjgod@3127
    64
gzjjgod@3127
    65
- (void) insertText:(id) aString
gzjjgod@3127
    66
{
gzjjgod@3127
    67
    const char *str;
gzjjgod@3127
    68
gzjjgod@3127
    69
    NSLog(@"insertText: %@", aString);
gzjjgod@3127
    70
gzjjgod@3127
    71
    if ([aString isKindOfClass: [NSAttributedString class]])
gzjjgod@3127
    72
        str = [[aString string] UTF8String];
gzjjgod@3127
    73
    else
gzjjgod@3127
    74
        str = [aString UTF8String];
gzjjgod@3127
    75
gzjjgod@3127
    76
    SDL_SendKeyboardText(0, str);
gzjjgod@3127
    77
}
gzjjgod@3127
    78
gzjjgod@3127
    79
- (void) doCommandBySelector:(SEL) myselector
gzjjgod@3127
    80
{
gzjjgod@3127
    81
    NSLog(@"doCommandBySelector, passed down");
gzjjgod@3127
    82
    [super doCommandBySelector: myselector];
gzjjgod@3127
    83
}
slouken@2289
    84
@end
slouken@2289
    85
slouken@1959
    86
/* This is the original behavior, before support was added for 
slouken@1959
    87
 * differentiating between left and right versions of the keys.
slouken@1959
    88
 */
slouken@1959
    89
static void
slouken@1959
    90
DoUnsidedModifiers(int keyboard, unsigned short scancode,
slouken@1959
    91
                   unsigned int oldMods, unsigned int newMods)
slouken@1959
    92
{
slouken@2303
    93
    const int mapping[] = {
slouken@2303
    94
        SDL_SCANCODE_CAPSLOCK,
slouken@2303
    95
        SDL_SCANCODE_LSHIFT,
slouken@2303
    96
        SDL_SCANCODE_LCTRL,
slouken@2303
    97
        SDL_SCANCODE_LALT,
slouken@2303
    98
        SDL_SCANCODE_LGUI
slouken@2303
    99
    };
slouken@1959
   100
    unsigned int i, bit;
slouken@1959
   101
slouken@1959
   102
    /* Iterate through the bits, testing each against the current modifiers */
slouken@1959
   103
    for (i = 0, bit = NSAlphaShiftKeyMask; bit <= NSCommandKeyMask; bit <<= 1, ++i) {
slouken@1959
   104
        unsigned int oldMask, newMask;
slouken@1959
   105
slouken@1959
   106
        oldMask = oldMods & bit;
slouken@1959
   107
        newMask = newMods & bit;
slouken@1959
   108
slouken@1959
   109
        if (oldMask && oldMask != newMask) {        /* modifier up event */
slouken@1959
   110
            /* If this was Caps Lock, we need some additional voodoo to make SDL happy */
slouken@1959
   111
            if (bit == NSAlphaShiftKeyMask) {
slouken@2303
   112
                SDL_SendKeyboardKey(keyboard, SDL_PRESSED, mapping[i]);
slouken@1959
   113
            }
slouken@2303
   114
            SDL_SendKeyboardKey(keyboard, SDL_RELEASED, mapping[i]);
slouken@1959
   115
        } else if (newMask && oldMask != newMask) { /* modifier down event */
slouken@2303
   116
            SDL_SendKeyboardKey(keyboard, SDL_PRESSED, mapping[i]);
slouken@1959
   117
            /* If this was Caps Lock, we need some additional voodoo to make SDL happy */
slouken@1959
   118
            if (bit == NSAlphaShiftKeyMask) {
slouken@2303
   119
                SDL_SendKeyboardKey(keyboard, SDL_RELEASED, mapping[i]);
slouken@1959
   120
            }
slouken@1959
   121
        }
slouken@1959
   122
    }
slouken@1959
   123
}
slouken@1959
   124
slouken@1959
   125
/* This is a helper function for HandleModifierSide. This 
slouken@1959
   126
 * function reverts back to behavior before the distinction between
slouken@1959
   127
 * sides was made.
slouken@1959
   128
 */
slouken@1959
   129
static void
slouken@2303
   130
HandleNonDeviceModifier(int keyboard,
slouken@1959
   131
                        unsigned int device_independent_mask,
slouken@1959
   132
                        unsigned int oldMods,
slouken@1959
   133
                        unsigned int newMods,
slouken@2303
   134
                        SDL_scancode scancode)
slouken@1959
   135
{
slouken@1959
   136
    unsigned int oldMask, newMask;
slouken@1959
   137
    
slouken@1959
   138
    /* Isolate just the bits we care about in the depedent bits so we can 
slouken@1959
   139
     * figure out what changed
slouken@1959
   140
     */ 
slouken@1959
   141
    oldMask = oldMods & device_independent_mask;
slouken@1959
   142
    newMask = newMods & device_independent_mask;
slouken@1959
   143
    
slouken@1959
   144
    if (oldMask && oldMask != newMask) {
slouken@2303
   145
        SDL_SendKeyboardKey(keyboard, SDL_RELEASED, scancode);
slouken@1959
   146
    } else if (newMask && oldMask != newMask) {
slouken@2303
   147
        SDL_SendKeyboardKey(keyboard, SDL_PRESSED, scancode);
slouken@1959
   148
    }
slouken@1959
   149
}
slouken@1959
   150
slouken@1959
   151
/* This is a helper function for HandleModifierSide. 
slouken@1959
   152
 * This function sets the actual SDL_PrivateKeyboard event.
slouken@1959
   153
 */
slouken@1959
   154
static void
slouken@2303
   155
HandleModifierOneSide(int keyboard,
slouken@1959
   156
                      unsigned int oldMods, unsigned int newMods,
slouken@2303
   157
                      SDL_scancode scancode, 
slouken@1959
   158
                      unsigned int sided_device_dependent_mask)
slouken@1959
   159
{
slouken@1959
   160
    unsigned int old_dep_mask, new_dep_mask;
slouken@1959
   161
slouken@1959
   162
    /* Isolate just the bits we care about in the depedent bits so we can 
slouken@1959
   163
     * figure out what changed
slouken@1959
   164
     */ 
slouken@1959
   165
    old_dep_mask = oldMods & sided_device_dependent_mask;
slouken@1959
   166
    new_dep_mask = newMods & sided_device_dependent_mask;
slouken@1959
   167
slouken@1959
   168
    /* We now know that this side bit flipped. But we don't know if
slouken@1959
   169
     * it went pressed to released or released to pressed, so we must 
slouken@1959
   170
     * find out which it is.
slouken@1959
   171
     */
slouken@1959
   172
    if (new_dep_mask && old_dep_mask != new_dep_mask) {
slouken@2303
   173
        SDL_SendKeyboardKey(keyboard, SDL_PRESSED, scancode);
slouken@1959
   174
    } else {
slouken@2303
   175
        SDL_SendKeyboardKey(keyboard, SDL_RELEASED, scancode);
slouken@1959
   176
    }
slouken@1959
   177
}
slouken@1959
   178
slouken@1959
   179
/* This is a helper function for DoSidedModifiers.
slouken@1959
   180
 * This function will figure out if the modifier key is the left or right side, 
slouken@1959
   181
 * e.g. left-shift vs right-shift. 
slouken@1959
   182
 */
slouken@1959
   183
static void
slouken@2303
   184
HandleModifierSide(int keyboard,
slouken@1959
   185
                   int device_independent_mask, 
slouken@1959
   186
                   unsigned int oldMods, unsigned int newMods, 
slouken@2303
   187
                   SDL_scancode left_scancode, 
slouken@2303
   188
                   SDL_scancode right_scancode,
slouken@1959
   189
                   unsigned int left_device_dependent_mask, 
slouken@1959
   190
                   unsigned int right_device_dependent_mask)
slouken@1959
   191
{
slouken@1959
   192
    unsigned int device_dependent_mask = (left_device_dependent_mask |
slouken@1959
   193
                                         right_device_dependent_mask);
slouken@1959
   194
    unsigned int diff_mod;
slouken@1959
   195
    
slouken@1959
   196
    /* On the basis that the device independent mask is set, but there are 
slouken@1959
   197
     * no device dependent flags set, we'll assume that we can't detect this 
slouken@1959
   198
     * keyboard and revert to the unsided behavior.
slouken@1959
   199
     */
slouken@1959
   200
    if ((device_dependent_mask & newMods) == 0) {
slouken@1959
   201
        /* Revert to the old behavior */
slouken@2303
   202
        HandleNonDeviceModifier(keyboard, device_independent_mask, oldMods, newMods, left_scancode);
slouken@1959
   203
        return;
slouken@1959
   204
    }
slouken@1959
   205
slouken@1959
   206
    /* XOR the previous state against the new state to see if there's a change */
slouken@1959
   207
    diff_mod = (device_dependent_mask & oldMods) ^
slouken@1959
   208
               (device_dependent_mask & newMods);
slouken@1959
   209
    if (diff_mod) {
slouken@1959
   210
        /* A change in state was found. Isolate the left and right bits 
slouken@1959
   211
         * to handle them separately just in case the values can simulataneously
slouken@1959
   212
         * change or if the bits don't both exist.
slouken@1959
   213
         */
slouken@1959
   214
        if (left_device_dependent_mask & diff_mod) {
slouken@2303
   215
            HandleModifierOneSide(keyboard, oldMods, newMods, left_scancode, left_device_dependent_mask);
slouken@1959
   216
        }
slouken@1959
   217
        if (right_device_dependent_mask & diff_mod) {
slouken@2303
   218
            HandleModifierOneSide(keyboard, oldMods, newMods, right_scancode, right_device_dependent_mask);
slouken@1959
   219
        }
slouken@1959
   220
    }
slouken@1959
   221
}
slouken@1959
   222
   
slouken@1959
   223
/* This is a helper function for DoSidedModifiers.
slouken@1959
   224
 * This function will release a key press in the case that 
slouken@1959
   225
 * it is clear that the modifier has been released (i.e. one side 
slouken@1959
   226
 * can't still be down).
slouken@1959
   227
 */
slouken@1959
   228
static void
slouken@2303
   229
ReleaseModifierSide(int keyboard,
slouken@1959
   230
                    unsigned int device_independent_mask, 
slouken@1959
   231
                    unsigned int oldMods, unsigned int newMods,
slouken@2303
   232
                    SDL_scancode left_scancode, 
slouken@2303
   233
                    SDL_scancode right_scancode,
slouken@1959
   234
                    unsigned int left_device_dependent_mask, 
slouken@1959
   235
                    unsigned int right_device_dependent_mask)
slouken@1959
   236
{
slouken@1959
   237
    unsigned int device_dependent_mask = (left_device_dependent_mask |
slouken@1959
   238
                                          right_device_dependent_mask);
slouken@1959
   239
slouken@1959
   240
    /* On the basis that the device independent mask is set, but there are 
slouken@1959
   241
     * no device dependent flags set, we'll assume that we can't detect this 
slouken@1959
   242
     * keyboard and revert to the unsided behavior.
slouken@1959
   243
     */
slouken@1959
   244
    if ((device_dependent_mask & oldMods) == 0) {
slouken@1959
   245
        /* In this case, we can't detect the keyboard, so use the left side 
slouken@1959
   246
         * to represent both, and release it. 
slouken@1959
   247
         */
slouken@2303
   248
        SDL_SendKeyboardKey(keyboard, SDL_RELEASED, left_scancode);
slouken@1959
   249
        return;
slouken@1959
   250
    }
slouken@1959
   251
slouken@1959
   252
    /* 
slouken@1959
   253
     * This could have been done in an if-else case because at this point,
slouken@1959
   254
     * we know that all keys have been released when calling this function. 
slouken@1959
   255
     * But I'm being paranoid so I want to handle each separately,
slouken@1959
   256
     * so I hope this doesn't cause other problems.
slouken@1959
   257
     */
slouken@1959
   258
    if ( left_device_dependent_mask & oldMods ) {
slouken@2303
   259
        SDL_SendKeyboardKey(keyboard, SDL_RELEASED, left_scancode);
slouken@1959
   260
    }
slouken@1959
   261
    if ( right_device_dependent_mask & oldMods ) {
slouken@2303
   262
        SDL_SendKeyboardKey(keyboard, SDL_RELEASED, right_scancode);
slouken@1959
   263
    }
slouken@1959
   264
}
slouken@1959
   265
slouken@1959
   266
/* This is a helper function for DoSidedModifiers.
slouken@1959
   267
 * This function handles the CapsLock case.
slouken@1959
   268
 */
slouken@1959
   269
static void
slouken@1959
   270
HandleCapsLock(int keyboard, unsigned short scancode,
slouken@1959
   271
               unsigned int oldMods, unsigned int newMods)
slouken@1959
   272
{
slouken@1959
   273
    unsigned int oldMask, newMask;
slouken@1959
   274
    
slouken@1959
   275
    oldMask = oldMods & NSAlphaShiftKeyMask;
slouken@1959
   276
    newMask = newMods & NSAlphaShiftKeyMask;
slouken@1959
   277
slouken@1959
   278
    if (oldMask != newMask) {
slouken@2303
   279
        SDL_SendKeyboardKey(keyboard, SDL_PRESSED, SDL_SCANCODE_CAPSLOCK);
slouken@2303
   280
        SDL_SendKeyboardKey(keyboard, SDL_RELEASED, SDL_SCANCODE_CAPSLOCK);
slouken@1959
   281
    }
slouken@1960
   282
slouken@1960
   283
    oldMask = oldMods & NSNumericPadKeyMask;
slouken@1960
   284
    newMask = newMods & NSNumericPadKeyMask;
slouken@1960
   285
slouken@1960
   286
    if (oldMask != newMask) {
slouken@2303
   287
        SDL_SendKeyboardKey(keyboard, SDL_PRESSED, SDL_SCANCODE_NUMLOCKCLEAR);
slouken@2303
   288
        SDL_SendKeyboardKey(keyboard, SDL_RELEASED, SDL_SCANCODE_NUMLOCKCLEAR);
slouken@1960
   289
    }
slouken@1959
   290
}
slouken@1959
   291
slouken@1959
   292
/* This function will handle the modifier keys and also determine the 
slouken@1959
   293
 * correct side of the key.
slouken@1959
   294
 */
slouken@1959
   295
static void
slouken@1959
   296
DoSidedModifiers(int keyboard, unsigned short scancode,
slouken@1959
   297
                 unsigned int oldMods, unsigned int newMods)
slouken@1959
   298
{
slouken@1959
   299
	/* Set up arrays for the key syms for the left and right side. */
slouken@2303
   300
    const SDL_scancode left_mapping[]  = {
slouken@2303
   301
        SDL_SCANCODE_LSHIFT,
slouken@2303
   302
        SDL_SCANCODE_LCTRL,
slouken@2303
   303
        SDL_SCANCODE_LALT,
slouken@2303
   304
        SDL_SCANCODE_LGUI
slouken@2303
   305
    };
slouken@2303
   306
    const SDL_scancode right_mapping[] = {
slouken@2303
   307
        SDL_SCANCODE_RSHIFT,
slouken@2303
   308
        SDL_SCANCODE_RCTRL,
slouken@2303
   309
        SDL_SCANCODE_RALT,
slouken@2303
   310
        SDL_SCANCODE_RGUI
slouken@2303
   311
    };
slouken@1959
   312
	/* Set up arrays for the device dependent masks with indices that 
slouken@1959
   313
     * correspond to the _mapping arrays 
slouken@1959
   314
     */
slouken@1959
   315
    const unsigned int left_device_mapping[]  = { NX_DEVICELSHIFTKEYMASK, NX_DEVICELCTLKEYMASK, NX_DEVICELALTKEYMASK, NX_DEVICELCMDKEYMASK };
slouken@1959
   316
    const unsigned int right_device_mapping[] = { NX_DEVICERSHIFTKEYMASK, NX_DEVICERCTLKEYMASK, NX_DEVICERALTKEYMASK, NX_DEVICERCMDKEYMASK };
slouken@1959
   317
slouken@1959
   318
    unsigned int i, bit;
slouken@1959
   319
slouken@1959
   320
    /* Handle CAPSLOCK separately because it doesn't have a left/right side */
slouken@1959
   321
    HandleCapsLock(keyboard, scancode, oldMods, newMods);
slouken@1959
   322
slouken@1959
   323
    /* Iterate through the bits, testing each against the old modifiers */
slouken@1959
   324
    for (i = 0, bit = NSShiftKeyMask; bit <= NSCommandKeyMask; bit <<= 1, ++i) {
slouken@1959
   325
        unsigned int oldMask, newMask;
slouken@1959
   326
		
slouken@1959
   327
        oldMask = oldMods & bit;
slouken@1959
   328
        newMask = newMods & bit;
slouken@1959
   329
		
slouken@1959
   330
        /* If the bit is set, we must always examine it because the left
slouken@1959
   331
         * and right side keys may alternate or both may be pressed.
slouken@1959
   332
         */
slouken@1959
   333
        if (newMask) {
slouken@2303
   334
            HandleModifierSide(keyboard, bit, oldMods, newMods,
slouken@1959
   335
                               left_mapping[i], right_mapping[i],
slouken@1959
   336
                               left_device_mapping[i], right_device_mapping[i]);
slouken@1959
   337
        }
slouken@1959
   338
        /* If the state changed from pressed to unpressed, we must examine
slouken@1959
   339
            * the device dependent bits to release the correct keys.
slouken@1959
   340
            */
slouken@1959
   341
        else if (oldMask && oldMask != newMask) {
slouken@2303
   342
            ReleaseModifierSide(keyboard, bit, oldMods, newMods,
slouken@1959
   343
                              left_mapping[i], right_mapping[i],
slouken@1959
   344
                              left_device_mapping[i], right_device_mapping[i]);
slouken@1959
   345
        }
slouken@1959
   346
    }
slouken@1959
   347
}
slouken@1959
   348
slouken@1959
   349
static void
slouken@1959
   350
HandleModifiers(_THIS, unsigned short scancode, unsigned int modifierFlags)
slouken@1959
   351
{
slouken@1959
   352
    SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
slouken@1959
   353
slouken@1959
   354
    if (modifierFlags == data->modifierFlags) {
slouken@1959
   355
    	return;
slouken@1959
   356
    }
slouken@1959
   357
slouken@1959
   358
    /* 
slouken@1959
   359
     * Starting with Panther (10.3.0), the ability to distinguish between 
slouken@1959
   360
     * left side and right side modifiers is available.
slouken@1959
   361
     */
slouken@1959
   362
    if (data->osversion >= 0x1030) {
slouken@1959
   363
        DoSidedModifiers(data->keyboard, scancode, data->modifierFlags, modifierFlags);
slouken@1959
   364
    } else {
slouken@1959
   365
        DoUnsidedModifiers(data->keyboard, scancode, data->modifierFlags, modifierFlags);
slouken@1959
   366
    }
slouken@1959
   367
    data->modifierFlags = modifierFlags;
slouken@1959
   368
}
slouken@1959
   369
slouken@2303
   370
static void
slouken@2303
   371
UpdateKeymap(SDL_VideoData *data)
slouken@2303
   372
{
slouken@2303
   373
    KeyboardLayoutRef key_layout;
slouken@2303
   374
    const void *chr_data;
slouken@2303
   375
    int i;
slouken@2303
   376
    SDL_scancode scancode;
slouken@2303
   377
    SDLKey keymap[SDL_NUM_SCANCODES];
slouken@2303
   378
slouken@2303
   379
    /* See if the keymap needs to be updated */
slouken@2303
   380
    KLGetCurrentKeyboardLayout(&key_layout);
slouken@2303
   381
    if (key_layout == data->key_layout) {
slouken@2303
   382
        return;
slouken@2303
   383
    }
slouken@2303
   384
    data->key_layout = key_layout;
slouken@2303
   385
slouken@2303
   386
    SDL_GetDefaultKeymap(keymap);
slouken@2303
   387
slouken@2303
   388
    /* Try Unicode data first (preferred as of Mac OS X 10.5) */
slouken@2303
   389
    KLGetKeyboardLayoutProperty(key_layout, kKLuchrData, &chr_data);
slouken@2303
   390
    if (chr_data) {
slouken@2303
   391
        UInt32 keyboard_type = LMGetKbdType();
slouken@2303
   392
        OSStatus err;
slouken@2303
   393
slouken@2305
   394
        for (i = 0; i < SDL_arraysize(darwin_scancode_table); i++) {
slouken@2303
   395
            UniChar s[8];
slouken@2303
   396
            UniCharCount len;
slouken@2303
   397
            UInt32 dead_key_state;
slouken@2303
   398
slouken@2303
   399
            /* Make sure this scancode is a valid character scancode */
slouken@2305
   400
            scancode = darwin_scancode_table[i];
slouken@2303
   401
            if (scancode == SDL_SCANCODE_UNKNOWN ||
slouken@2303
   402
                (keymap[scancode] & SDLK_SCANCODE_MASK)) {
slouken@2303
   403
                continue;
slouken@2303
   404
            }
slouken@2303
   405
slouken@2303
   406
            dead_key_state = 0;
slouken@2303
   407
            err = UCKeyTranslate (chr_data, i, kUCKeyActionDown,
slouken@2303
   408
                                  0, keyboard_type,
slouken@2303
   409
                                  kUCKeyTranslateNoDeadKeysMask,
slouken@2303
   410
                                  &dead_key_state, 8, &len, s);
slouken@2303
   411
            if (err != noErr)
slouken@2303
   412
                continue;
slouken@2303
   413
slouken@2303
   414
            if (len > 0 && s[0] != 0x10) {
slouken@2303
   415
                keymap[scancode] = s[0];
slouken@2303
   416
            }
slouken@2303
   417
        }
slouken@2303
   418
        SDL_SetKeymap(data->keyboard, 0, keymap, SDL_NUM_SCANCODES);
slouken@2303
   419
        return;
slouken@2303
   420
    }
slouken@2303
   421
slouken@2303
   422
    /* Fall back to older style key map data */
slouken@2303
   423
    KLGetKeyboardLayoutProperty(key_layout, kKLKCHRData, &chr_data);
slouken@2303
   424
    if (chr_data) {
slouken@2303
   425
        for (i = 0; i < 128; i++) {
slouken@2303
   426
            UInt32 c, state = 0;
slouken@2303
   427
slouken@2303
   428
            /* Make sure this scancode is a valid character scancode */
slouken@2305
   429
            scancode = darwin_scancode_table[i];
slouken@2303
   430
            if (scancode == SDL_SCANCODE_UNKNOWN ||
slouken@2303
   431
                (keymap[scancode] & SDLK_SCANCODE_MASK)) {
slouken@2303
   432
                continue;
slouken@2303
   433
            }
slouken@2303
   434
slouken@2304
   435
            c = KeyTranslate (chr_data, i, &state) & 255;
slouken@2303
   436
            if (state) {
slouken@2303
   437
                /* Dead key, process key up */
slouken@2304
   438
                c = KeyTranslate (chr_data, i | 128, &state) & 255;
slouken@2303
   439
            }
slouken@2303
   440
slouken@2304
   441
            if (c != 0 && c != 0x10) {
slouken@2303
   442
                /* MacRoman to Unicode table, taken from X.org sources */
slouken@2303
   443
                static const unsigned short macroman_table[128] = {
slouken@2303
   444
                    0xc4, 0xc5, 0xc7, 0xc9, 0xd1, 0xd6, 0xdc, 0xe1,
slouken@2303
   445
                    0xe0, 0xe2, 0xe4, 0xe3, 0xe5, 0xe7, 0xe9, 0xe8,
slouken@2303
   446
                    0xea, 0xeb, 0xed, 0xec, 0xee, 0xef, 0xf1, 0xf3,
slouken@2303
   447
                    0xf2, 0xf4, 0xf6, 0xf5, 0xfa, 0xf9, 0xfb, 0xfc,
slouken@2303
   448
                    0x2020, 0xb0, 0xa2, 0xa3, 0xa7, 0x2022, 0xb6, 0xdf,
slouken@2303
   449
                    0xae, 0xa9, 0x2122, 0xb4, 0xa8, 0x2260, 0xc6, 0xd8,
slouken@2303
   450
                    0x221e, 0xb1, 0x2264, 0x2265, 0xa5, 0xb5, 0x2202, 0x2211,
slouken@2303
   451
                    0x220f, 0x3c0, 0x222b, 0xaa, 0xba, 0x3a9, 0xe6, 0xf8,
slouken@2303
   452
                    0xbf, 0xa1, 0xac, 0x221a, 0x192, 0x2248, 0x2206, 0xab,
slouken@2303
   453
                    0xbb, 0x2026, 0xa0, 0xc0, 0xc3, 0xd5, 0x152, 0x153,
slouken@2303
   454
                    0x2013, 0x2014, 0x201c, 0x201d, 0x2018, 0x2019, 0xf7, 0x25ca,
slouken@2303
   455
                    0xff, 0x178, 0x2044, 0x20ac, 0x2039, 0x203a, 0xfb01, 0xfb02,
slouken@2303
   456
                    0x2021, 0xb7, 0x201a, 0x201e, 0x2030, 0xc2, 0xca, 0xc1,
slouken@2303
   457
                    0xcb, 0xc8, 0xcd, 0xce, 0xcf, 0xcc, 0xd3, 0xd4,
slouken@2303
   458
                    0xf8ff, 0xd2, 0xda, 0xdb, 0xd9, 0x131, 0x2c6, 0x2dc,
slouken@2303
   459
                    0xaf, 0x2d8, 0x2d9, 0x2da, 0xb8, 0x2dd, 0x2db, 0x2c7,
slouken@2303
   460
                };
slouken@2303
   461
slouken@2303
   462
                if (c >= 128) {
slouken@2303
   463
                    c = macroman_table[c - 128];
slouken@2303
   464
                }
slouken@2303
   465
                keymap[scancode] = c;
slouken@2303
   466
            }
slouken@2303
   467
        }
slouken@2303
   468
        SDL_SetKeymap(data->keyboard, 0, keymap, SDL_NUM_SCANCODES);
slouken@2303
   469
        return;
slouken@2303
   470
    }
slouken@2303
   471
}
slouken@2303
   472
slouken@1931
   473
void
slouken@1931
   474
Cocoa_InitKeyboard(_THIS)
slouken@1931
   475
{
slouken@1931
   476
    SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
slouken@1931
   477
    SDL_Keyboard keyboard;
slouken@2170
   478
    NSAutoreleasePool *pool;
slouken@1931
   479
slouken@2170
   480
    pool = [[NSAutoreleasePool alloc] init];
slouken@2289
   481
    data->fieldEdit = [[SDLTranslatorResponder alloc] initWithFrame:NSMakeRect(0.0, 0.0, 0.0, 0.0)];
slouken@2170
   482
    [pool release];
slouken@2169
   483
    
slouken@1931
   484
    SDL_zero(keyboard);
slouken@1931
   485
    data->keyboard = SDL_AddKeyboard(&keyboard, -1);
slouken@2303
   486
    UpdateKeymap(data);
slouken@2268
   487
    
slouken@2268
   488
    /* Set our own names for the platform-dependent but layout-independent keys */
slouken@2303
   489
    /* This key is NumLock on the MacBook keyboard. :) */
slouken@2303
   490
    /*SDL_SetScancodeName(SDL_SCANCODE_NUMLOCKCLEAR, "Clear");*/
slouken@2303
   491
    SDL_SetScancodeName(SDL_SCANCODE_LALT, "Left Option");
slouken@2303
   492
    SDL_SetScancodeName(SDL_SCANCODE_LGUI, "Left Command");
slouken@2303
   493
    SDL_SetScancodeName(SDL_SCANCODE_RALT, "Right Option");
slouken@2303
   494
    SDL_SetScancodeName(SDL_SCANCODE_RGUI, "Right Command");
slouken@1931
   495
}
slouken@1931
   496
slouken@1931
   497
void
slouken@1959
   498
Cocoa_HandleKeyEvent(_THIS, NSEvent *event)
slouken@1959
   499
{
slouken@1959
   500
    SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
slouken@1959
   501
    unsigned short scancode = [event keyCode];
slouken@2303
   502
    SDL_scancode code;
slouken@1959
   503
    const char *text;
slouken@1959
   504
slouken@2268
   505
    if ((scancode == 10 || scancode == 50) && KBGetLayoutType(LMGetKbdType()) == kKeyboardISO) {
slouken@2268
   506
        /* see comments in SDL_cocoakeys.h */
slouken@2268
   507
        scancode = 60 - scancode;
slouken@2268
   508
    }
slouken@2305
   509
    if (scancode < SDL_arraysize(darwin_scancode_table)) {
slouken@2305
   510
        code = darwin_scancode_table[scancode];
slouken@2268
   511
    }
slouken@2268
   512
    else {
slouken@1959
   513
        /* Hmm, does this ever happen?  If so, need to extend the keymap... */
slouken@2303
   514
        code = SDL_SCANCODE_UNKNOWN;
slouken@1959
   515
    }
slouken@1959
   516
slouken@1959
   517
    switch ([event type]) {
slouken@1959
   518
    case NSKeyDown:
slouken@2129
   519
        if (![event isARepeat]) {
slouken@2303
   520
            /* See if we need to rebuild the keyboard layout */
slouken@2303
   521
            UpdateKeymap(data);
slouken@2303
   522
slouken@2303
   523
            SDL_SendKeyboardKey(data->keyboard, SDL_PRESSED, code);
slouken@2268
   524
#if 1
slouken@2303
   525
            if (code == SDL_SCANCODE_UNKNOWN) {
slouken@2268
   526
                fprintf(stderr, "The key you just pressed is not recognized by SDL. To help get this fixed, report this to the SDL mailing list <sdl@libsdl.org> or to Christian Walther <cwalther@gmx.ch>. Mac virtual key code is %d.\n", scancode);
slouken@2268
   527
            }
slouken@2268
   528
#endif
slouken@1959
   529
        }
slouken@2129
   530
        if (SDL_EventState(SDL_TEXTINPUT, SDL_QUERY)) {
slouken@2268
   531
            /* FIXME CW 2007-08-16: only send those events to the field editor for which we actually want text events, not e.g. esc or function keys. Arrow keys in particular seem to produce crashes sometimes. */
gzjjgod@3127
   532
            NSLog(@"interpretKeyEvents");
gzjjgod@3127
   533
            if (! [[data->fieldEdit superview] isEqual: [[event window] contentView]])
gzjjgod@3127
   534
            {
gzjjgod@3127
   535
                NSLog(@"add fieldEdit to window contentView");
gzjjgod@3127
   536
                [data->fieldEdit removeFromSuperview];
gzjjgod@3127
   537
                [[[event window] contentView] addSubview: data->fieldEdit];
gzjjgod@3127
   538
                [[event window] makeFirstResponder: data->fieldEdit];
gzjjgod@3127
   539
            }
slouken@2169
   540
            [data->fieldEdit interpretKeyEvents:[NSArray arrayWithObject:event]];
gzjjgod@3127
   541
#if 0
slouken@2129
   542
            text = [[event characters] UTF8String];
slouken@2129
   543
            if(text && *text) {
slouken@2129
   544
                SDL_SendKeyboardText(data->keyboard, text);
slouken@2273
   545
                [data->fieldEdit setString:@""];
slouken@2129
   546
            }
gzjjgod@3127
   547
#endif
slouken@1959
   548
        }
slouken@1959
   549
        break;
slouken@1959
   550
    case NSKeyUp:
slouken@2303
   551
        SDL_SendKeyboardKey(data->keyboard, SDL_RELEASED, code);
slouken@1959
   552
        break;
slouken@1959
   553
    case NSFlagsChanged:
slouken@2268
   554
        /* FIXME CW 2007-08-14: check if this whole mess that takes up half of this file is really necessary */
slouken@1959
   555
        HandleModifiers(_this, scancode, [event modifierFlags]);
slouken@1959
   556
        break;
slouken@2268
   557
    default: /* just to avoid compiler warnings */
slouken@2268
   558
        break;
slouken@2268
   559
    }
slouken@2268
   560
}
slouken@2268
   561
slouken@1959
   562
void
slouken@1931
   563
Cocoa_QuitKeyboard(_THIS)
slouken@1931
   564
{
slouken@1931
   565
    SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
slouken@2270
   566
    NSAutoreleasePool *pool;
slouken@1931
   567
slouken@1931
   568
    SDL_DelKeyboard(data->keyboard);
slouken@2169
   569
slouken@2270
   570
    pool = [[NSAutoreleasePool alloc] init];
slouken@2169
   571
    [data->fieldEdit release];
slouken@2270
   572
    [pool release];
slouken@1931
   573
}
slouken@1931
   574
slouken@1931
   575
/* vi: set ts=4 sw=4 expandtab: */