Implemented Cocoa key event handling.
authorSam Lantinga <slouken@libsdl.org>
Sun, 30 Jul 2006 05:18:33 +0000
changeset 195925d6537feea4
parent 1958 5fc6fb0fb605
child 1960 118daa3a24cc
Implemented Cocoa key event handling.
src/events/SDL_keyboard.c
src/video/cocoa/SDL_cocoaevents.m
src/video/cocoa/SDL_cocoakeyboard.m
src/video/cocoa/SDL_cocoakeys.h
src/video/cocoa/SDL_cocoavideo.h
src/video/cocoa/SDL_cocoavideo.m
src/video/cocoa/SDL_cocoawindow.m
     1.1 --- a/src/events/SDL_keyboard.c	Sat Jul 29 23:00:15 2006 +0000
     1.2 +++ b/src/events/SDL_keyboard.c	Sun Jul 30 05:18:33 2006 +0000
     1.3 @@ -654,6 +654,7 @@
     1.4          event.key.keysym.mod = modstate;
     1.5          event.key.keysym.unicode = 0;
     1.6          event.key.windowID = keyboard->focus;
     1.7 +        /* FIXME: This doesn't make sense anymore... */
     1.8          /*
     1.9           * jk 991215 - Added
    1.10           */
    1.11 @@ -688,7 +689,7 @@
    1.12          event.text.type = SDL_TEXTINPUT;
    1.13          event.text.which = (Uint8) index;
    1.14          SDL_strlcpy(event.text.text, text, SDL_arraysize(event.text.text));
    1.15 -        event.key.windowID = keyboard->focus;
    1.16 +        event.text.windowID = keyboard->focus;
    1.17          posted = (SDL_PushEvent(&event) > 0);
    1.18      }
    1.19      return (posted);
     2.1 --- a/src/video/cocoa/SDL_cocoaevents.m	Sat Jul 29 23:00:15 2006 +0000
     2.2 +++ b/src/video/cocoa/SDL_cocoaevents.m	Sun Jul 30 05:18:33 2006 +0000
     2.3 @@ -89,9 +89,9 @@
     2.4      [appleMenu addItem:[NSMenuItem separatorItem]];
     2.5  
     2.6      title = [@"Hide " stringByAppendingString:appName];
     2.7 -    [appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"];
     2.8 +    [appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@/*"h"*/""];
     2.9  
    2.10 -    menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"];
    2.11 +    menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@/*"h"*/""];
    2.12      [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)];
    2.13  
    2.14      [appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""];
    2.15 @@ -99,7 +99,7 @@
    2.16      [appleMenu addItem:[NSMenuItem separatorItem]];
    2.17  
    2.18      title = [@"Quit " stringByAppendingString:appName];
    2.19 -    [appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"];
    2.20 +    [appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@/*"q"*/""];
    2.21      
    2.22      /* Put menu into the menubar */
    2.23      menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""];
    2.24 @@ -116,7 +116,7 @@
    2.25      windowMenu = [[NSMenu alloc] initWithTitle:@"Window"];
    2.26      
    2.27      /* "Minimize" item */
    2.28 -    menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"];
    2.29 +    menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@/*"m"*/""];
    2.30      [windowMenu addItem:menuItem];
    2.31      [menuItem release];
    2.32      
    2.33 @@ -169,7 +169,16 @@
    2.34          if ( event == nil ) {
    2.35              break;
    2.36          }
    2.37 -        [NSApp sendEvent:event];
    2.38 +        switch ([event type]) {
    2.39 +        case NSKeyDown:
    2.40 +        case NSKeyUp:
    2.41 +        case NSFlagsChanged:
    2.42 +            Cocoa_HandleKeyEvent(_this, event);
    2.43 +            /* Fall through to pass event to NSApp */
    2.44 +        default:
    2.45 +            [NSApp sendEvent:event];
    2.46 +            break;
    2.47 +        }
    2.48      }
    2.49      [pool release];
    2.50  }
     3.1 --- a/src/video/cocoa/SDL_cocoakeyboard.m	Sat Jul 29 23:00:15 2006 +0000
     3.2 +++ b/src/video/cocoa/SDL_cocoakeyboard.m	Sun Jul 30 05:18:33 2006 +0000
     3.3 @@ -22,20 +22,527 @@
     3.4  #include "SDL_config.h"
     3.5  
     3.6  #include "SDL_cocoavideo.h"
     3.7 +#include "SDL_cocoakeys.h"
     3.8  
     3.9  #include "../../events/SDL_keyboard_c.h"
    3.10  
    3.11 +
    3.12 +#ifndef NX_DEVICERCTLKEYMASK
    3.13 +    #define NX_DEVICELCTLKEYMASK    0x00000001
    3.14 +#endif
    3.15 +#ifndef NX_DEVICELSHIFTKEYMASK
    3.16 +    #define NX_DEVICELSHIFTKEYMASK  0x00000002
    3.17 +#endif
    3.18 +#ifndef NX_DEVICERSHIFTKEYMASK
    3.19 +    #define NX_DEVICERSHIFTKEYMASK  0x00000004
    3.20 +#endif
    3.21 +#ifndef NX_DEVICELCMDKEYMASK
    3.22 +    #define NX_DEVICELCMDKEYMASK    0x00000008
    3.23 +#endif
    3.24 +#ifndef NX_DEVICERCMDKEYMASK
    3.25 +    #define NX_DEVICERCMDKEYMASK    0x00000010
    3.26 +#endif
    3.27 +#ifndef NX_DEVICELALTKEYMASK
    3.28 +    #define NX_DEVICELALTKEYMASK    0x00000020
    3.29 +#endif
    3.30 +#ifndef NX_DEVICERALTKEYMASK
    3.31 +    #define NX_DEVICERALTKEYMASK    0x00000040
    3.32 +#endif
    3.33 +#ifndef NX_DEVICERCTLKEYMASK
    3.34 +    #define NX_DEVICERCTLKEYMASK    0x00002000
    3.35 +#endif
    3.36 +
    3.37 +static void
    3.38 +InitKeymap (SDLKey *keymap)
    3.39 +{
    3.40 +    const void *KCHRPtr;
    3.41 +    UInt32 state;
    3.42 +    UInt32 value;
    3.43 +    int i;
    3.44 +
    3.45 +    for ( i=0; i<256; ++i )
    3.46 +        keymap[i] = SDLK_UNKNOWN;
    3.47 +
    3.48 +    /* This keymap is almost exactly the same as the OS 9 one */
    3.49 +    keymap[KEY_ESCAPE] = SDLK_ESCAPE;
    3.50 +    keymap[KEY_F1] = SDLK_F1;
    3.51 +    keymap[KEY_F2] = SDLK_F2;
    3.52 +    keymap[KEY_F3] = SDLK_F3;
    3.53 +    keymap[KEY_F4] = SDLK_F4;
    3.54 +    keymap[KEY_F5] = SDLK_F5;
    3.55 +    keymap[KEY_F6] = SDLK_F6;
    3.56 +    keymap[KEY_F7] = SDLK_F7;
    3.57 +    keymap[KEY_F8] = SDLK_F8;
    3.58 +    keymap[KEY_F9] = SDLK_F9;
    3.59 +    keymap[KEY_F10] = SDLK_F10;
    3.60 +    keymap[KEY_F11] = SDLK_F11;
    3.61 +    keymap[KEY_F12] = SDLK_F12;
    3.62 +    keymap[KEY_PRINT] = SDLK_PRINT;
    3.63 +    keymap[KEY_SCROLLOCK] = SDLK_SCROLLOCK;
    3.64 +    keymap[KEY_PAUSE] = SDLK_PAUSE;
    3.65 +    keymap[KEY_POWER] = SDLK_POWER;
    3.66 +    keymap[KEY_BACKQUOTE] = SDLK_BACKQUOTE;
    3.67 +    keymap[KEY_1] = SDLK_1;
    3.68 +    keymap[KEY_2] = SDLK_2;
    3.69 +    keymap[KEY_3] = SDLK_3;
    3.70 +    keymap[KEY_4] = SDLK_4;
    3.71 +    keymap[KEY_5] = SDLK_5;
    3.72 +    keymap[KEY_6] = SDLK_6;
    3.73 +    keymap[KEY_7] = SDLK_7;
    3.74 +    keymap[KEY_8] = SDLK_8;
    3.75 +    keymap[KEY_9] = SDLK_9;
    3.76 +    keymap[KEY_0] = SDLK_0;
    3.77 +    keymap[KEY_MINUS] = SDLK_MINUS;
    3.78 +    keymap[KEY_EQUALS] = SDLK_EQUALS;
    3.79 +    keymap[KEY_BACKSPACE] = SDLK_BACKSPACE;
    3.80 +    keymap[KEY_INSERT] = SDLK_INSERT;
    3.81 +    keymap[KEY_HOME] = SDLK_HOME;
    3.82 +    keymap[KEY_PAGEUP] = SDLK_PAGEUP;
    3.83 +    keymap[KEY_NUMLOCK] = SDLK_NUMLOCK;
    3.84 +    keymap[KEY_KP_EQUALS] = SDLK_KP_EQUALS;
    3.85 +    keymap[KEY_KP_DIVIDE] = SDLK_KP_DIVIDE;
    3.86 +    keymap[KEY_KP_MULTIPLY] = SDLK_KP_MULTIPLY;
    3.87 +    keymap[KEY_TAB] = SDLK_TAB;
    3.88 +    keymap[KEY_q] = SDLK_q;
    3.89 +    keymap[KEY_w] = SDLK_w;
    3.90 +    keymap[KEY_e] = SDLK_e;
    3.91 +    keymap[KEY_r] = SDLK_r;
    3.92 +    keymap[KEY_t] = SDLK_t;
    3.93 +    keymap[KEY_y] = SDLK_y;
    3.94 +    keymap[KEY_u] = SDLK_u;
    3.95 +    keymap[KEY_i] = SDLK_i;
    3.96 +    keymap[KEY_o] = SDLK_o;
    3.97 +    keymap[KEY_p] = SDLK_p;
    3.98 +    keymap[KEY_LEFTBRACKET] = SDLK_LEFTBRACKET;
    3.99 +    keymap[KEY_RIGHTBRACKET] = SDLK_RIGHTBRACKET;
   3.100 +    keymap[KEY_BACKSLASH] = SDLK_BACKSLASH;
   3.101 +    keymap[KEY_DELETE] = SDLK_DELETE;
   3.102 +    keymap[KEY_END] = SDLK_END;
   3.103 +    keymap[KEY_PAGEDOWN] = SDLK_PAGEDOWN;
   3.104 +    keymap[KEY_KP7] = SDLK_KP7;
   3.105 +    keymap[KEY_KP8] = SDLK_KP8;
   3.106 +    keymap[KEY_KP9] = SDLK_KP9;
   3.107 +    keymap[KEY_KP_MINUS] = SDLK_KP_MINUS;
   3.108 +    keymap[KEY_CAPSLOCK] = SDLK_CAPSLOCK;
   3.109 +    keymap[KEY_a] = SDLK_a;
   3.110 +    keymap[KEY_s] = SDLK_s;
   3.111 +    keymap[KEY_d] = SDLK_d;
   3.112 +    keymap[KEY_f] = SDLK_f;
   3.113 +    keymap[KEY_g] = SDLK_g;
   3.114 +    keymap[KEY_h] = SDLK_h;
   3.115 +    keymap[KEY_j] = SDLK_j;
   3.116 +    keymap[KEY_k] = SDLK_k;
   3.117 +    keymap[KEY_l] = SDLK_l;
   3.118 +    keymap[KEY_SEMICOLON] = SDLK_SEMICOLON;
   3.119 +    keymap[KEY_QUOTE] = SDLK_QUOTE;
   3.120 +    keymap[KEY_RETURN] = SDLK_RETURN;
   3.121 +    keymap[KEY_KP4] = SDLK_KP4;
   3.122 +    keymap[KEY_KP5] = SDLK_KP5;
   3.123 +    keymap[KEY_KP6] = SDLK_KP6;
   3.124 +    keymap[KEY_KP_PLUS] = SDLK_KP_PLUS;
   3.125 +    keymap[KEY_LSHIFT] = SDLK_LSHIFT;
   3.126 +    keymap[KEY_RSHIFT] = SDLK_RSHIFT;
   3.127 +    keymap[KEY_z] = SDLK_z;
   3.128 +    keymap[KEY_x] = SDLK_x;
   3.129 +    keymap[KEY_c] = SDLK_c;
   3.130 +    keymap[KEY_v] = SDLK_v;
   3.131 +    keymap[KEY_b] = SDLK_b;
   3.132 +    keymap[KEY_n] = SDLK_n;
   3.133 +    keymap[KEY_m] = SDLK_m;
   3.134 +    keymap[KEY_COMMA] = SDLK_COMMA;
   3.135 +    keymap[KEY_PERIOD] = SDLK_PERIOD;
   3.136 +    keymap[KEY_SLASH] = SDLK_SLASH;
   3.137 +    keymap[KEY_UP] = SDLK_UP;
   3.138 +    keymap[KEY_KP1] = SDLK_KP1;
   3.139 +    keymap[KEY_KP2] = SDLK_KP2;
   3.140 +    keymap[KEY_KP3] = SDLK_KP3;
   3.141 +    keymap[KEY_KP_ENTER] = SDLK_KP_ENTER;
   3.142 +    keymap[KEY_LCTRL] = SDLK_LCTRL;
   3.143 +    keymap[KEY_LALT] = SDLK_LALT;
   3.144 +    keymap[KEY_LMETA] = SDLK_LMETA;
   3.145 +    keymap[KEY_RCTRL] = SDLK_RCTRL;
   3.146 +    keymap[KEY_RALT] = SDLK_RALT;
   3.147 +    keymap[KEY_RMETA] = SDLK_RMETA;
   3.148 +    keymap[KEY_SPACE] = SDLK_SPACE;
   3.149 +    keymap[KEY_LEFT] = SDLK_LEFT;
   3.150 +    keymap[KEY_DOWN] = SDLK_DOWN;
   3.151 +    keymap[KEY_RIGHT] = SDLK_RIGHT;
   3.152 +    keymap[KEY_KP0] = SDLK_KP0;
   3.153 +    keymap[KEY_KP_PERIOD] = SDLK_KP_PERIOD;
   3.154 +    keymap[KEY_IBOOK_ENTER] = SDLK_KP_ENTER;
   3.155 +    keymap[KEY_IBOOK_RIGHT] = SDLK_RIGHT;
   3.156 +    keymap[KEY_IBOOK_DOWN] = SDLK_DOWN;
   3.157 +    keymap[KEY_IBOOK_UP]      = SDLK_UP;
   3.158 +    keymap[KEY_IBOOK_LEFT] = SDLK_LEFT;
   3.159 +
   3.160 +    /* 
   3.161 +        Up there we setup a static scancode->keysym map. However, it will not
   3.162 +        work very well on international keyboard. Hence we now query Mac OS X
   3.163 +        for its own keymap to adjust our own mapping table. However, this is
   3.164 +        basically only useful for ascii char keys. This is also the reason
   3.165 +        why we keep the static table, too.
   3.166 +     */
   3.167 +
   3.168 +    /* Get a pointer to the systems cached KCHR */
   3.169 +    KCHRPtr = (void *)GetScriptManagerVariable(smKCHRCache);
   3.170 +    if (KCHRPtr) {
   3.171 +        /* Loop over all 127 possible scan codes */
   3.172 +        for (i = 0; i < 0x7F; i++) {
   3.173 +            /* We pretend a clean start to begin with (i.e. no dead keys active */
   3.174 +            state = 0;
   3.175 +
   3.176 +            /* Now translate the key code to a key value */
   3.177 +            value = KeyTranslate(KCHRPtr, i, &state) & 0xff;
   3.178 +
   3.179 +            /* If the state become 0, it was a dead key. We need to translate again,
   3.180 +                passing in the new state, to get the actual key value */
   3.181 +            if (state != 0)
   3.182 +                value = KeyTranslate(KCHRPtr, i, &state) & 0xff;
   3.183 +
   3.184 +            /* Now we should have a latin1 value, which are SDL keysyms */
   3.185 +            if (value >= 32 && value <= 255) {
   3.186 +                keymap[i] = value;
   3.187 +            }
   3.188 +        }
   3.189 +    }
   3.190 +
   3.191 +    /* 
   3.192 +        The keypad codes are re-setup here, because the loop above cannot
   3.193 +        distinguish between a key on the keypad and a regular key. We maybe
   3.194 +        could get around this problem in another fashion: NSEvent's flags
   3.195 +        include a "NSNumericPadKeyMask" bit; we could check that and modify
   3.196 +        the symbol we return on the fly. However, this flag seems to exhibit
   3.197 +        some weird behaviour related to the num lock key
   3.198 +    */
   3.199 +    keymap[KEY_KP0] = SDLK_KP0;
   3.200 +    keymap[KEY_KP1] = SDLK_KP1;
   3.201 +    keymap[KEY_KP2] = SDLK_KP2;
   3.202 +    keymap[KEY_KP3] = SDLK_KP3;
   3.203 +    keymap[KEY_KP4] = SDLK_KP4;
   3.204 +    keymap[KEY_KP5] = SDLK_KP5;
   3.205 +    keymap[KEY_KP6] = SDLK_KP6;
   3.206 +    keymap[KEY_KP7] = SDLK_KP7;
   3.207 +    keymap[KEY_KP8] = SDLK_KP8;
   3.208 +    keymap[KEY_KP9] = SDLK_KP9;
   3.209 +    keymap[KEY_KP_MINUS] = SDLK_KP_MINUS;
   3.210 +    keymap[KEY_KP_PLUS] = SDLK_KP_PLUS;
   3.211 +    keymap[KEY_KP_PERIOD] = SDLK_KP_PERIOD;
   3.212 +    keymap[KEY_KP_EQUALS] = SDLK_KP_EQUALS;
   3.213 +    keymap[KEY_KP_DIVIDE] = SDLK_KP_DIVIDE;
   3.214 +    keymap[KEY_KP_MULTIPLY] = SDLK_KP_MULTIPLY;
   3.215 +    keymap[KEY_KP_ENTER] = SDLK_KP_ENTER;
   3.216 +}
   3.217 +
   3.218 +/* This is the original behavior, before support was added for 
   3.219 + * differentiating between left and right versions of the keys.
   3.220 + */
   3.221 +static void
   3.222 +DoUnsidedModifiers(int keyboard, unsigned short scancode,
   3.223 +                   unsigned int oldMods, unsigned int newMods)
   3.224 +{
   3.225 +    const int mapping[] = { SDLK_CAPSLOCK, SDLK_LSHIFT, SDLK_LCTRL, SDLK_LALT, SDLK_LMETA };
   3.226 +    unsigned int i, bit;
   3.227 +
   3.228 +    /* Iterate through the bits, testing each against the current modifiers */
   3.229 +    for (i = 0, bit = NSAlphaShiftKeyMask; bit <= NSCommandKeyMask; bit <<= 1, ++i) {
   3.230 +        unsigned int oldMask, newMask;
   3.231 +
   3.232 +        oldMask = oldMods & bit;
   3.233 +        newMask = newMods & bit;
   3.234 +
   3.235 +        if (oldMask && oldMask != newMask) {        /* modifier up event */
   3.236 +            /* If this was Caps Lock, we need some additional voodoo to make SDL happy */
   3.237 +            if (bit == NSAlphaShiftKeyMask) {
   3.238 +                SDL_SendKeyboardKey(keyboard, SDL_PRESSED, (Uint8)scancode, mapping[i]);
   3.239 +            }
   3.240 +            SDL_SendKeyboardKey(keyboard, SDL_RELEASED, (Uint8)scancode, mapping[i]);
   3.241 +        } else if (newMask && oldMask != newMask) { /* modifier down event */
   3.242 +            SDL_SendKeyboardKey(keyboard, SDL_PRESSED, (Uint8)scancode, mapping[i]);
   3.243 +            /* If this was Caps Lock, we need some additional voodoo to make SDL happy */
   3.244 +            if (bit == NSAlphaShiftKeyMask) {
   3.245 +                SDL_SendKeyboardKey(keyboard, SDL_RELEASED, (Uint8)scancode, mapping[i]);
   3.246 +            }
   3.247 +        }
   3.248 +    }
   3.249 +}
   3.250 +
   3.251 +/* This is a helper function for HandleModifierSide. This 
   3.252 + * function reverts back to behavior before the distinction between
   3.253 + * sides was made.
   3.254 + */
   3.255 +static void
   3.256 +HandleNonDeviceModifier(int keyboard, unsigned short scancode,
   3.257 +                        unsigned int device_independent_mask,
   3.258 +                        unsigned int oldMods,
   3.259 +                        unsigned int newMods,
   3.260 +                        SDLKey key_sym)
   3.261 +{
   3.262 +    unsigned int oldMask, newMask;
   3.263 +    
   3.264 +    /* Isolate just the bits we care about in the depedent bits so we can 
   3.265 +     * figure out what changed
   3.266 +     */ 
   3.267 +    oldMask = oldMods & device_independent_mask;
   3.268 +    newMask = newMods & device_independent_mask;
   3.269 +    
   3.270 +    if (oldMask && oldMask != newMask) {
   3.271 +        SDL_SendKeyboardKey(keyboard, SDL_RELEASED, (Uint8)scancode, key_sym);
   3.272 +    } else if (newMask && oldMask != newMask) {
   3.273 +        SDL_SendKeyboardKey(keyboard, SDL_PRESSED, (Uint8)scancode, key_sym);
   3.274 +    }
   3.275 +}
   3.276 +
   3.277 +/* This is a helper function for HandleModifierSide. 
   3.278 + * This function sets the actual SDL_PrivateKeyboard event.
   3.279 + */
   3.280 +static void
   3.281 +HandleModifierOneSide(int keyboard, unsigned short scancode,
   3.282 +                      unsigned int oldMods, unsigned int newMods,
   3.283 +                      SDLKey key_sym, 
   3.284 +                      unsigned int sided_device_dependent_mask)
   3.285 +{
   3.286 +    unsigned int old_dep_mask, new_dep_mask;
   3.287 +
   3.288 +    /* Isolate just the bits we care about in the depedent bits so we can 
   3.289 +     * figure out what changed
   3.290 +     */ 
   3.291 +    old_dep_mask = oldMods & sided_device_dependent_mask;
   3.292 +    new_dep_mask = newMods & sided_device_dependent_mask;
   3.293 +
   3.294 +    /* We now know that this side bit flipped. But we don't know if
   3.295 +     * it went pressed to released or released to pressed, so we must 
   3.296 +     * find out which it is.
   3.297 +     */
   3.298 +    if (new_dep_mask && old_dep_mask != new_dep_mask) {
   3.299 +        SDL_SendKeyboardKey(keyboard, SDL_PRESSED, (Uint8)scancode, key_sym);
   3.300 +    } else {
   3.301 +        SDL_SendKeyboardKey(keyboard, SDL_RELEASED, (Uint8)scancode, key_sym);
   3.302 +    }
   3.303 +}
   3.304 +
   3.305 +/* This is a helper function for DoSidedModifiers.
   3.306 + * This function will figure out if the modifier key is the left or right side, 
   3.307 + * e.g. left-shift vs right-shift. 
   3.308 + */
   3.309 +static void
   3.310 +HandleModifierSide(int keyboard, unsigned short scancode,
   3.311 +                   int device_independent_mask, 
   3.312 +                   unsigned int oldMods, unsigned int newMods, 
   3.313 +                   SDLKey left_key_sym, 
   3.314 +                   SDLKey right_key_sym,
   3.315 +                   unsigned int left_device_dependent_mask, 
   3.316 +                   unsigned int right_device_dependent_mask)
   3.317 +{
   3.318 +    unsigned int device_dependent_mask = (left_device_dependent_mask |
   3.319 +                                         right_device_dependent_mask);
   3.320 +    unsigned int diff_mod;
   3.321 +    
   3.322 +    /* On the basis that the device independent mask is set, but there are 
   3.323 +     * no device dependent flags set, we'll assume that we can't detect this 
   3.324 +     * keyboard and revert to the unsided behavior.
   3.325 +     */
   3.326 +    if ((device_dependent_mask & newMods) == 0) {
   3.327 +        /* Revert to the old behavior */
   3.328 +        HandleNonDeviceModifier(keyboard, scancode, device_independent_mask, oldMods, newMods, left_key_sym);
   3.329 +        return;
   3.330 +    }
   3.331 +
   3.332 +    /* XOR the previous state against the new state to see if there's a change */
   3.333 +    diff_mod = (device_dependent_mask & oldMods) ^
   3.334 +               (device_dependent_mask & newMods);
   3.335 +    if (diff_mod) {
   3.336 +        /* A change in state was found. Isolate the left and right bits 
   3.337 +         * to handle them separately just in case the values can simulataneously
   3.338 +         * change or if the bits don't both exist.
   3.339 +         */
   3.340 +        if (left_device_dependent_mask & diff_mod) {
   3.341 +            HandleModifierOneSide(keyboard, scancode, oldMods, newMods, left_key_sym, left_device_dependent_mask);
   3.342 +        }
   3.343 +        if (right_device_dependent_mask & diff_mod) {
   3.344 +            HandleModifierOneSide(keyboard, scancode, oldMods, newMods, right_key_sym, right_device_dependent_mask);
   3.345 +        }
   3.346 +    }
   3.347 +}
   3.348 +   
   3.349 +/* This is a helper function for DoSidedModifiers.
   3.350 + * This function will release a key press in the case that 
   3.351 + * it is clear that the modifier has been released (i.e. one side 
   3.352 + * can't still be down).
   3.353 + */
   3.354 +static void
   3.355 +ReleaseModifierSide(int keyboard, unsigned short scancode,
   3.356 +                    unsigned int device_independent_mask, 
   3.357 +                    unsigned int oldMods, unsigned int newMods,
   3.358 +                    SDLKey left_key_sym, 
   3.359 +                    SDLKey right_key_sym,
   3.360 +                    unsigned int left_device_dependent_mask, 
   3.361 +                    unsigned int right_device_dependent_mask)
   3.362 +{
   3.363 +    unsigned int device_dependent_mask = (left_device_dependent_mask |
   3.364 +                                          right_device_dependent_mask);
   3.365 +
   3.366 +    /* On the basis that the device independent mask is set, but there are 
   3.367 +     * no device dependent flags set, we'll assume that we can't detect this 
   3.368 +     * keyboard and revert to the unsided behavior.
   3.369 +     */
   3.370 +    if ((device_dependent_mask & oldMods) == 0) {
   3.371 +        /* In this case, we can't detect the keyboard, so use the left side 
   3.372 +         * to represent both, and release it. 
   3.373 +         */
   3.374 +        SDL_SendKeyboardKey(keyboard, SDL_RELEASED, (Uint8)scancode, left_key_sym);
   3.375 +        return;
   3.376 +    }
   3.377 +
   3.378 +    /* 
   3.379 +     * This could have been done in an if-else case because at this point,
   3.380 +     * we know that all keys have been released when calling this function. 
   3.381 +     * But I'm being paranoid so I want to handle each separately,
   3.382 +     * so I hope this doesn't cause other problems.
   3.383 +     */
   3.384 +    if ( left_device_dependent_mask & oldMods ) {
   3.385 +        SDL_SendKeyboardKey(keyboard, SDL_RELEASED, (Uint8)scancode, left_key_sym);
   3.386 +    }
   3.387 +    if ( right_device_dependent_mask & oldMods ) {
   3.388 +        SDL_SendKeyboardKey(keyboard, SDL_RELEASED, (Uint8)scancode, right_key_sym);
   3.389 +    }
   3.390 +}
   3.391 +
   3.392 +/* This is a helper function for DoSidedModifiers.
   3.393 + * This function handles the CapsLock case.
   3.394 + */
   3.395 +static void
   3.396 +HandleCapsLock(int keyboard, unsigned short scancode,
   3.397 +               unsigned int oldMods, unsigned int newMods)
   3.398 +{
   3.399 +    unsigned int oldMask, newMask;
   3.400 +    
   3.401 +    oldMask = oldMods & NSAlphaShiftKeyMask;
   3.402 +    newMask = newMods & NSAlphaShiftKeyMask;
   3.403 +
   3.404 +    if (oldMask != newMask) {
   3.405 +        SDL_SendKeyboardKey(keyboard, SDL_PRESSED, (Uint8)scancode, SDLK_CAPSLOCK);
   3.406 +        SDL_SendKeyboardKey(keyboard, SDL_RELEASED, (Uint8)scancode, SDLK_CAPSLOCK);
   3.407 +    }
   3.408 +}
   3.409 +
   3.410 +/* This function will handle the modifier keys and also determine the 
   3.411 + * correct side of the key.
   3.412 + */
   3.413 +static void
   3.414 +DoSidedModifiers(int keyboard, unsigned short scancode,
   3.415 +                 unsigned int oldMods, unsigned int newMods)
   3.416 +{
   3.417 +	/* Set up arrays for the key syms for the left and right side. */
   3.418 +    const SDLKey left_mapping[]  = { SDLK_LSHIFT, SDLK_LCTRL, SDLK_LALT, SDLK_LMETA };
   3.419 +    const SDLKey right_mapping[] = { SDLK_RSHIFT, SDLK_RCTRL, SDLK_RALT, SDLK_RMETA };
   3.420 +	/* Set up arrays for the device dependent masks with indices that 
   3.421 +     * correspond to the _mapping arrays 
   3.422 +     */
   3.423 +    const unsigned int left_device_mapping[]  = { NX_DEVICELSHIFTKEYMASK, NX_DEVICELCTLKEYMASK, NX_DEVICELALTKEYMASK, NX_DEVICELCMDKEYMASK };
   3.424 +    const unsigned int right_device_mapping[] = { NX_DEVICERSHIFTKEYMASK, NX_DEVICERCTLKEYMASK, NX_DEVICERALTKEYMASK, NX_DEVICERCMDKEYMASK };
   3.425 +
   3.426 +    unsigned int i, bit;
   3.427 +
   3.428 +    /* Handle CAPSLOCK separately because it doesn't have a left/right side */
   3.429 +    HandleCapsLock(keyboard, scancode, oldMods, newMods);
   3.430 +
   3.431 +    /* Iterate through the bits, testing each against the old modifiers */
   3.432 +    for (i = 0, bit = NSShiftKeyMask; bit <= NSCommandKeyMask; bit <<= 1, ++i) {
   3.433 +        unsigned int oldMask, newMask;
   3.434 +		
   3.435 +        oldMask = oldMods & bit;
   3.436 +        newMask = newMods & bit;
   3.437 +		
   3.438 +        /* If the bit is set, we must always examine it because the left
   3.439 +         * and right side keys may alternate or both may be pressed.
   3.440 +         */
   3.441 +        if (newMask) {
   3.442 +            HandleModifierSide(keyboard, scancode, bit, oldMods, newMods,
   3.443 +                               left_mapping[i], right_mapping[i],
   3.444 +                               left_device_mapping[i], right_device_mapping[i]);
   3.445 +        }
   3.446 +        /* If the state changed from pressed to unpressed, we must examine
   3.447 +            * the device dependent bits to release the correct keys.
   3.448 +            */
   3.449 +        else if (oldMask && oldMask != newMask) {
   3.450 +            ReleaseModifierSide(keyboard, scancode, bit, oldMods, newMods,
   3.451 +                              left_mapping[i], right_mapping[i],
   3.452 +                              left_device_mapping[i], right_device_mapping[i]);
   3.453 +        }
   3.454 +    }
   3.455 +}
   3.456 +
   3.457 +static void
   3.458 +HandleModifiers(_THIS, unsigned short scancode, unsigned int modifierFlags)
   3.459 +{
   3.460 +    SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
   3.461 +
   3.462 +    if (modifierFlags == data->modifierFlags) {
   3.463 +    	return;
   3.464 +    }
   3.465 +
   3.466 +    /* 
   3.467 +     * Starting with Panther (10.3.0), the ability to distinguish between 
   3.468 +     * left side and right side modifiers is available.
   3.469 +     */
   3.470 +    if (data->osversion >= 0x1030) {
   3.471 +        DoSidedModifiers(data->keyboard, scancode, data->modifierFlags, modifierFlags);
   3.472 +    } else {
   3.473 +        DoUnsidedModifiers(data->keyboard, scancode, data->modifierFlags, modifierFlags);
   3.474 +    }
   3.475 +    data->modifierFlags = modifierFlags;
   3.476 +}
   3.477 +
   3.478  void
   3.479  Cocoa_InitKeyboard(_THIS)
   3.480  {
   3.481      SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
   3.482      SDL_Keyboard keyboard;
   3.483  
   3.484 +    InitKeymap(data->keymap);
   3.485 +
   3.486      SDL_zero(keyboard);
   3.487      data->keyboard = SDL_AddKeyboard(&keyboard, -1);
   3.488  }
   3.489  
   3.490  void
   3.491 +Cocoa_HandleKeyEvent(_THIS, NSEvent *event)
   3.492 +{
   3.493 +    SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
   3.494 +    unsigned short scancode = [event keyCode];
   3.495 +    const char *text;
   3.496 +
   3.497 +    if (scancode >= 256) {
   3.498 +        /* Hmm, does this ever happen?  If so, need to extend the keymap... */
   3.499 +        return;
   3.500 +    }
   3.501 +
   3.502 +    switch ([event type]) {
   3.503 +    case NSKeyDown:
   3.504 +        if ([event isARepeat]) {
   3.505 +            break;
   3.506 +        }
   3.507 +printf("NSKeyDown: %x, %x\n", scancode, [event modifierFlags]);
   3.508 +        SDL_SendKeyboardKey(data->keyboard, SDL_PRESSED, (Uint8)scancode,
   3.509 +                            data->keymap[scancode]);
   3.510 +        text = [[event characters] UTF8String];
   3.511 +        if(text && *text) {
   3.512 +            SDL_SendKeyboardText(data->keyboard, text);
   3.513 +        }
   3.514 +        break;
   3.515 +    case NSKeyUp:
   3.516 +printf("NSKeyUp: %x, %x\n", scancode, [event modifierFlags]);
   3.517 +        SDL_SendKeyboardKey(data->keyboard, SDL_RELEASED, (Uint8)scancode,
   3.518 +                            data->keymap[scancode]);
   3.519 +        break;
   3.520 +    case NSFlagsChanged:
   3.521 +printf("NSFlagsChanged: %x, %x\n", scancode, [event modifierFlags]);
   3.522 +        HandleModifiers(_this, scancode, [event modifierFlags]);
   3.523 +        break;
   3.524 +    }
   3.525 +}
   3.526 +
   3.527 +void
   3.528  Cocoa_QuitKeyboard(_THIS)
   3.529  {
   3.530      SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/src/video/cocoa/SDL_cocoakeys.h	Sun Jul 30 05:18:33 2006 +0000
     4.3 @@ -0,0 +1,141 @@
     4.4 +/*
     4.5 +    SDL - Simple DirectMedia Layer
     4.6 +    Copyright (C) 1997-2006 Sam Lantinga
     4.7 +
     4.8 +    This library is free software; you can redistribute it and/or
     4.9 +    modify it under the terms of the GNU Lesser General Public
    4.10 +    License as published by the Free Software Foundation; either
    4.11 +    version 2.1 of the License, or (at your option) any later version.
    4.12 +
    4.13 +    This library is distributed in the hope that it will be useful,
    4.14 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
    4.15 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    4.16 +    Lesser General Public License for more details.
    4.17 +
    4.18 +    You should have received a copy of the GNU Lesser General Public
    4.19 +    License along with this library; if not, write to the Free Software
    4.20 +    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    4.21 +
    4.22 +    Sam Lantinga
    4.23 +    slouken@libsdl.org
    4.24 +*/
    4.25 +#include "SDL_config.h"
    4.26 +
    4.27 +/* These are the Macintosh key scancode constants -- from Inside Macintosh */
    4.28 +
    4.29 +#define KEY_ESCAPE		0x35
    4.30 +#define KEY_F1			0x7A
    4.31 +#define KEY_F2			0x78
    4.32 +#define KEY_F3			0x63
    4.33 +#define KEY_F4			0x76
    4.34 +#define KEY_F5			0x60
    4.35 +#define KEY_F6			0x61
    4.36 +#define KEY_F7			0x62
    4.37 +#define KEY_F8			0x64
    4.38 +#define KEY_F9			0x65
    4.39 +#define KEY_F10			0x6D
    4.40 +#define KEY_F11			0x67
    4.41 +#define KEY_F12			0x6F
    4.42 +#define KEY_PRINT		0x69
    4.43 +#define KEY_SCROLLOCK    0x6B
    4.44 +#define KEY_PAUSE		0x71
    4.45 +#define KEY_POWER		0x7F
    4.46 +#define KEY_BACKQUOTE	0x32
    4.47 +#define KEY_1			0x12
    4.48 +#define KEY_2			0x13
    4.49 +#define KEY_3			0x14
    4.50 +#define KEY_4			0x15
    4.51 +#define KEY_5			0x17
    4.52 +#define KEY_6			0x16
    4.53 +#define KEY_7			0x1A
    4.54 +#define KEY_8			0x1C
    4.55 +#define KEY_9			0x19
    4.56 +#define KEY_0			0x1D
    4.57 +#define KEY_MINUS		0x1B
    4.58 +#define KEY_EQUALS		0x18
    4.59 +#define KEY_BACKSPACE	0x33
    4.60 +#define KEY_INSERT		0x72
    4.61 +#define KEY_HOME			0x73
    4.62 +#define KEY_PAGEUP		0x74
    4.63 +#define KEY_NUMLOCK		0x47
    4.64 +#define KEY_KP_EQUALS	0x51
    4.65 +#define KEY_KP_DIVIDE	0x4B
    4.66 +#define KEY_KP_MULTIPLY	0x43
    4.67 +#define KEY_TAB			0x30
    4.68 +#define KEY_q			0x0C
    4.69 +#define KEY_w			0x0D
    4.70 +#define KEY_e			0x0E
    4.71 +#define KEY_r			0x0F
    4.72 +#define KEY_t			0x11
    4.73 +#define KEY_y			0x10
    4.74 +#define KEY_u			0x20
    4.75 +#define KEY_i			0x22
    4.76 +#define KEY_o			0x1F
    4.77 +#define KEY_p			0x23
    4.78 +#define KEY_LEFTBRACKET	0x21
    4.79 +#define KEY_RIGHTBRACKET	0x1E
    4.80 +#define KEY_BACKSLASH	0x2A
    4.81 +#define KEY_DELETE		0x75
    4.82 +#define KEY_END			0x77
    4.83 +#define KEY_PAGEDOWN		0x79
    4.84 +#define KEY_KP7			0x59
    4.85 +#define KEY_KP8			0x5B
    4.86 +#define KEY_KP9			0x5C
    4.87 +#define KEY_KP_MINUS		0x4E
    4.88 +#define KEY_CAPSLOCK		0x39
    4.89 +#define KEY_a			0x00
    4.90 +#define KEY_s			0x01
    4.91 +#define KEY_d			0x02
    4.92 +#define KEY_f			0x03
    4.93 +#define KEY_g			0x05
    4.94 +#define KEY_h			0x04
    4.95 +#define KEY_j			0x26
    4.96 +#define KEY_k			0x28
    4.97 +#define KEY_l			0x25
    4.98 +#define KEY_SEMICOLON	0x29
    4.99 +#define KEY_QUOTE		0x27
   4.100 +#define KEY_RETURN		0x24
   4.101 +#define KEY_KP4			0x56
   4.102 +#define KEY_KP5			0x57
   4.103 +#define KEY_KP6			0x58
   4.104 +#define KEY_KP_PLUS		0x45
   4.105 +#define KEY_LSHIFT		0x38
   4.106 +#define KEY_z			0x06
   4.107 +#define KEY_x			0x07
   4.108 +#define KEY_c			0x08
   4.109 +#define KEY_v			0x09
   4.110 +#define KEY_b			0x0B
   4.111 +#define KEY_n			0x2D
   4.112 +#define KEY_m			0x2E
   4.113 +#define KEY_COMMA		0x2B
   4.114 +#define KEY_PERIOD		0x2F
   4.115 +#define KEY_SLASH		0x2C
   4.116 +#if 1                           /* Panther now defines right side keys */
   4.117 +#define KEY_RSHIFT		0x3C
   4.118 +#endif
   4.119 +#define KEY_UP			0x7E
   4.120 +#define KEY_KP1			0x53
   4.121 +#define KEY_KP2			0x54
   4.122 +#define KEY_KP3			0x55
   4.123 +#define KEY_KP_ENTER		0x4C
   4.124 +#define KEY_LCTRL		0x3B
   4.125 +#define KEY_LALT			0x3A
   4.126 +#define KEY_LMETA		0x37
   4.127 +#define KEY_SPACE		0x31
   4.128 +#if 1                           /* Panther now defines right side keys */
   4.129 +#define KEY_RMETA		0x36
   4.130 +#define KEY_RALT			0x3D
   4.131 +#define KEY_RCTRL		0x3E
   4.132 +#endif
   4.133 +#define KEY_LEFT			0x7B
   4.134 +#define KEY_DOWN			0x7D
   4.135 +#define KEY_RIGHT		0x7C
   4.136 +#define KEY_KP0			0x52
   4.137 +#define KEY_KP_PERIOD	0x41
   4.138 +
   4.139 +/* Wierd, these keys are on my iBook under Mac OS X */
   4.140 +#define KEY_IBOOK_ENTER		0x34
   4.141 +#define KEY_IBOOK_LEFT		0x3B
   4.142 +#define KEY_IBOOK_RIGHT		0x3C
   4.143 +#define KEY_IBOOK_DOWN		0x3D
   4.144 +#define KEY_IBOOK_UP			0x3E
     5.1 --- a/src/video/cocoa/SDL_cocoavideo.h	Sat Jul 29 23:00:15 2006 +0000
     5.2 +++ b/src/video/cocoa/SDL_cocoavideo.h	Sun Jul 30 05:18:33 2006 +0000
     5.3 @@ -27,6 +27,7 @@
     5.4  #include <ApplicationServices/ApplicationServices.h>
     5.5  #include <Cocoa/Cocoa.h>
     5.6  
     5.7 +#include "SDL_keysym.h"
     5.8  #include "../SDL_sysvideo.h"
     5.9  
    5.10  #include "SDL_cocoaevents.h"
    5.11 @@ -40,6 +41,9 @@
    5.12  
    5.13  typedef struct SDL_VideoData
    5.14  {
    5.15 +    SInt32 osversion;
    5.16 +    SDLKey keymap[256];
    5.17 +    unsigned int modifierFlags;
    5.18      int mouse;
    5.19      int keyboard;
    5.20  } SDL_VideoData;
     6.1 --- a/src/video/cocoa/SDL_cocoavideo.m	Sat Jul 29 23:00:15 2006 +0000
     6.2 +++ b/src/video/cocoa/SDL_cocoavideo.m	Sun Jul 30 05:18:33 2006 +0000
     6.3 @@ -66,6 +66,9 @@
     6.4      }
     6.5      device->driverdata = data;
     6.6  
     6.7 +    /* Find out what version of Mac OS X we're running */
     6.8 +    Gestalt(gestaltSystemVersion, &data->osversion);
     6.9 +
    6.10      /* Set the function pointers */
    6.11      device->VideoInit = Cocoa_VideoInit;
    6.12      device->VideoQuit = Cocoa_VideoQuit;
     7.1 --- a/src/video/cocoa/SDL_cocoawindow.m	Sat Jul 29 23:00:15 2006 +0000
     7.2 +++ b/src/video/cocoa/SDL_cocoawindow.m	Sun Jul 30 05:18:33 2006 +0000
     7.3 @@ -148,49 +148,67 @@
     7.4  - (void)mouseDown:(NSEvent *)theEvent
     7.5  {
     7.6      int index;
     7.7 +    int button;
     7.8  
     7.9      index = _data->videodata->mouse;
    7.10 -    SDL_SendMouseButton(index, SDL_PRESSED, SDL_BUTTON_LEFT);
    7.11 +    switch ([theEvent buttonNumber]) {
    7.12 +    case 0:
    7.13 +        button = SDL_BUTTON_LEFT;
    7.14 +        break;
    7.15 +    case 1:
    7.16 +        button = SDL_BUTTON_RIGHT;
    7.17 +        break;
    7.18 +    case 2:
    7.19 +        button = SDL_BUTTON_MIDDLE;
    7.20 +        break;
    7.21 +    default:
    7.22 +        button = [theEvent buttonNumber];
    7.23 +        break;
    7.24 +    }
    7.25 +    SDL_SendMouseButton(index, SDL_PRESSED, button);
    7.26  }
    7.27  
    7.28  - (void)rightMouseDown:(NSEvent *)theEvent
    7.29  {
    7.30 -    int index;
    7.31 -
    7.32 -    index = _data->videodata->mouse;
    7.33 -    SDL_SendMouseButton(index, SDL_PRESSED, SDL_BUTTON_RIGHT);
    7.34 +    [self mouseDown:theEvent];
    7.35  }
    7.36  
    7.37  - (void)otherMouseDown:(NSEvent *)theEvent
    7.38  {
    7.39 -    int index;
    7.40 -
    7.41 -    index = _data->videodata->mouse;
    7.42 -    SDL_SendMouseButton(index, SDL_PRESSED, SDL_BUTTON_MIDDLE);
    7.43 +    [self mouseDown:theEvent];
    7.44  }
    7.45  
    7.46  - (void)mouseUp:(NSEvent *)theEvent
    7.47  {
    7.48      int index;
    7.49 +    int button;
    7.50  
    7.51      index = _data->videodata->mouse;
    7.52 -    SDL_SendMouseButton(index, SDL_RELEASED, SDL_BUTTON_LEFT);
    7.53 +    switch ([theEvent buttonNumber]) {
    7.54 +    case 0:
    7.55 +        button = SDL_BUTTON_LEFT;
    7.56 +        break;
    7.57 +    case 1:
    7.58 +        button = SDL_BUTTON_RIGHT;
    7.59 +        break;
    7.60 +    case 2:
    7.61 +        button = SDL_BUTTON_MIDDLE;
    7.62 +        break;
    7.63 +    default:
    7.64 +        button = [theEvent buttonNumber];
    7.65 +        break;
    7.66 +    }
    7.67 +    SDL_SendMouseButton(index, SDL_RELEASED, button);
    7.68  }
    7.69  
    7.70  - (void)rightMouseUp:(NSEvent *)theEvent
    7.71  {
    7.72 -    int index;
    7.73 -
    7.74 -    index = _data->videodata->mouse;
    7.75 -    SDL_SendMouseButton(index, SDL_RELEASED, SDL_BUTTON_RIGHT);
    7.76 +    [self mouseUp:theEvent];
    7.77  }
    7.78  
    7.79  - (void)otherMouseUp:(NSEvent *)theEvent
    7.80  {
    7.81 -    int index;
    7.82 -
    7.83 -    index = _data->videodata->mouse;
    7.84 -    SDL_SendMouseButton(index, SDL_RELEASED, SDL_BUTTON_MIDDLE);
    7.85 +    [self mouseUp:theEvent];
    7.86  }
    7.87  
    7.88  - (void)mouseMoved:(NSEvent *)theEvent
    7.89 @@ -238,11 +256,21 @@
    7.90  
    7.91  - (void)keyDown:(NSEvent *)theEvent
    7.92  {
    7.93 +    int index;
    7.94 +
    7.95 +    index = _data->videodata->keyboard;
    7.96  fprintf(stderr, "keyDown\n");
    7.97 +    const char *text = [[theEvent characters] UTF8String];
    7.98 +    if(text && *text) {
    7.99 +        SDL_SendKeyboardText(index, text);
   7.100 +    }
   7.101  }
   7.102  
   7.103  - (void)keyUp:(NSEvent *)theEvent
   7.104  {
   7.105 +    int index;
   7.106 +
   7.107 +    index = _data->videodata->keyboard;
   7.108  fprintf(stderr, "keyUp\n");
   7.109  }
   7.110