src/video/cocoa/SDL_cocoakeyboard.m
author Sam Lantinga <slouken@libsdl.org>
Sun, 09 May 2010 20:47:22 -0700
changeset 4465 3e69e077cb95
parent 4436 d3c193100522
child 4498 3d91e31fcf71
permissions -rw-r--r--
Removed multi-mouse / multi-keyboard support in anticipation of a real multi-mouse and multi-touch API.

Plus, this lets me start implementing cursor support.
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2009 Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Lesser General Public
     7     License as published by the Free Software Foundation; either
     8     version 2.1 of the License, or (at your option) any later version.
     9 
    10     This library is distributed in the hope that it will be useful,
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13     Lesser General Public License for more details.
    14 
    15     You should have received a copy of the GNU Lesser General Public
    16     License along with this library; if not, write to the Free Software
    17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 */
    22 #include "SDL_config.h"
    23 
    24 #include "SDL_cocoavideo.h"
    25 
    26 #include "../../events/SDL_keyboard_c.h"
    27 #include "../../events/scancodes_darwin.h"
    28 
    29 #include <Carbon/Carbon.h>
    30 
    31 //#define DEBUG_IME NSLog
    32 #define DEBUG_IME
    33 
    34 #ifndef NX_DEVICERCTLKEYMASK
    35     #define NX_DEVICELCTLKEYMASK    0x00000001
    36 #endif
    37 #ifndef NX_DEVICELSHIFTKEYMASK
    38     #define NX_DEVICELSHIFTKEYMASK  0x00000002
    39 #endif
    40 #ifndef NX_DEVICERSHIFTKEYMASK
    41     #define NX_DEVICERSHIFTKEYMASK  0x00000004
    42 #endif
    43 #ifndef NX_DEVICELCMDKEYMASK
    44     #define NX_DEVICELCMDKEYMASK    0x00000008
    45 #endif
    46 #ifndef NX_DEVICERCMDKEYMASK
    47     #define NX_DEVICERCMDKEYMASK    0x00000010
    48 #endif
    49 #ifndef NX_DEVICELALTKEYMASK
    50     #define NX_DEVICELALTKEYMASK    0x00000020
    51 #endif
    52 #ifndef NX_DEVICERALTKEYMASK
    53     #define NX_DEVICERALTKEYMASK    0x00000040
    54 #endif
    55 #ifndef NX_DEVICERCTLKEYMASK
    56     #define NX_DEVICERCTLKEYMASK    0x00002000
    57 #endif
    58 
    59 @interface SDLTranslatorResponder : NSView <NSTextInput>
    60 {
    61     NSString *_markedText;
    62     NSRange   _markedRange;
    63     NSRange   _selectedRange;
    64     SDL_Rect  _inputRect;
    65 }
    66 - (void) doCommandBySelector:(SEL)myselector;
    67 - (void) setInputRect:(SDL_Rect *) rect;
    68 @end
    69 
    70 @implementation SDLTranslatorResponder
    71 
    72 - (void) setInputRect:(SDL_Rect *) rect
    73 {
    74     _inputRect = *rect;
    75 }
    76 
    77 - (void) insertText:(id) aString
    78 {
    79     const char *str;
    80 
    81     DEBUG_IME(@"insertText: %@", aString);
    82 
    83     /* Could be NSString or NSAttributedString, so we have
    84      * to test and convert it before return as SDL event */
    85     if ([aString isKindOfClass: [NSAttributedString class]])
    86         str = [[aString string] UTF8String];
    87     else
    88         str = [aString UTF8String];
    89 
    90     SDL_SendKeyboardText(str);
    91 }
    92 
    93 - (void) doCommandBySelector:(SEL) myselector
    94 {
    95     // No need to do anything since we are not using Cocoa
    96     // selectors to handle special keys, instead we use SDL
    97     // key events to do the same job.
    98 }
    99 
   100 - (BOOL) hasMarkedText
   101 {
   102     return _markedText != nil;
   103 }
   104 
   105 - (NSRange) markedRange
   106 {
   107     return _markedRange;
   108 }
   109 
   110 - (NSRange) selectedRange
   111 {
   112     return _selectedRange;
   113 }
   114 
   115 - (void) setMarkedText:(id) aString
   116          selectedRange:(NSRange) selRange
   117 {
   118     if ([aString isKindOfClass: [NSAttributedString class]])
   119         aString = [aString string];
   120 
   121     if ([aString length] == 0)
   122     {
   123         [self unmarkText];
   124         return;
   125     }
   126 
   127     if (_markedText != aString)
   128     {
   129         [_markedText release];
   130         _markedText = [aString retain];
   131     }
   132 
   133     _selectedRange = selRange;
   134     _markedRange = NSMakeRange(0, [aString length]);
   135 
   136     SDL_SendEditingText([aString UTF8String],
   137                         selRange.location, selRange.length);
   138 
   139     DEBUG_IME(@"setMarkedText: %@, (%d, %d)", _markedText,
   140           selRange.location, selRange.length);
   141 }
   142 
   143 - (void) unmarkText
   144 {
   145     [_markedText release];
   146     _markedText = nil;
   147 }
   148 
   149 - (NSRect) firstRectForCharacterRange: (NSRange) theRange
   150 {
   151     NSWindow *window = [self window];
   152     NSRect contentRect = [window contentRectForFrameRect: [window frame]];
   153     float windowHeight = contentRect.size.height;
   154     NSRect rect = NSMakeRect(_inputRect.x, windowHeight - _inputRect.y - _inputRect.h,
   155                              _inputRect.w, _inputRect.h);
   156 
   157     DEBUG_IME(@"firstRectForCharacterRange: (%d, %d): windowHeight = %g, rect = %@",
   158             theRange.location, theRange.length, windowHeight,
   159             NSStringFromRect(rect));
   160     rect.origin = [[self window] convertBaseToScreen: rect.origin];
   161 
   162     return rect;
   163 }
   164 
   165 - (NSAttributedString *) attributedSubstringFromRange: (NSRange) theRange
   166 {
   167     DEBUG_IME(@"attributedSubstringFromRange: (%d, %d)", theRange.location, theRange.length);
   168     return nil;
   169 }
   170 
   171 /* Needs long instead of NSInteger for compilation on Mac OS X 10.4 */
   172 - (long) conversationIdentifier
   173 {
   174     return (long) self;
   175 }
   176 
   177 // This method returns the index for character that is 
   178 // nearest to thePoint.  thPoint is in screen coordinate system.
   179 - (NSUInteger) characterIndexForPoint:(NSPoint) thePoint
   180 {
   181     DEBUG_IME(@"characterIndexForPoint: (%g, %g)", thePoint.x, thePoint.y);
   182     return 0;
   183 }
   184 
   185 // This method is the key to attribute extension. 
   186 // We could add new attributes through this method.
   187 // NSInputServer examines the return value of this
   188 // method & constructs appropriate attributed string.
   189 - (NSArray *) validAttributesForMarkedText
   190 {
   191     return [NSArray array];
   192 }
   193 
   194 @end
   195 
   196 /* This is the original behavior, before support was added for 
   197  * differentiating between left and right versions of the keys.
   198  */
   199 static void
   200 DoUnsidedModifiers(unsigned short scancode,
   201                    unsigned int oldMods, unsigned int newMods)
   202 {
   203     const int mapping[] = {
   204         SDL_SCANCODE_CAPSLOCK,
   205         SDL_SCANCODE_LSHIFT,
   206         SDL_SCANCODE_LCTRL,
   207         SDL_SCANCODE_LALT,
   208         SDL_SCANCODE_LGUI
   209     };
   210     unsigned int i, bit;
   211 
   212     /* Iterate through the bits, testing each against the current modifiers */
   213     for (i = 0, bit = NSAlphaShiftKeyMask; bit <= NSCommandKeyMask; bit <<= 1, ++i) {
   214         unsigned int oldMask, newMask;
   215 
   216         oldMask = oldMods & bit;
   217         newMask = newMods & bit;
   218 
   219         if (oldMask && oldMask != newMask) {        /* modifier up event */
   220             /* If this was Caps Lock, we need some additional voodoo to make SDL happy */
   221             if (bit == NSAlphaShiftKeyMask) {
   222                 SDL_SendKeyboardKey(SDL_PRESSED, mapping[i]);
   223             }
   224             SDL_SendKeyboardKey(SDL_RELEASED, mapping[i]);
   225         } else if (newMask && oldMask != newMask) { /* modifier down event */
   226             SDL_SendKeyboardKey(SDL_PRESSED, mapping[i]);
   227             /* If this was Caps Lock, we need some additional voodoo to make SDL happy */
   228             if (bit == NSAlphaShiftKeyMask) {
   229                 SDL_SendKeyboardKey(SDL_RELEASED, mapping[i]);
   230             }
   231         }
   232     }
   233 }
   234 
   235 /* This is a helper function for HandleModifierSide. This 
   236  * function reverts back to behavior before the distinction between
   237  * sides was made.
   238  */
   239 static void
   240 HandleNonDeviceModifier(unsigned int device_independent_mask,
   241                         unsigned int oldMods,
   242                         unsigned int newMods,
   243                         SDL_scancode scancode)
   244 {
   245     unsigned int oldMask, newMask;
   246     
   247     /* Isolate just the bits we care about in the depedent bits so we can 
   248      * figure out what changed
   249      */ 
   250     oldMask = oldMods & device_independent_mask;
   251     newMask = newMods & device_independent_mask;
   252     
   253     if (oldMask && oldMask != newMask) {
   254         SDL_SendKeyboardKey(SDL_RELEASED, scancode);
   255     } else if (newMask && oldMask != newMask) {
   256         SDL_SendKeyboardKey(SDL_PRESSED, scancode);
   257     }
   258 }
   259 
   260 /* This is a helper function for HandleModifierSide. 
   261  * This function sets the actual SDL_PrivateKeyboard event.
   262  */
   263 static void
   264 HandleModifierOneSide(unsigned int oldMods, unsigned int newMods,
   265                       SDL_scancode scancode, 
   266                       unsigned int sided_device_dependent_mask)
   267 {
   268     unsigned int old_dep_mask, new_dep_mask;
   269 
   270     /* Isolate just the bits we care about in the depedent bits so we can 
   271      * figure out what changed
   272      */ 
   273     old_dep_mask = oldMods & sided_device_dependent_mask;
   274     new_dep_mask = newMods & sided_device_dependent_mask;
   275 
   276     /* We now know that this side bit flipped. But we don't know if
   277      * it went pressed to released or released to pressed, so we must 
   278      * find out which it is.
   279      */
   280     if (new_dep_mask && old_dep_mask != new_dep_mask) {
   281         SDL_SendKeyboardKey(SDL_PRESSED, scancode);
   282     } else {
   283         SDL_SendKeyboardKey(SDL_RELEASED, scancode);
   284     }
   285 }
   286 
   287 /* This is a helper function for DoSidedModifiers.
   288  * This function will figure out if the modifier key is the left or right side, 
   289  * e.g. left-shift vs right-shift. 
   290  */
   291 static void
   292 HandleModifierSide(int device_independent_mask, 
   293                    unsigned int oldMods, unsigned int newMods, 
   294                    SDL_scancode left_scancode, 
   295                    SDL_scancode right_scancode,
   296                    unsigned int left_device_dependent_mask, 
   297                    unsigned int right_device_dependent_mask)
   298 {
   299     unsigned int device_dependent_mask = (left_device_dependent_mask |
   300                                          right_device_dependent_mask);
   301     unsigned int diff_mod;
   302     
   303     /* On the basis that the device independent mask is set, but there are 
   304      * no device dependent flags set, we'll assume that we can't detect this 
   305      * keyboard and revert to the unsided behavior.
   306      */
   307     if ((device_dependent_mask & newMods) == 0) {
   308         /* Revert to the old behavior */
   309         HandleNonDeviceModifier(device_independent_mask, oldMods, newMods, left_scancode);
   310         return;
   311     }
   312 
   313     /* XOR the previous state against the new state to see if there's a change */
   314     diff_mod = (device_dependent_mask & oldMods) ^
   315                (device_dependent_mask & newMods);
   316     if (diff_mod) {
   317         /* A change in state was found. Isolate the left and right bits 
   318          * to handle them separately just in case the values can simulataneously
   319          * change or if the bits don't both exist.
   320          */
   321         if (left_device_dependent_mask & diff_mod) {
   322             HandleModifierOneSide(oldMods, newMods, left_scancode, left_device_dependent_mask);
   323         }
   324         if (right_device_dependent_mask & diff_mod) {
   325             HandleModifierOneSide(oldMods, newMods, right_scancode, right_device_dependent_mask);
   326         }
   327     }
   328 }
   329    
   330 /* This is a helper function for DoSidedModifiers.
   331  * This function will release a key press in the case that 
   332  * it is clear that the modifier has been released (i.e. one side 
   333  * can't still be down).
   334  */
   335 static void
   336 ReleaseModifierSide(unsigned int device_independent_mask, 
   337                     unsigned int oldMods, unsigned int newMods,
   338                     SDL_scancode left_scancode, 
   339                     SDL_scancode right_scancode,
   340                     unsigned int left_device_dependent_mask, 
   341                     unsigned int right_device_dependent_mask)
   342 {
   343     unsigned int device_dependent_mask = (left_device_dependent_mask |
   344                                           right_device_dependent_mask);
   345 
   346     /* On the basis that the device independent mask is set, but there are 
   347      * no device dependent flags set, we'll assume that we can't detect this 
   348      * keyboard and revert to the unsided behavior.
   349      */
   350     if ((device_dependent_mask & oldMods) == 0) {
   351         /* In this case, we can't detect the keyboard, so use the left side 
   352          * to represent both, and release it. 
   353          */
   354         SDL_SendKeyboardKey(SDL_RELEASED, left_scancode);
   355         return;
   356     }
   357 
   358     /* 
   359      * This could have been done in an if-else case because at this point,
   360      * we know that all keys have been released when calling this function. 
   361      * But I'm being paranoid so I want to handle each separately,
   362      * so I hope this doesn't cause other problems.
   363      */
   364     if ( left_device_dependent_mask & oldMods ) {
   365         SDL_SendKeyboardKey(SDL_RELEASED, left_scancode);
   366     }
   367     if ( right_device_dependent_mask & oldMods ) {
   368         SDL_SendKeyboardKey(SDL_RELEASED, right_scancode);
   369     }
   370 }
   371 
   372 /* This is a helper function for DoSidedModifiers.
   373  * This function handles the CapsLock case.
   374  */
   375 static void
   376 HandleCapsLock(unsigned short scancode,
   377                unsigned int oldMods, unsigned int newMods)
   378 {
   379     unsigned int oldMask, newMask;
   380     
   381     oldMask = oldMods & NSAlphaShiftKeyMask;
   382     newMask = newMods & NSAlphaShiftKeyMask;
   383 
   384     if (oldMask != newMask) {
   385         SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_CAPSLOCK);
   386         SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_CAPSLOCK);
   387     }
   388 
   389     oldMask = oldMods & NSNumericPadKeyMask;
   390     newMask = newMods & NSNumericPadKeyMask;
   391 
   392     if (oldMask != newMask) {
   393         SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_NUMLOCKCLEAR);
   394         SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_NUMLOCKCLEAR);
   395     }
   396 }
   397 
   398 /* This function will handle the modifier keys and also determine the 
   399  * correct side of the key.
   400  */
   401 static void
   402 DoSidedModifiers(unsigned short scancode,
   403                  unsigned int oldMods, unsigned int newMods)
   404 {
   405 	/* Set up arrays for the key syms for the left and right side. */
   406     const SDL_scancode left_mapping[]  = {
   407         SDL_SCANCODE_LSHIFT,
   408         SDL_SCANCODE_LCTRL,
   409         SDL_SCANCODE_LALT,
   410         SDL_SCANCODE_LGUI
   411     };
   412     const SDL_scancode right_mapping[] = {
   413         SDL_SCANCODE_RSHIFT,
   414         SDL_SCANCODE_RCTRL,
   415         SDL_SCANCODE_RALT,
   416         SDL_SCANCODE_RGUI
   417     };
   418 	/* Set up arrays for the device dependent masks with indices that 
   419      * correspond to the _mapping arrays 
   420      */
   421     const unsigned int left_device_mapping[]  = { NX_DEVICELSHIFTKEYMASK, NX_DEVICELCTLKEYMASK, NX_DEVICELALTKEYMASK, NX_DEVICELCMDKEYMASK };
   422     const unsigned int right_device_mapping[] = { NX_DEVICERSHIFTKEYMASK, NX_DEVICERCTLKEYMASK, NX_DEVICERALTKEYMASK, NX_DEVICERCMDKEYMASK };
   423 
   424     unsigned int i, bit;
   425 
   426     /* Handle CAPSLOCK separately because it doesn't have a left/right side */
   427     HandleCapsLock(scancode, oldMods, newMods);
   428 
   429     /* Iterate through the bits, testing each against the old modifiers */
   430     for (i = 0, bit = NSShiftKeyMask; bit <= NSCommandKeyMask; bit <<= 1, ++i) {
   431         unsigned int oldMask, newMask;
   432 		
   433         oldMask = oldMods & bit;
   434         newMask = newMods & bit;
   435 		
   436         /* If the bit is set, we must always examine it because the left
   437          * and right side keys may alternate or both may be pressed.
   438          */
   439         if (newMask) {
   440             HandleModifierSide(bit, oldMods, newMods,
   441                                left_mapping[i], right_mapping[i],
   442                                left_device_mapping[i], right_device_mapping[i]);
   443         }
   444         /* If the state changed from pressed to unpressed, we must examine
   445             * the device dependent bits to release the correct keys.
   446             */
   447         else if (oldMask && oldMask != newMask) {
   448             ReleaseModifierSide(bit, oldMods, newMods,
   449                               left_mapping[i], right_mapping[i],
   450                               left_device_mapping[i], right_device_mapping[i]);
   451         }
   452     }
   453 }
   454 
   455 static void
   456 HandleModifiers(_THIS, unsigned short scancode, unsigned int modifierFlags)
   457 {
   458     SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
   459 
   460     if (modifierFlags == data->modifierFlags) {
   461     	return;
   462     }
   463 
   464     /* 
   465      * Starting with Panther (10.3.0), the ability to distinguish between 
   466      * left side and right side modifiers is available.
   467      */
   468     if (data->osversion >= 0x1030) {
   469         DoSidedModifiers(scancode, data->modifierFlags, modifierFlags);
   470     } else {
   471         DoUnsidedModifiers(scancode, data->modifierFlags, modifierFlags);
   472     }
   473     data->modifierFlags = modifierFlags;
   474 }
   475 
   476 static void
   477 UpdateKeymap(SDL_VideoData *data)
   478 {
   479 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
   480     TISInputSourceRef key_layout;
   481 #else
   482     KeyboardLayoutRef key_layout;
   483 #endif
   484     const void *chr_data;
   485     int i;
   486     SDL_scancode scancode;
   487     SDLKey keymap[SDL_NUM_SCANCODES];
   488 
   489     /* See if the keymap needs to be updated */
   490 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
   491     key_layout = TISCopyCurrentKeyboardLayoutInputSource();
   492 #else
   493     KLGetCurrentKeyboardLayout(&key_layout);
   494 #endif
   495     if (key_layout == data->key_layout) {
   496         return;
   497     }
   498     data->key_layout = key_layout;
   499 
   500     SDL_GetDefaultKeymap(keymap);
   501 
   502     /* Try Unicode data first (preferred as of Mac OS X 10.5) */
   503 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
   504     CFDataRef uchrDataRef = TISGetInputSourceProperty(key_layout, kTISPropertyUnicodeKeyLayoutData);
   505     if (uchrDataRef)
   506         chr_data = CFDataGetBytePtr(uchrDataRef);
   507     else
   508         goto cleanup;
   509 #else
   510     KLGetKeyboardLayoutProperty(key_layout, kKLuchrData, &chr_data);
   511 #endif
   512     if (chr_data) {
   513         UInt32 keyboard_type = LMGetKbdType();
   514         OSStatus err;
   515 
   516         for (i = 0; i < SDL_arraysize(darwin_scancode_table); i++) {
   517             UniChar s[8];
   518             UniCharCount len;
   519             UInt32 dead_key_state;
   520 
   521             /* Make sure this scancode is a valid character scancode */
   522             scancode = darwin_scancode_table[i];
   523             if (scancode == SDL_SCANCODE_UNKNOWN ||
   524                 (keymap[scancode] & SDLK_SCANCODE_MASK)) {
   525                 continue;
   526             }
   527 
   528             dead_key_state = 0;
   529             err = UCKeyTranslate ((UCKeyboardLayout *) chr_data,
   530                                   i, kUCKeyActionDown,
   531                                   0, keyboard_type,
   532                                   kUCKeyTranslateNoDeadKeysMask,
   533                                   &dead_key_state, 8, &len, s);
   534             if (err != noErr)
   535                 continue;
   536 
   537             if (len > 0 && s[0] != 0x10) {
   538                 keymap[scancode] = s[0];
   539             }
   540         }
   541         SDL_SetKeymap(0, keymap, SDL_NUM_SCANCODES);
   542         return;
   543     }
   544 
   545 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
   546 cleanup:
   547     CFRelease(key_layout);
   548 #else
   549     /* Fall back to older style key map data */
   550     KLGetKeyboardLayoutProperty(key_layout, kKLKCHRData, &chr_data);
   551     if (chr_data) {
   552         for (i = 0; i < 128; i++) {
   553             UInt32 c, state = 0;
   554 
   555             /* Make sure this scancode is a valid character scancode */
   556             scancode = darwin_scancode_table[i];
   557             if (scancode == SDL_SCANCODE_UNKNOWN ||
   558                 (keymap[scancode] & SDLK_SCANCODE_MASK)) {
   559                 continue;
   560             }
   561 
   562             c = KeyTranslate (chr_data, i, &state) & 255;
   563             if (state) {
   564                 /* Dead key, process key up */
   565                 c = KeyTranslate (chr_data, i | 128, &state) & 255;
   566             }
   567 
   568             if (c != 0 && c != 0x10) {
   569                 /* MacRoman to Unicode table, taken from X.org sources */
   570                 static const unsigned short macroman_table[128] = {
   571                     0xc4, 0xc5, 0xc7, 0xc9, 0xd1, 0xd6, 0xdc, 0xe1,
   572                     0xe0, 0xe2, 0xe4, 0xe3, 0xe5, 0xe7, 0xe9, 0xe8,
   573                     0xea, 0xeb, 0xed, 0xec, 0xee, 0xef, 0xf1, 0xf3,
   574                     0xf2, 0xf4, 0xf6, 0xf5, 0xfa, 0xf9, 0xfb, 0xfc,
   575                     0x2020, 0xb0, 0xa2, 0xa3, 0xa7, 0x2022, 0xb6, 0xdf,
   576                     0xae, 0xa9, 0x2122, 0xb4, 0xa8, 0x2260, 0xc6, 0xd8,
   577                     0x221e, 0xb1, 0x2264, 0x2265, 0xa5, 0xb5, 0x2202, 0x2211,
   578                     0x220f, 0x3c0, 0x222b, 0xaa, 0xba, 0x3a9, 0xe6, 0xf8,
   579                     0xbf, 0xa1, 0xac, 0x221a, 0x192, 0x2248, 0x2206, 0xab,
   580                     0xbb, 0x2026, 0xa0, 0xc0, 0xc3, 0xd5, 0x152, 0x153,
   581                     0x2013, 0x2014, 0x201c, 0x201d, 0x2018, 0x2019, 0xf7, 0x25ca,
   582                     0xff, 0x178, 0x2044, 0x20ac, 0x2039, 0x203a, 0xfb01, 0xfb02,
   583                     0x2021, 0xb7, 0x201a, 0x201e, 0x2030, 0xc2, 0xca, 0xc1,
   584                     0xcb, 0xc8, 0xcd, 0xce, 0xcf, 0xcc, 0xd3, 0xd4,
   585                     0xf8ff, 0xd2, 0xda, 0xdb, 0xd9, 0x131, 0x2c6, 0x2dc,
   586                     0xaf, 0x2d8, 0x2d9, 0x2da, 0xb8, 0x2dd, 0x2db, 0x2c7,
   587                 };
   588 
   589                 if (c >= 128) {
   590                     c = macroman_table[c - 128];
   591                 }
   592                 keymap[scancode] = c;
   593             }
   594         }
   595         SDL_SetKeymap(0, keymap, SDL_NUM_SCANCODES);
   596         return;
   597     }
   598 #endif
   599 }
   600 
   601 void
   602 Cocoa_InitKeyboard(_THIS)
   603 {
   604     SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
   605 
   606     UpdateKeymap(data);
   607     
   608     /* Set our own names for the platform-dependent but layout-independent keys */
   609     /* This key is NumLock on the MacBook keyboard. :) */
   610     /*SDL_SetScancodeName(SDL_SCANCODE_NUMLOCKCLEAR, "Clear");*/
   611     SDL_SetScancodeName(SDL_SCANCODE_LALT, "Left Option");
   612     SDL_SetScancodeName(SDL_SCANCODE_LGUI, "Left Command");
   613     SDL_SetScancodeName(SDL_SCANCODE_RALT, "Right Option");
   614     SDL_SetScancodeName(SDL_SCANCODE_RGUI, "Right Command");
   615 }
   616 
   617 void
   618 Cocoa_StartTextInput(_THIS)
   619 {
   620     SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
   621     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
   622     NSView *parentView = [[NSApp keyWindow] contentView];
   623 
   624     /* We only keep one field editor per process, since only the front most
   625      * window can receive text input events, so it make no sense to keep more
   626      * than one copy. When we switched to another window and requesting for
   627      * text input, simply remove the field editor from its superview then add
   628      * it to the front most window's content view */
   629     if (!data->fieldEdit) {
   630         data->fieldEdit =
   631             [[SDLTranslatorResponder alloc] initWithFrame: NSMakeRect(0.0, 0.0, 0.0, 0.0)];
   632     }
   633 
   634     if (![[data->fieldEdit superview] isEqual: parentView])
   635     {
   636         // DEBUG_IME(@"add fieldEdit to window contentView");
   637         [data->fieldEdit removeFromSuperview];
   638         [parentView addSubview: data->fieldEdit];
   639         [[NSApp keyWindow] makeFirstResponder: data->fieldEdit];
   640     }
   641 
   642     [pool release];
   643 }
   644 
   645 void
   646 Cocoa_StopTextInput(_THIS)
   647 {
   648     SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
   649 
   650     if (data && data->fieldEdit) {
   651         NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
   652         [data->fieldEdit removeFromSuperview];
   653         [data->fieldEdit release];
   654         data->fieldEdit = nil;
   655         [pool release];
   656     }
   657 }
   658 
   659 void
   660 Cocoa_SetTextInputRect(_THIS, SDL_Rect *rect)
   661 {
   662     SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
   663 
   664     [data->fieldEdit setInputRect: rect];
   665 }
   666 
   667 void
   668 Cocoa_HandleKeyEvent(_THIS, NSEvent *event)
   669 {
   670     SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
   671     unsigned short scancode = [event keyCode];
   672     SDL_scancode code;
   673 #if 0
   674     const char *text;
   675 #endif
   676 
   677     if ((scancode == 10 || scancode == 50) && KBGetLayoutType(LMGetKbdType()) == kKeyboardISO) {
   678         /* see comments in SDL_cocoakeys.h */
   679         scancode = 60 - scancode;
   680     }
   681     if (scancode < SDL_arraysize(darwin_scancode_table)) {
   682         code = darwin_scancode_table[scancode];
   683     }
   684     else {
   685         /* Hmm, does this ever happen?  If so, need to extend the keymap... */
   686         code = SDL_SCANCODE_UNKNOWN;
   687     }
   688 
   689     switch ([event type]) {
   690     case NSKeyDown:
   691         if (![event isARepeat]) {
   692             /* See if we need to rebuild the keyboard layout */
   693             UpdateKeymap(data);
   694 
   695             SDL_SendKeyboardKey(SDL_PRESSED, code);
   696 #if 1
   697             if (code == SDL_SCANCODE_UNKNOWN) {
   698                 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);
   699             }
   700 #endif
   701         }
   702         if (SDL_EventState(SDL_TEXTINPUT, SDL_QUERY)) {
   703             /* 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. */
   704             [data->fieldEdit interpretKeyEvents:[NSArray arrayWithObject:event]];
   705 #if 0
   706             text = [[event characters] UTF8String];
   707             if(text && *text) {
   708                 SDL_SendKeyboardText(text);
   709                 [data->fieldEdit setString:@""];
   710             }
   711 #endif
   712         }
   713         break;
   714     case NSKeyUp:
   715         SDL_SendKeyboardKey(SDL_RELEASED, code);
   716         break;
   717     case NSFlagsChanged:
   718         /* FIXME CW 2007-08-14: check if this whole mess that takes up half of this file is really necessary */
   719         HandleModifiers(_this, scancode, [event modifierFlags]);
   720         break;
   721     default: /* just to avoid compiler warnings */
   722         break;
   723     }
   724 }
   725 
   726 void
   727 Cocoa_QuitKeyboard(_THIS)
   728 {
   729 }
   730 
   731 /* vi: set ts=4 sw=4 expandtab: */