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