src/video/quartz/SDL_QuartzEvents.m
changeset 1895 c121d94672cb
parent 1876 406b8325ee34
equal deleted inserted replaced
1894:c69cee13dd76 1895:c121d94672cb
    21 */
    21 */
    22 #include "SDL_config.h"
    22 #include "SDL_config.h"
    23 
    23 
    24 #include "SDL_QuartzVideo.h"
    24 #include "SDL_QuartzVideo.h"
    25 
    25 
    26 #include <IOKit/IOMessage.h> /* For wake from sleep detection */
    26 #include <IOKit/IOMessage.h>    /* For wake from sleep detection */
    27 #include <IOKit/pwr_mgt/IOPMLib.h> /* For wake from sleep detection */
    27 #include <IOKit/pwr_mgt/IOPMLib.h>      /* For wake from sleep detection */
    28 #include "SDL_QuartzKeys.h"
    28 #include "SDL_QuartzKeys.h"
    29 
    29 
    30 /* 
    30 /* 
    31  * In Panther, this header defines device dependent masks for 
    31  * In Panther, this header defines device dependent masks for 
    32  * right side keys. These definitions only exist in Panther, but
    32  * right side keys. These definitions only exist in Panther, but
    37 /* 
    37 /* 
    38  * These are not defined before Panther. To keep the code compiling
    38  * These are not defined before Panther. To keep the code compiling
    39  * on systems without these, I will define if they don't exist.
    39  * on systems without these, I will define if they don't exist.
    40  */
    40  */
    41 #ifndef NX_DEVICERCTLKEYMASK
    41 #ifndef NX_DEVICERCTLKEYMASK
    42     #define NX_DEVICELCTLKEYMASK    0x00000001
    42 #define NX_DEVICELCTLKEYMASK    0x00000001
    43 #endif
    43 #endif
    44 #ifndef NX_DEVICELSHIFTKEYMASK
    44 #ifndef NX_DEVICELSHIFTKEYMASK
    45     #define NX_DEVICELSHIFTKEYMASK  0x00000002
    45 #define NX_DEVICELSHIFTKEYMASK  0x00000002
    46 #endif
    46 #endif
    47 #ifndef NX_DEVICERSHIFTKEYMASK
    47 #ifndef NX_DEVICERSHIFTKEYMASK
    48     #define NX_DEVICERSHIFTKEYMASK  0x00000004
    48 #define NX_DEVICERSHIFTKEYMASK  0x00000004
    49 #endif
    49 #endif
    50 #ifndef NX_DEVICELCMDKEYMASK
    50 #ifndef NX_DEVICELCMDKEYMASK
    51     #define NX_DEVICELCMDKEYMASK    0x00000008
    51 #define NX_DEVICELCMDKEYMASK    0x00000008
    52 #endif
    52 #endif
    53 #ifndef NX_DEVICERCMDKEYMASK
    53 #ifndef NX_DEVICERCMDKEYMASK
    54     #define NX_DEVICERCMDKEYMASK    0x00000010
    54 #define NX_DEVICERCMDKEYMASK    0x00000010
    55 #endif
    55 #endif
    56 #ifndef NX_DEVICELALTKEYMASK
    56 #ifndef NX_DEVICELALTKEYMASK
    57     #define NX_DEVICELALTKEYMASK    0x00000020
    57 #define NX_DEVICELALTKEYMASK    0x00000020
    58 #endif
    58 #endif
    59 #ifndef NX_DEVICERALTKEYMASK
    59 #ifndef NX_DEVICERALTKEYMASK
    60     #define NX_DEVICERALTKEYMASK    0x00000040
    60 #define NX_DEVICERALTKEYMASK    0x00000040
    61 #endif
    61 #endif
    62 #ifndef NX_DEVICERCTLKEYMASK
    62 #ifndef NX_DEVICERCTLKEYMASK
    63     #define NX_DEVICERCTLKEYMASK    0x00002000
    63 #define NX_DEVICERCTLKEYMASK    0x00002000
    64 #endif
    64 #endif
    65 
    65 
    66 void     QZ_InitOSKeymap (_THIS) {
    66 void
       
    67 QZ_InitOSKeymap (_THIS)
       
    68 {
    67     const void *KCHRPtr;
    69     const void *KCHRPtr;
    68     UInt32 state;
    70     UInt32 state;
    69     UInt32 value;
    71     UInt32 value;
    70     int i;
    72     int i;
    71     int world = SDLK_WORLD_0;
    73     int world = SDLK_WORLD_0;
    72 
    74 
    73     for ( i=0; i<SDL_TABLESIZE(keymap); ++i )
    75     for (i = 0; i < SDL_TABLESIZE (keymap); ++i)
    74         keymap[i] = SDLK_UNKNOWN;
    76         keymap[i] = SDLK_UNKNOWN;
    75 
    77 
    76     /* This keymap is almost exactly the same as the OS 9 one */
    78     /* This keymap is almost exactly the same as the OS 9 one */
    77     keymap[QZ_ESCAPE] = SDLK_ESCAPE;
    79     keymap[QZ_ESCAPE] = SDLK_ESCAPE;
    78     keymap[QZ_F1] = SDLK_F1;
    80     keymap[QZ_F1] = SDLK_F1;
   180     keymap[QZ_KP0] = SDLK_KP0;
   182     keymap[QZ_KP0] = SDLK_KP0;
   181     keymap[QZ_KP_PERIOD] = SDLK_KP_PERIOD;
   183     keymap[QZ_KP_PERIOD] = SDLK_KP_PERIOD;
   182     keymap[QZ_IBOOK_ENTER] = SDLK_KP_ENTER;
   184     keymap[QZ_IBOOK_ENTER] = SDLK_KP_ENTER;
   183     keymap[QZ_IBOOK_RIGHT] = SDLK_RIGHT;
   185     keymap[QZ_IBOOK_RIGHT] = SDLK_RIGHT;
   184     keymap[QZ_IBOOK_DOWN] = SDLK_DOWN;
   186     keymap[QZ_IBOOK_DOWN] = SDLK_DOWN;
   185     keymap[QZ_IBOOK_UP]      = SDLK_UP;
   187     keymap[QZ_IBOOK_UP] = SDLK_UP;
   186     keymap[QZ_IBOOK_LEFT] = SDLK_LEFT;
   188     keymap[QZ_IBOOK_LEFT] = SDLK_LEFT;
   187 
   189 
   188     /* 
   190     /* 
   189         Up there we setup a static scancode->keysym map. However, it will not
   191        Up there we setup a static scancode->keysym map. However, it will not
   190         work very well on international keyboard. Hence we now query MacOS
   192        work very well on international keyboard. Hence we now query MacOS
   191         for its own keymap to adjust our own mapping table. However, this is
   193        for its own keymap to adjust our own mapping table. However, this is
   192         basically only useful for ascii char keys. This is also the reason
   194        basically only useful for ascii char keys. This is also the reason
   193         why we keep the static table, too.
   195        why we keep the static table, too.
   194      */
   196      */
   195 
   197 
   196     /* Get a pointer to the systems cached KCHR */
   198     /* Get a pointer to the systems cached KCHR */
   197     KCHRPtr = (void *)GetScriptManagerVariable(smKCHRCache);
   199     KCHRPtr = (void *) GetScriptManagerVariable (smKCHRCache);
   198     if (KCHRPtr)
   200     if (KCHRPtr) {
   199     {
       
   200         /* Loop over all 127 possible scan codes */
   201         /* Loop over all 127 possible scan codes */
   201         for (i = 0; i < 0x7F; i++)
   202         for (i = 0; i < 0x7F; i++) {
   202         {
       
   203             /* We pretend a clean start to begin with (i.e. no dead keys active */
   203             /* We pretend a clean start to begin with (i.e. no dead keys active */
   204             state = 0;
   204             state = 0;
   205 
   205 
   206             /* Now translate the key code to a key value */
   206             /* Now translate the key code to a key value */
   207             value = KeyTranslate(KCHRPtr, i, &state) & 0xff;
   207             value = KeyTranslate (KCHRPtr, i, &state) & 0xff;
   208 
   208 
   209             /* If the state become 0, it was a dead key. We need to translate again,
   209             /* If the state become 0, it was a dead key. We need to translate again,
   210                 passing in the new state, to get the actual key value */
   210                passing in the new state, to get the actual key value */
   211             if (state != 0)
   211             if (state != 0)
   212                 value = KeyTranslate(KCHRPtr, i, &state) & 0xff;
   212                 value = KeyTranslate (KCHRPtr, i, &state) & 0xff;
   213 
   213 
   214             /* Now we should have an ascii value, or 0. Try to figure out to which SDL symbol it maps */
   214             /* Now we should have an ascii value, or 0. Try to figure out to which SDL symbol it maps */
   215             if (value >= 128)     /* Some non-ASCII char, map it to SDLK_WORLD_* */
   215             if (value >= 128)   /* Some non-ASCII char, map it to SDLK_WORLD_* */
   216                 keymap[i] = world++;
   216                 keymap[i] = world++;
   217             else if (value >= 32)     /* non-control ASCII char */
   217             else if (value >= 32)       /* non-control ASCII char */
   218                 keymap[i] = value;
   218                 keymap[i] = value;
   219         }
   219         }
   220     }
   220     }
   221 
   221 
   222     /* 
   222     /* 
   223         The keypad codes are re-setup here, because the loop above cannot
   223        The keypad codes are re-setup here, because the loop above cannot
   224         distinguish between a key on the keypad and a regular key. We maybe
   224        distinguish between a key on the keypad and a regular key. We maybe
   225         could get around this problem in another fashion: NSEvent's flags
   225        could get around this problem in another fashion: NSEvent's flags
   226         include a "NSNumericPadKeyMask" bit; we could check that and modify
   226        include a "NSNumericPadKeyMask" bit; we could check that and modify
   227         the symbol we return on the fly. However, this flag seems to exhibit
   227        the symbol we return on the fly. However, this flag seems to exhibit
   228         some weird behaviour related to the num lock key
   228        some weird behaviour related to the num lock key
   229     */
   229      */
   230     keymap[QZ_KP0] = SDLK_KP0;
   230     keymap[QZ_KP0] = SDLK_KP0;
   231     keymap[QZ_KP1] = SDLK_KP1;
   231     keymap[QZ_KP1] = SDLK_KP1;
   232     keymap[QZ_KP2] = SDLK_KP2;
   232     keymap[QZ_KP2] = SDLK_KP2;
   233     keymap[QZ_KP3] = SDLK_KP3;
   233     keymap[QZ_KP3] = SDLK_KP3;
   234     keymap[QZ_KP4] = SDLK_KP4;
   234     keymap[QZ_KP4] = SDLK_KP4;
   244     keymap[QZ_KP_DIVIDE] = SDLK_KP_DIVIDE;
   244     keymap[QZ_KP_DIVIDE] = SDLK_KP_DIVIDE;
   245     keymap[QZ_KP_MULTIPLY] = SDLK_KP_MULTIPLY;
   245     keymap[QZ_KP_MULTIPLY] = SDLK_KP_MULTIPLY;
   246     keymap[QZ_KP_ENTER] = SDLK_KP_ENTER;
   246     keymap[QZ_KP_ENTER] = SDLK_KP_ENTER;
   247 }
   247 }
   248 
   248 
   249 static void QZ_DoKey (_THIS, int state, NSEvent *event) {
   249 static void
       
   250 QZ_DoKey (_THIS, int state, NSEvent * event)
       
   251 {
   250 
   252 
   251     NSString *chars;
   253     NSString *chars;
   252     unsigned int numChars;
   254     unsigned int numChars;
   253     SDL_keysym key;
   255     SDL_keysym key;
   254     
   256 
   255     /* 
   257     /* 
   256         A key event can contain multiple characters,
   258        A key event can contain multiple characters,
   257         or no characters at all. In most cases, it
   259        or no characters at all. In most cases, it
   258         will contain a single character. If it contains
   260        will contain a single character. If it contains
   259         0 characters, we'll use 0 as the unicode. If it
   261        0 characters, we'll use 0 as the unicode. If it
   260         contains multiple characters, we'll use 0 as
   262        contains multiple characters, we'll use 0 as
   261         the scancode/keysym.
   263        the scancode/keysym.
   262     */
   264      */
   263     if (SDL_TranslateUNICODE) {
   265     chars =[event characters];
   264         chars = [ event characters ];
   266     numChars =[chars length];
   265         numChars = [ chars length ];
   267 
   266     } else {
   268     if (numChars == 1) {
   267         numChars = 0;
   269 
   268     }
   270         key.scancode =[event keyCode];
   269 
   271         key.sym = keymap[key.scancode];
   270     if (numChars == 0) {
   272       key.unicode =[chars characterAtIndex:0];
   271       
   273         key.mod = KMOD_NONE;
   272         key.scancode = [ event keyCode ];
       
   273         key.sym      = keymap [ key.scancode ];
       
   274         key.unicode  = 0;
       
   275         key.mod      = KMOD_NONE;
       
   276 
   274 
   277         SDL_PrivateKeyboard (state, &key);
   275         SDL_PrivateKeyboard (state, &key);
   278     }
   276     } else if (numChars == 0) {
   279     else if (numChars == 1) {
   277 
   280 
   278         key.scancode =[event keyCode];
   281         key.scancode = [ event keyCode ];
   279         key.sym = keymap[key.scancode];
   282         key.sym      = keymap [ key.scancode ];
   280         key.unicode = 0;
   283         key.unicode  = [ chars characterAtIndex:0 ];
   281         key.mod = KMOD_NONE;
   284         key.mod      = KMOD_NONE;
       
   285 
   282 
   286         SDL_PrivateKeyboard (state, &key);
   283         SDL_PrivateKeyboard (state, &key);
   287     }
   284     } else {                    /* (numChars > 1) */
   288     else /* (numChars > 1) */ {
   285 
   289       
   286 
   290         int i;
   287         int i;
   291         for (i = 0; i < numChars; i++) {
   288         for (i = 0; i < numChars; i++) {
   292 
   289 
   293             key.scancode = 0;
   290             key.scancode = 0;
   294             key.sym      = 0;
   291             key.sym = 0;
   295             key.unicode  = [ chars characterAtIndex:i];
   292           key.unicode =[chars characterAtIndex:i];
   296             key.mod      = KMOD_NONE;
   293             key.mod = KMOD_NONE;
   297 
   294 
   298             SDL_PrivateKeyboard (state, &key);
   295             SDL_PrivateKeyboard (state, &key);
   299         }
   296         }
   300     }
   297     }
   301     
   298 
   302     if (SDL_getenv ("SDL_ENABLEAPPEVENTS"))
   299     if (SDL_getenv ("SDL_ENABLEAPPEVENTS"))
   303         [ NSApp sendEvent:event ];
   300       [NSApp sendEvent:event];
   304 }
   301 }
   305 
   302 
   306 /* This is the original behavior, before support was added for 
   303 /* This is the original behavior, before support was added for 
   307  * differentiating between left and right versions of the keys.
   304  * differentiating between left and right versions of the keys.
   308  */
   305  */
   309 static void QZ_DoUnsidedModifiers (_THIS, unsigned int newMods) {
   306 static void
   310 
   307 QZ_DoUnsidedModifiers (_THIS, unsigned int newMods)
   311     const int mapping[] = { SDLK_CAPSLOCK, SDLK_LSHIFT, SDLK_LCTRL, SDLK_LALT, SDLK_LMETA };
   308 {
       
   309 
       
   310     const int mapping[] =
       
   311         { SDLK_CAPSLOCK, SDLK_LSHIFT, SDLK_LCTRL, SDLK_LALT, SDLK_LMETA };
   312 
   312 
   313     int i;
   313     int i;
   314     int bit;
   314     int bit;
   315     SDL_keysym key;
   315     SDL_keysym key;
   316     
   316 
   317     key.scancode    = 0;
   317     key.scancode = 0;
   318     key.sym         = SDLK_UNKNOWN;
   318     key.sym = SDLK_UNKNOWN;
   319     key.unicode     = 0;
   319     key.unicode = 0;
   320     key.mod         = KMOD_NONE;
   320     key.mod = KMOD_NONE;
   321 
   321 
   322     /* Iterate through the bits, testing each against the current modifiers */
   322     /* Iterate through the bits, testing each against the current modifiers */
   323     for (i = 0, bit = NSAlphaShiftKeyMask; bit <= NSCommandKeyMask; bit <<= 1, ++i) {
   323     for (i = 0, bit = NSAlphaShiftKeyMask; bit <= NSCommandKeyMask;
       
   324          bit <<= 1, ++i) {
   324 
   325 
   325         unsigned int currentMask, newMask;
   326         unsigned int currentMask, newMask;
   326 
   327 
   327         currentMask = current_mods & bit;
   328         currentMask = current_mods & bit;
   328         newMask     = newMods & bit;
   329         newMask = newMods & bit;
   329 
   330 
   330         if ( currentMask &&
   331         if (currentMask && currentMask != newMask) {    /* modifier up event */
   331              currentMask != newMask ) {     /* modifier up event */
   332 
   332 
   333             key.sym = mapping[i];
   333              key.sym = mapping[i];
   334             /* If this was Caps Lock, we need some additional voodoo to make SDL happy */
   334              /* If this was Caps Lock, we need some additional voodoo to make SDL happy */
   335             if (bit == NSAlphaShiftKeyMask)
   335              if (bit == NSAlphaShiftKeyMask)
   336                 SDL_PrivateKeyboard (SDL_PRESSED, &key);
   336                   SDL_PrivateKeyboard (SDL_PRESSED, &key);
   337             SDL_PrivateKeyboard (SDL_RELEASED, &key);
   337              SDL_PrivateKeyboard (SDL_RELEASED, &key);
   338         } else if (newMask && currentMask != newMask) { /* modifier down event */
   338         }
   339 
   339         else if ( newMask &&
   340             key.sym = mapping[i];
   340                   currentMask != newMask ) {     /* modifier down event */
   341             SDL_PrivateKeyboard (SDL_PRESSED, &key);
   341         
   342             /* If this was Caps Lock, we need some additional voodoo to make SDL happy */
   342              key.sym = mapping[i];
   343             if (bit == NSAlphaShiftKeyMask)
   343              SDL_PrivateKeyboard (SDL_PRESSED, &key);
   344                 SDL_PrivateKeyboard (SDL_RELEASED, &key);
   344              /* If this was Caps Lock, we need some additional voodoo to make SDL happy */
       
   345              if (bit == NSAlphaShiftKeyMask)
       
   346                   SDL_PrivateKeyboard (SDL_RELEASED, &key);
       
   347         }
   345         }
   348     }
   346     }
   349 }
   347 }
   350 
   348 
   351 /* This is a helper function for QZ_HandleModifierSide. This 
   349 /* This is a helper function for QZ_HandleModifierSide. This 
   352  * function reverts back to behavior before the distinction between
   350  * function reverts back to behavior before the distinction between
   353  * sides was made.
   351  * sides was made.
   354  */
   352  */
   355 static void QZ_HandleNonDeviceModifier ( _THIS, unsigned int device_independent_mask, unsigned int newMods, unsigned int key_sym) {
   353 static void
       
   354 QZ_HandleNonDeviceModifier (_THIS, unsigned int device_independent_mask,
       
   355                             unsigned int newMods, unsigned int key_sym)
       
   356 {
   356     unsigned int currentMask, newMask;
   357     unsigned int currentMask, newMask;
   357     SDL_keysym key;
   358     SDL_keysym key;
   358     
   359 
   359     key.scancode    = 0;
   360     key.scancode = 0;
   360     key.sym         = key_sym;
   361     key.sym = key_sym;
   361     key.unicode     = 0;
   362     key.unicode = 0;
   362     key.mod         = KMOD_NONE;
   363     key.mod = KMOD_NONE;
   363     
   364 
   364     /* Isolate just the bits we care about in the depedent bits so we can 
   365     /* Isolate just the bits we care about in the depedent bits so we can 
   365      * figure out what changed
   366      * figure out what changed
   366      */ 
   367      */
   367     currentMask = current_mods & device_independent_mask;
   368     currentMask = current_mods & device_independent_mask;
   368     newMask     = newMods & device_independent_mask;
   369     newMask = newMods & device_independent_mask;
   369     
   370 
   370     if ( currentMask &&
   371     if (currentMask && currentMask != newMask) {        /* modifier up event */
   371          currentMask != newMask ) {     /* modifier up event */
   372         SDL_PrivateKeyboard (SDL_RELEASED, &key);
   372          SDL_PrivateKeyboard (SDL_RELEASED, &key);
   373     } else if (newMask && currentMask != newMask) {     /* modifier down event */
   373     }
   374         SDL_PrivateKeyboard (SDL_PRESSED, &key);
   374     else if ( newMask &&
       
   375           currentMask != newMask ) {     /* modifier down event */
       
   376           SDL_PrivateKeyboard (SDL_PRESSED, &key);
       
   377     }
   375     }
   378 }
   376 }
   379 
   377 
   380 /* This is a helper function for QZ_HandleModifierSide. 
   378 /* This is a helper function for QZ_HandleModifierSide. 
   381  * This function sets the actual SDL_PrivateKeyboard event.
   379  * This function sets the actual SDL_PrivateKeyboard event.
   382  */
   380  */
   383 static void QZ_HandleModifierOneSide ( _THIS, unsigned int newMods,
   381 static void
   384                                        unsigned int key_sym, 
   382 QZ_HandleModifierOneSide (_THIS, unsigned int newMods,
   385                                        unsigned int sided_device_dependent_mask ) {
   383                           unsigned int key_sym,
   386     
   384                           unsigned int sided_device_dependent_mask)
       
   385 {
       
   386 
   387     SDL_keysym key;
   387     SDL_keysym key;
   388     unsigned int current_dep_mask, new_dep_mask;
   388     unsigned int current_dep_mask, new_dep_mask;
   389     
   389 
   390     key.scancode    = 0;
   390     key.scancode = 0;
   391     key.sym         = key_sym;
   391     key.sym = key_sym;
   392     key.unicode     = 0;
   392     key.unicode = 0;
   393     key.mod         = KMOD_NONE;
   393     key.mod = KMOD_NONE;
   394     
   394 
   395     /* Isolate just the bits we care about in the depedent bits so we can 
   395     /* Isolate just the bits we care about in the depedent bits so we can 
   396      * figure out what changed
   396      * figure out what changed
   397      */ 
   397      */
   398     current_dep_mask = current_mods & sided_device_dependent_mask;
   398     current_dep_mask = current_mods & sided_device_dependent_mask;
   399     new_dep_mask     = newMods & sided_device_dependent_mask;
   399     new_dep_mask = newMods & sided_device_dependent_mask;
   400     
   400 
   401     /* We now know that this side bit flipped. But we don't know if
   401     /* We now know that this side bit flipped. But we don't know if
   402      * it went pressed to released or released to pressed, so we must 
   402      * it went pressed to released or released to pressed, so we must 
   403      * find out which it is.
   403      * find out which it is.
   404      */
   404      */
   405     if( new_dep_mask &&
   405     if (new_dep_mask && current_dep_mask != new_dep_mask) {
   406         current_dep_mask != new_dep_mask ) { 
       
   407         /* Modifier down event */
   406         /* Modifier down event */
   408         SDL_PrivateKeyboard (SDL_PRESSED, &key);
   407         SDL_PrivateKeyboard (SDL_PRESSED, &key);
   409     }
   408     } else {                    /* Modifier up event */
   410     else /* Modifier up event */ {
   409 
   411         SDL_PrivateKeyboard (SDL_RELEASED, &key);
   410         SDL_PrivateKeyboard (SDL_RELEASED, &key);
   412     }
   411     }
   413 }
   412 }
   414 
   413 
   415 /* This is a helper function for QZ_DoSidedModifiers.
   414 /* This is a helper function for QZ_DoSidedModifiers.
   416  * This function will figure out if the modifier key is the left or right side, 
   415  * This function will figure out if the modifier key is the left or right side, 
   417  * e.g. left-shift vs right-shift. 
   416  * e.g. left-shift vs right-shift. 
   418  */
   417  */
   419 static void QZ_HandleModifierSide ( _THIS, int device_independent_mask, 
   418 static void
   420                                     unsigned int newMods, 
   419 QZ_HandleModifierSide (_THIS, int device_independent_mask,
   421                                     unsigned int left_key_sym, 
   420                        unsigned int newMods,
   422                                     unsigned int right_key_sym,
   421                        unsigned int left_key_sym,
   423                                     unsigned int left_device_dependent_mask, 
   422                        unsigned int right_key_sym,
   424                                     unsigned int right_device_dependent_mask ) {
   423                        unsigned int left_device_dependent_mask,
       
   424                        unsigned int right_device_dependent_mask)
       
   425 {
   425     unsigned int device_dependent_mask = 0;
   426     unsigned int device_dependent_mask = 0;
   426     unsigned int diff_mod = 0;
   427     unsigned int diff_mod = 0;
   427     
   428 
   428     device_dependent_mask = left_device_dependent_mask | right_device_dependent_mask;
   429     device_dependent_mask =
       
   430         left_device_dependent_mask | right_device_dependent_mask;
   429     /* On the basis that the device independent mask is set, but there are 
   431     /* On the basis that the device independent mask is set, but there are 
   430      * no device dependent flags set, we'll assume that we can't detect this 
   432      * no device dependent flags set, we'll assume that we can't detect this 
   431      * keyboard and revert to the unsided behavior.
   433      * keyboard and revert to the unsided behavior.
   432      */
   434      */
   433     if ( (device_dependent_mask & newMods) == 0 ) {
   435     if ((device_dependent_mask & newMods) == 0) {
   434         /* Revert to the old behavior */
   436         /* Revert to the old behavior */
   435         QZ_HandleNonDeviceModifier ( this, device_independent_mask, newMods, left_key_sym );
   437         QZ_HandleNonDeviceModifier (this, device_independent_mask, newMods,
       
   438                                     left_key_sym);
   436         return;
   439         return;
   437     }
   440     }
   438         
   441 
   439     /* XOR the previous state against the new state to see if there's a change */
   442     /* XOR the previous state against the new state to see if there's a change */
   440     diff_mod = (device_dependent_mask & current_mods)
   443     diff_mod = (device_dependent_mask & current_mods)
   441         ^ (device_dependent_mask & newMods);
   444         ^ (device_dependent_mask & newMods);
   442 
   445 
   443     if ( diff_mod ) {
   446     if (diff_mod) {
   444         /* A change in state was found. Isolate the left and right bits 
   447         /* A change in state was found. Isolate the left and right bits 
   445          * to handle them separately just in case the values can simulataneously
   448          * to handle them separately just in case the values can simulataneously
   446          * change or if the bits don't both exist.
   449          * change or if the bits don't both exist.
   447          */
   450          */
   448         if ( left_device_dependent_mask & diff_mod ) {
   451         if (left_device_dependent_mask & diff_mod) {
   449             QZ_HandleModifierOneSide ( this, newMods, left_key_sym, left_device_dependent_mask );
   452             QZ_HandleModifierOneSide (this, newMods, left_key_sym,
       
   453                                       left_device_dependent_mask);
   450         }
   454         }
   451         if ( right_device_dependent_mask & diff_mod ) {
   455         if (right_device_dependent_mask & diff_mod) {
   452             QZ_HandleModifierOneSide ( this, newMods, right_key_sym, right_device_dependent_mask );
   456             QZ_HandleModifierOneSide (this, newMods, right_key_sym,
       
   457                                       right_device_dependent_mask);
   453         }
   458         }
   454     }
   459     }
   455 }
   460 }
   456    
   461 
   457 /* This is a helper function for QZ_DoSidedModifiers.
   462 /* This is a helper function for QZ_DoSidedModifiers.
   458  * This function will release a key press in the case that 
   463  * This function will release a key press in the case that 
   459  * it is clear that the modifier has been released (i.e. one side 
   464  * it is clear that the modifier has been released (i.e. one side 
   460  * can't still be down).
   465  * can't still be down).
   461  */
   466  */
   462 static void QZ_ReleaseModifierSide ( _THIS, 
   467 static void
   463                                      unsigned int device_independent_mask, 
   468 QZ_ReleaseModifierSide (_THIS,
   464                                      unsigned int newMods,
   469                         unsigned int device_independent_mask,
   465                                      unsigned int left_key_sym, 
   470                         unsigned int newMods,
   466                                      unsigned int right_key_sym,
   471                         unsigned int left_key_sym,
   467                                      unsigned int left_device_dependent_mask, 
   472                         unsigned int right_key_sym,
   468                                      unsigned int right_device_dependent_mask ) {
   473                         unsigned int left_device_dependent_mask,
       
   474                         unsigned int right_device_dependent_mask)
       
   475 {
   469     unsigned int device_dependent_mask = 0;
   476     unsigned int device_dependent_mask = 0;
   470     SDL_keysym key;
   477     SDL_keysym key;
   471     
   478 
   472     key.scancode    = 0;
   479     key.scancode = 0;
   473     key.sym         = SDLK_UNKNOWN;
   480     key.sym = SDLK_UNKNOWN;
   474     key.unicode     = 0;
   481     key.unicode = 0;
   475     key.mod         = KMOD_NONE;
   482     key.mod = KMOD_NONE;
   476     
   483 
   477     device_dependent_mask = left_device_dependent_mask | right_device_dependent_mask;
   484     device_dependent_mask =
       
   485         left_device_dependent_mask | right_device_dependent_mask;
   478     /* On the basis that the device independent mask is set, but there are 
   486     /* On the basis that the device independent mask is set, but there are 
   479      * no device dependent flags set, we'll assume that we can't detect this 
   487      * no device dependent flags set, we'll assume that we can't detect this 
   480      * keyboard and revert to the unsided behavior.
   488      * keyboard and revert to the unsided behavior.
   481      */
   489      */
   482     if ( (device_dependent_mask & current_mods) == 0 ) {
   490     if ((device_dependent_mask & current_mods) == 0) {
   483         /* In this case, we can't detect the keyboard, so use the left side 
   491         /* In this case, we can't detect the keyboard, so use the left side 
   484          * to represent both, and release it. 
   492          * to represent both, and release it. 
   485          */
   493          */
   486         key.sym = left_key_sym;
   494         key.sym = left_key_sym;
   487         SDL_PrivateKeyboard (SDL_RELEASED, &key);
   495         SDL_PrivateKeyboard (SDL_RELEASED, &key);
   488 
   496 
   489         return;
   497         return;
   490     }
   498     }
   491         
   499 
   492         
   500 
   493     /* 
   501     /* 
   494      * This could have been done in an if-else case because at this point,
   502      * This could have been done in an if-else case because at this point,
   495      * we know that all keys have been released when calling this function. 
   503      * we know that all keys have been released when calling this function. 
   496      * But I'm being paranoid so I want to handle each separately,
   504      * But I'm being paranoid so I want to handle each separately,
   497      * so I hope this doesn't cause other problems.
   505      * so I hope this doesn't cause other problems.
   498      */
   506      */
   499     if ( left_device_dependent_mask & current_mods ) {
   507     if (left_device_dependent_mask & current_mods) {
   500         key.sym = left_key_sym;
   508         key.sym = left_key_sym;
   501         SDL_PrivateKeyboard (SDL_RELEASED, &key);
   509         SDL_PrivateKeyboard (SDL_RELEASED, &key);
   502     }
   510     }
   503     if ( right_device_dependent_mask & current_mods ) {
   511     if (right_device_dependent_mask & current_mods) {
   504         key.sym = right_key_sym;
   512         key.sym = right_key_sym;
   505         SDL_PrivateKeyboard (SDL_RELEASED, &key);
   513         SDL_PrivateKeyboard (SDL_RELEASED, &key);
   506     }
   514     }
   507 }
   515 }
   508 
   516 
   509 /* This is a helper function for QZ_DoSidedModifiers.
   517 /* This is a helper function for QZ_DoSidedModifiers.
   510  * This function handles the CapsLock case.
   518  * This function handles the CapsLock case.
   511  */
   519  */
   512 static void QZ_HandleCapsLock (_THIS, unsigned int newMods) {
   520 static void
       
   521 QZ_HandleCapsLock (_THIS, unsigned int newMods)
       
   522 {
   513     unsigned int currentMask, newMask;
   523     unsigned int currentMask, newMask;
   514     SDL_keysym key;
   524     SDL_keysym key;
   515     
   525 
   516     key.scancode    = 0;
   526     key.scancode = 0;
   517     key.sym         = SDLK_CAPSLOCK;
   527     key.sym = SDLK_CAPSLOCK;
   518     key.unicode     = 0;
   528     key.unicode = 0;
   519     key.mod         = KMOD_NONE;
   529     key.mod = KMOD_NONE;
   520     
   530 
   521     currentMask = current_mods & NSAlphaShiftKeyMask;
   531     currentMask = current_mods & NSAlphaShiftKeyMask;
   522     newMask     = newMods & NSAlphaShiftKeyMask;
   532     newMask = newMods & NSAlphaShiftKeyMask;
   523 
   533 
   524     if ( currentMask &&
   534     if (currentMask && currentMask != newMask) {        /* modifier up event */
   525          currentMask != newMask ) {     /* modifier up event */
       
   526          /* If this was Caps Lock, we need some additional voodoo to make SDL happy */
       
   527          SDL_PrivateKeyboard (SDL_PRESSED, &key);
       
   528          SDL_PrivateKeyboard (SDL_RELEASED, &key);
       
   529     }
       
   530     else if ( newMask &&
       
   531               currentMask != newMask ) {     /* modifier down event */
       
   532         /* If this was Caps Lock, we need some additional voodoo to make SDL happy */
   535         /* If this was Caps Lock, we need some additional voodoo to make SDL happy */
   533         SDL_PrivateKeyboard (SDL_PRESSED, &key);
   536         SDL_PrivateKeyboard (SDL_PRESSED, &key);
   534         SDL_PrivateKeyboard (SDL_RELEASED, &key);
   537         SDL_PrivateKeyboard (SDL_RELEASED, &key);
       
   538     } else if (newMask && currentMask != newMask) {     /* modifier down event */
       
   539         /* If this was Caps Lock, we need some additional voodoo to make SDL happy */
       
   540         SDL_PrivateKeyboard (SDL_PRESSED, &key);
       
   541         SDL_PrivateKeyboard (SDL_RELEASED, &key);
   535     }
   542     }
   536 }
   543 }
   537 
   544 
   538 /* This function will handle the modifier keys and also determine the 
   545 /* This function will handle the modifier keys and also determine the 
   539  * correct side of the key.
   546  * correct side of the key.
   540  */
   547  */
   541 static void QZ_DoSidedModifiers (_THIS, unsigned int newMods) {
   548 static void
   542 	/* Set up arrays for the key syms for the left and right side. */
   549 QZ_DoSidedModifiers (_THIS, unsigned int newMods)
   543     const unsigned int left_mapping[]  = { SDLK_LSHIFT, SDLK_LCTRL, SDLK_LALT, SDLK_LMETA };
   550 {
   544     const unsigned int right_mapping[] = { SDLK_RSHIFT, SDLK_RCTRL, SDLK_RALT, SDLK_RMETA };
   551     /* Set up arrays for the key syms for the left and right side. */
   545 	/* Set up arrays for the device dependent masks with indices that 
   552     const unsigned int left_mapping[] =
       
   553         { SDLK_LSHIFT, SDLK_LCTRL, SDLK_LALT, SDLK_LMETA };
       
   554     const unsigned int right_mapping[] =
       
   555         { SDLK_RSHIFT, SDLK_RCTRL, SDLK_RALT, SDLK_RMETA };
       
   556     /* Set up arrays for the device dependent masks with indices that 
   546      * correspond to the _mapping arrays 
   557      * correspond to the _mapping arrays 
   547      */
   558      */
   548     const unsigned int left_device_mapping[]  = { NX_DEVICELSHIFTKEYMASK, NX_DEVICELCTLKEYMASK, NX_DEVICELALTKEYMASK, NX_DEVICELCMDKEYMASK };
   559     const unsigned int left_device_mapping[] =
   549     const unsigned int right_device_mapping[] = { NX_DEVICERSHIFTKEYMASK, NX_DEVICERCTLKEYMASK, NX_DEVICERALTKEYMASK, NX_DEVICERCMDKEYMASK };
   560         { NX_DEVICELSHIFTKEYMASK, NX_DEVICELCTLKEYMASK, NX_DEVICELALTKEYMASK,
       
   561         NX_DEVICELCMDKEYMASK
       
   562     };
       
   563     const unsigned int right_device_mapping[] =
       
   564         { NX_DEVICERSHIFTKEYMASK, NX_DEVICERCTLKEYMASK, NX_DEVICERALTKEYMASK,
       
   565         NX_DEVICERCMDKEYMASK
       
   566     };
   550 
   567 
   551     unsigned int i;
   568     unsigned int i;
   552     unsigned int bit;
   569     unsigned int bit;
   553     
   570 
   554     /* Handle CAPSLOCK separately because it doesn't have a left/right side */
   571     /* Handle CAPSLOCK separately because it doesn't have a left/right side */
   555     QZ_HandleCapsLock ( this, newMods );
   572     QZ_HandleCapsLock (this, newMods);
   556         
   573 
   557     /* Iterate through the bits, testing each against the current modifiers */
   574     /* Iterate through the bits, testing each against the current modifiers */
   558     for (i = 0, bit = NSShiftKeyMask; bit <= NSCommandKeyMask; bit <<= 1, ++i) {
   575     for (i = 0, bit = NSShiftKeyMask; bit <= NSCommandKeyMask; bit <<= 1, ++i) {
   559 		
   576 
   560         unsigned int currentMask, newMask;
   577         unsigned int currentMask, newMask;
   561 		
   578 
   562         currentMask = current_mods & bit;
   579         currentMask = current_mods & bit;
   563         newMask     = newMods & bit;
   580         newMask = newMods & bit;
   564 		
   581 
   565         /* If the bit is set, we must always examine it because the left
   582         /* If the bit is set, we must always examine it because the left
   566          * and right side keys may alternate or both may be pressed.
   583          * and right side keys may alternate or both may be pressed.
   567          */
   584          */
   568         if ( newMask ) {
   585         if (newMask) {
   569             QZ_HandleModifierSide ( this, bit, newMods, 
   586             QZ_HandleModifierSide (this, bit, newMods,
   570                                        left_mapping[i],
   587                                    left_mapping[i],
   571                                        right_mapping[i],
   588                                    right_mapping[i],
   572                                        left_device_mapping[i],
   589                                    left_device_mapping[i],
   573                                        right_device_mapping[i] );
   590                                    right_device_mapping[i]);
   574         }
   591         }
   575         /* If the state changed from pressed to unpressed, we must examine
   592         /* If the state changed from pressed to unpressed, we must examine
   576             * the device dependent bits to release the correct keys.
   593          * the device dependent bits to release the correct keys.
   577             */
   594          */
   578         else if ( currentMask &&
   595         else if (currentMask && currentMask != newMask) {       /* modifier up event */
   579                   currentMask != newMask ) { /* modifier up event */
   596             QZ_ReleaseModifierSide (this, bit, newMods,
   580                   QZ_ReleaseModifierSide ( this, bit, newMods,
   597                                     left_mapping[i],
   581                                            left_mapping[i],
   598                                     right_mapping[i],
   582                                            right_mapping[i],
   599                                     left_device_mapping[i],
   583                                            left_device_mapping[i],
   600                                     right_device_mapping[i]);
   584                                            right_device_mapping[i] );
       
   585         }
   601         }
   586     }
   602     }
   587 }
   603 }
   588 
   604 
   589 /* This function is called to handle the modifiers.
   605 /* This function is called to handle the modifiers.
   590  * It will try to distinguish between the left side and right side 
   606  * It will try to distinguish between the left side and right side 
   591  * of the keyboard for those modifiers that qualify if the 
   607  * of the keyboard for those modifiers that qualify if the 
   592  * operating system version supports it. Otherwise, the code 
   608  * operating system version supports it. Otherwise, the code 
   593  * will not try to make the distinction.
   609  * will not try to make the distinction.
   594  */
   610  */
   595 static void QZ_DoModifiers (_THIS, unsigned int newMods) {
   611 static void
   596 	
   612 QZ_DoModifiers (_THIS, unsigned int newMods)
       
   613 {
       
   614 
   597     if (current_mods == newMods)
   615     if (current_mods == newMods)
   598     	return;
   616         return;
   599     
   617 
   600     /* 
   618     /* 
   601      * Starting with Panther (10.3.0), the ability to distinguish between 
   619      * Starting with Panther (10.3.0), the ability to distinguish between 
   602      * left side and right side modifiers is available.
   620      * left side and right side modifiers is available.
   603      */
   621      */
   604     if( system_version >= 0x1030 ) {
   622     if (system_version >= 0x1030) {
   605         QZ_DoSidedModifiers (this, newMods);
   623         QZ_DoSidedModifiers (this, newMods);
   606     }
   624     } else {
   607     else {
       
   608         QZ_DoUnsidedModifiers (this, newMods);
   625         QZ_DoUnsidedModifiers (this, newMods);
   609     }
   626     }
   610     
   627 
   611     current_mods = newMods;
   628     current_mods = newMods;
   612 }
   629 }
   613 
   630 
   614 static void QZ_GetMouseLocation (_THIS, NSPoint *p) {
   631 static void
   615     *p = [ NSEvent mouseLocation ]; /* global coordinates */
   632 QZ_GetMouseLocation (_THIS, NSPoint * p)
       
   633 {
       
   634     *p =[NSEvent mouseLocation];        /* global coordinates */
   616     if (qz_window)
   635     if (qz_window)
   617         QZ_PrivateGlobalToLocal (this, p);
   636         QZ_PrivateGlobalToLocal (this, p);
   618     QZ_PrivateCocoaToSDL (this, p);
   637     QZ_PrivateCocoaToSDL (this, p);
   619 }
   638 }
   620 
   639 
   621 void QZ_DoActivate (_THIS) {
   640 void
   622 
   641 QZ_DoActivate (_THIS)
   623     SDL_PrivateAppActive (1, SDL_APPINPUTFOCUS | (QZ_IsMouseInWindow (this) ? SDL_APPMOUSEFOCUS : 0));
   642 {
   624     
   643 
       
   644     SDL_PrivateAppActive (1,
       
   645                           SDL_APPINPUTFOCUS | (QZ_IsMouseInWindow (this) ?
       
   646                                                SDL_APPMOUSEFOCUS : 0));
       
   647 
   625     /* Hide the cursor if it was hidden by SDL_ShowCursor() */
   648     /* Hide the cursor if it was hidden by SDL_ShowCursor() */
   626     if (!cursor_should_be_visible)
   649     if (!cursor_should_be_visible)
   627         QZ_HideMouse (this);
   650         QZ_HideMouse (this);
   628 
   651 
   629     /* Regrab input, only if it was previously grabbed */
   652     /* Regrab input, only if it was previously grabbed */
   630     if ( current_grab_mode == SDL_GRAB_ON ) {
   653     if (current_grab_mode == SDL_GRAB_ON) {
   631         
   654 
   632         /* Restore cursor location if input was grabbed */
   655         /* Restore cursor location if input was grabbed */
   633         QZ_PrivateWarpCursor (this, cursor_loc.x, cursor_loc.y);
   656         QZ_PrivateWarpCursor (this, cursor_loc.x, cursor_loc.y);
   634         QZ_ChangeGrabState (this, QZ_ENABLE_GRAB);
   657         QZ_ChangeGrabState (this, QZ_ENABLE_GRAB);
   635     }
   658     } else {
   636     else {
       
   637         /* Update SDL's mouse location */
   659         /* Update SDL's mouse location */
   638         NSPoint p;
   660         NSPoint p;
   639         QZ_GetMouseLocation (this, &p);
   661         QZ_GetMouseLocation (this, &p);
   640         SDL_PrivateMouseMotion (0, 0, p.x, p.y);
   662         SDL_PrivateMouseMotion (0, 0, p.x, p.y);
   641     }
   663     }
   642 }
   664 }
   643 
   665 
   644 void QZ_DoDeactivate (_THIS) {
   666 void
   645     
   667 QZ_DoDeactivate (_THIS)
       
   668 {
       
   669 
   646     SDL_PrivateAppActive (0, SDL_APPINPUTFOCUS | SDL_APPMOUSEFOCUS);
   670     SDL_PrivateAppActive (0, SDL_APPINPUTFOCUS | SDL_APPMOUSEFOCUS);
   647 
   671 
   648     /* Get the current cursor location, for restore on activate */
   672     /* Get the current cursor location, for restore on activate */
   649     QZ_GetMouseLocation (this, &cursor_loc);
   673     QZ_GetMouseLocation (this, &cursor_loc);
   650     
   674 
   651     /* Reassociate mouse and cursor */
   675     /* Reassociate mouse and cursor */
   652     CGAssociateMouseAndMouseCursorPosition (1);
   676     CGAssociateMouseAndMouseCursorPosition (1);
   653 
   677 
   654     /* Show the cursor if it was hidden by SDL_ShowCursor() */
   678     /* Show the cursor if it was hidden by SDL_ShowCursor() */
   655     if (!cursor_should_be_visible)
   679     if (!cursor_should_be_visible)
   656         QZ_ShowMouse (this);
   680         QZ_ShowMouse (this);
   657 }
   681 }
   658 
   682 
   659 void QZ_SleepNotificationHandler (void * refcon,
   683 void
   660                                   io_service_t service,
   684 QZ_SleepNotificationHandler (void *refcon,
   661                                   natural_t messageType,
   685                              io_service_t service,
   662                                   void * messageArgument )
   686                              natural_t messageType, void *messageArgument)
   663 {
   687 {
   664      SDL_VideoDevice *this = (SDL_VideoDevice*)refcon;
   688     SDL_VideoDevice *this = (SDL_VideoDevice *) refcon;
   665      
   689 
   666      switch(messageType)
   690     switch (messageType) {
   667      {
   691     case kIOMessageSystemWillSleep:
   668          case kIOMessageSystemWillSleep:
   692         IOAllowPowerChange (power_connection, (long) messageArgument);
   669              IOAllowPowerChange(power_connection, (long) messageArgument);
   693         break;
   670              break;
   694     case kIOMessageCanSystemSleep:
   671          case kIOMessageCanSystemSleep:
   695         IOAllowPowerChange (power_connection, (long) messageArgument);
   672              IOAllowPowerChange(power_connection, (long) messageArgument);
   696         break;
   673              break;
   697     case kIOMessageSystemHasPoweredOn:
   674          case kIOMessageSystemHasPoweredOn:
   698         /* awake */
   675             /* awake */
   699         SDL_PrivateExpose ();
   676             SDL_PrivateExpose();
   700         break;
   677             break;
   701     }
   678      }
   702 }
   679 }
   703 
   680 
   704 void
   681 void QZ_RegisterForSleepNotifications (_THIS)
   705 QZ_RegisterForSleepNotifications (_THIS)
   682 {
   706 {
   683      CFRunLoopSourceRef rls;
   707     CFRunLoopSourceRef rls;
   684      IONotificationPortRef thePortRef;
   708     IONotificationPortRef thePortRef;
   685      io_object_t notifier;
   709     io_object_t notifier;
   686 
   710 
   687      power_connection = IORegisterForSystemPower (this, &thePortRef, QZ_SleepNotificationHandler, &notifier);
   711     power_connection =
   688 
   712         IORegisterForSystemPower (this, &thePortRef,
   689      if (power_connection == 0)
   713                                   QZ_SleepNotificationHandler, &notifier);
   690          NSLog(@"SDL: QZ_SleepNotificationHandler() IORegisterForSystemPower failed.");
   714 
   691 
   715     if (power_connection == 0)
   692      rls = IONotificationPortGetRunLoopSource (thePortRef);
   716         NSLog
   693      CFRunLoopAddSource (CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode);
   717             (@"SDL: QZ_SleepNotificationHandler() IORegisterForSystemPower failed.");
   694      CFRelease (rls);
   718 
       
   719     rls = IONotificationPortGetRunLoopSource (thePortRef);
       
   720     CFRunLoopAddSource (CFRunLoopGetCurrent (), rls, kCFRunLoopDefaultMode);
       
   721     CFRelease (rls);
   695 }
   722 }
   696 
   723 
   697 
   724 
   698 /* Try to map Quartz mouse buttons to SDL's lingo... */
   725 /* Try to map Quartz mouse buttons to SDL's lingo... */
   699 static int QZ_OtherMouseButtonToSDL(int button)
   726 static int
   700 {
   727 QZ_OtherMouseButtonToSDL (int button)
   701     switch (button)
   728 {
   702     {
   729     switch (button) {
   703         case 0:
   730     case 0:
   704             return(SDL_BUTTON_LEFT);   /* 1 */
   731         return (SDL_BUTTON_LEFT);       /* 1 */
   705         case 1:
   732     case 1:
   706             return(SDL_BUTTON_RIGHT);  /* 3 */
   733         return (SDL_BUTTON_RIGHT);      /* 3 */
   707         case 2:
   734     case 2:
   708             return(SDL_BUTTON_MIDDLE); /* 2 */
   735         return (SDL_BUTTON_MIDDLE);     /* 2 */
   709     }
   736     }
   710 
   737 
   711     /* >= 3: skip 4 & 5, since those are the SDL mousewheel buttons. */
   738     /* >= 3: skip 4 & 5, since those are the SDL mousewheel buttons. */
   712     return(button + 3);
   739     return (button + 3);
   713 }
   740 }
   714 
   741 
   715 
   742 
   716 void QZ_PumpEvents (_THIS)
   743 void
       
   744 QZ_PumpEvents (_THIS)
   717 {
   745 {
   718     static Uint32 screensaverTicks = 0;
   746     static Uint32 screensaverTicks = 0;
   719     Uint32 nowTicks;
   747     Uint32 nowTicks;
   720     int firstMouseEvent;
   748     int firstMouseEvent;
   721     CGMouseDelta dx, dy;
   749     CGMouseDelta dx, dy;
   724     NSEvent *event;
   752     NSEvent *event;
   725     NSRect winRect;
   753     NSRect winRect;
   726     NSAutoreleasePool *pool;
   754     NSAutoreleasePool *pool;
   727 
   755 
   728     if (!SDL_VideoSurface)
   756     if (!SDL_VideoSurface)
   729         return;  /* don't do anything if there's no screen surface. */
   757         return;                 /* don't do anything if there's no screen surface. */
   730 
   758 
   731     /* Update activity every five seconds to prevent screensaver. --ryan. */
   759     /* Update activity every five seconds to prevent screensaver. --ryan. */
   732     nowTicks = SDL_GetTicks();
   760     nowTicks = SDL_GetTicks ();
   733     if ((nowTicks - screensaverTicks) > 5000)
   761     if ((nowTicks - screensaverTicks) > 5000) {
   734     {
   762         UpdateSystemActivity (UsrActivity);
   735         UpdateSystemActivity(UsrActivity);
       
   736         screensaverTicks = nowTicks;
   763         screensaverTicks = nowTicks;
   737     }
   764     }
   738 
   765 
   739     pool = [ [ NSAutoreleasePool alloc ] init ];
   766     pool =[[NSAutoreleasePool alloc] init];
   740     distantPast = [ NSDate distantPast ];
   767     distantPast =[NSDate distantPast];
   741 
   768 
   742     winRect = NSMakeRect (0, 0, SDL_VideoSurface->w, SDL_VideoSurface->h);
   769     winRect = NSMakeRect (0, 0, SDL_VideoSurface->w, SDL_VideoSurface->h);
   743     
   770 
   744     /* send the first mouse event in absolute coordinates */
   771     /* send the first mouse event in absolute coordinates */
   745     firstMouseEvent = 1;
   772     firstMouseEvent = 1;
   746     
   773 
   747     /* accumulate any additional mouse moved events into one SDL mouse event */
   774     /* accumulate any additional mouse moved events into one SDL mouse event */
   748     dx = 0;
   775     dx = 0;
   749     dy = 0;
   776     dy = 0;
   750     
   777 
   751     do {
   778     do {
   752     
   779 
   753         /* Poll for an event. This will not block */
   780         /* Poll for an event. This will not block */
   754         event = [ NSApp nextEventMatchingMask:NSAnyEventMask
   781       event =[NSApp nextEventMatchingMask: NSAnyEventMask untilDate: distantPast inMode: NSDefaultRunLoopMode dequeue:YES];
   755                                     untilDate:distantPast
       
   756                                     inMode: NSDefaultRunLoopMode dequeue:YES ];
       
   757         if (event != nil) {
   782         if (event != nil) {
   758 
   783 
   759             int button;
   784             int button;
   760             unsigned int type;
   785             unsigned int type;
   761             BOOL isInGameWin;
   786             BOOL isInGameWin;
   762             
   787 
   763             #define DO_MOUSE_DOWN(button) do {                                               \
   788 #define DO_MOUSE_DOWN(button) do {                                               \
   764                             if ( SDL_GetAppState() & SDL_APPMOUSEFOCUS ) {                   \
   789                             if ( SDL_GetAppState() & SDL_APPMOUSEFOCUS ) {                   \
   765                                 SDL_PrivateMouseButton (SDL_PRESSED, button, 0, 0);          \
   790                                 SDL_PrivateMouseButton (SDL_PRESSED, button, 0, 0);          \
   766                                 expect_mouse_up |= 1<<button;                                \
   791                                 expect_mouse_up |= 1<<button;                                \
   767                             }                                                                \
   792                             }                                                                \
   768                             [ NSApp sendEvent:event ];                                       \
   793                             [ NSApp sendEvent:event ];                                       \
   769             } while(0)
   794             } while(0)
   770             
   795 
   771             #define DO_MOUSE_UP(button) do {                                            \
   796 #define DO_MOUSE_UP(button) do {                                            \
   772                             if ( expect_mouse_up & (1<<button) ) {                      \
   797                             if ( expect_mouse_up & (1<<button) ) {                      \
   773                                 SDL_PrivateMouseButton (SDL_RELEASED, button, 0, 0);    \
   798                                 SDL_PrivateMouseButton (SDL_RELEASED, button, 0, 0);    \
   774                                 expect_mouse_up &= ~(1<<button);                        \
   799                                 expect_mouse_up &= ~(1<<button);                        \
   775                             }                                                           \
   800                             }                                                           \
   776                             [ NSApp sendEvent:event ];                                  \
   801                             [ NSApp sendEvent:event ];                                  \
   777             } while(0)
   802             } while(0)
   778             
   803 
   779             type = [ event type ];
   804             type =[event type];
   780             isInGameWin = QZ_IsMouseInWindow (this);
   805             isInGameWin = QZ_IsMouseInWindow (this);
   781 
   806 
   782             QZ_DoModifiers(this, [ event modifierFlags ] );
   807             QZ_DoModifiers (this,[event modifierFlags]);
   783 
   808 
   784             switch (type) {
   809             switch (type) {
   785                 case NSLeftMouseDown:
   810             case NSLeftMouseDown:
   786                     if ( SDL_getenv("SDL_HAS3BUTTONMOUSE") ) {
   811                 if (SDL_getenv ("SDL_HAS3BUTTONMOUSE")) {
       
   812                     DO_MOUSE_DOWN (SDL_BUTTON_LEFT);
       
   813                 } else {
       
   814                     if (NSCommandKeyMask & current_mods) {
       
   815                         last_virtual_button = SDL_BUTTON_RIGHT;
       
   816                         DO_MOUSE_DOWN (SDL_BUTTON_RIGHT);
       
   817                     } else if (NSAlternateKeyMask & current_mods) {
       
   818                         last_virtual_button = SDL_BUTTON_MIDDLE;
       
   819                         DO_MOUSE_DOWN (SDL_BUTTON_MIDDLE);
       
   820                     } else {
   787                         DO_MOUSE_DOWN (SDL_BUTTON_LEFT);
   821                         DO_MOUSE_DOWN (SDL_BUTTON_LEFT);
   788                     } else {
       
   789                         if ( NSCommandKeyMask & current_mods ) {
       
   790                             last_virtual_button = SDL_BUTTON_RIGHT;
       
   791                             DO_MOUSE_DOWN (SDL_BUTTON_RIGHT);
       
   792                         }
       
   793                         else if ( NSAlternateKeyMask & current_mods ) {
       
   794                             last_virtual_button = SDL_BUTTON_MIDDLE;
       
   795                             DO_MOUSE_DOWN (SDL_BUTTON_MIDDLE);
       
   796                         }
       
   797                         else {
       
   798                             DO_MOUSE_DOWN (SDL_BUTTON_LEFT);
       
   799                         }
       
   800                     }
   822                     }
   801                     break;
   823                 }
   802 
   824                 break;
   803                 case NSLeftMouseUp:
   825 
   804                     if ( last_virtual_button != 0 ) {
   826             case NSLeftMouseUp:
   805                         DO_MOUSE_UP (last_virtual_button);
   827                 if (last_virtual_button != 0) {
   806                         last_virtual_button = 0;
   828                     DO_MOUSE_UP (last_virtual_button);
       
   829                     last_virtual_button = 0;
       
   830                 } else {
       
   831                     DO_MOUSE_UP (SDL_BUTTON_LEFT);
       
   832                 }
       
   833                 break;
       
   834 
       
   835             case NSOtherMouseDown:
       
   836             case NSRightMouseDown:
       
   837                 button = QZ_OtherMouseButtonToSDL ([event buttonNumber]);
       
   838                 DO_MOUSE_DOWN (button);
       
   839                 break;
       
   840 
       
   841             case NSOtherMouseUp:
       
   842             case NSRightMouseUp:
       
   843                 button = QZ_OtherMouseButtonToSDL ([event buttonNumber]);
       
   844                 DO_MOUSE_UP (button);
       
   845                 break;
       
   846 
       
   847             case NSSystemDefined:
       
   848                 /*
       
   849                    Future: up to 32 "mouse" buttons can be handled.
       
   850                    if ([event subtype] == 7) {
       
   851                    unsigned int buttons;
       
   852                    buttons = [ event data2 ];
       
   853                  */
       
   854                 break;
       
   855             case NSLeftMouseDragged:
       
   856             case NSRightMouseDragged:
       
   857             case NSOtherMouseDragged:  /* usually middle mouse dragged */
       
   858             case NSMouseMoved:
       
   859                 if (grab_state == QZ_INVISIBLE_GRAB) {
       
   860 
       
   861                     /*
       
   862                        If input is grabbed+hidden, the cursor doesn't move,
       
   863                        so we have to call the lowlevel window server
       
   864                        function. This is less accurate but works OK.                         
       
   865                      */
       
   866                     CGMouseDelta dx1, dy1;
       
   867                     CGGetLastMouseDelta (&dx1, &dy1);
       
   868                     dx += dx1;
       
   869                     dy += dy1;
       
   870                 } else if (firstMouseEvent) {
       
   871 
       
   872                     /*
       
   873                        Get the first mouse event in a possible
       
   874                        sequence of mouse moved events. Since we
       
   875                        use absolute coordinates, this serves to
       
   876                        compensate any inaccuracy in deltas, and
       
   877                        provides the first known mouse position,
       
   878                        since everything after this uses deltas
       
   879                      */
       
   880                     NSPoint p;
       
   881                     QZ_GetMouseLocation (this, &p);
       
   882                     SDL_PrivateMouseMotion (0, 0, p.x, p.y);
       
   883                     firstMouseEvent = 0;
       
   884                 } else {
       
   885 
       
   886                     /*
       
   887                        Get the amount moved since the last drag or move event,
       
   888                        add it on for one big move event at the end.
       
   889                      */
       
   890                     dx +=[event deltaX];
       
   891                     dy +=[event deltaY];
       
   892                 }
       
   893 
       
   894                 /* 
       
   895                    Handle grab input+cursor visible by warping the cursor back
       
   896                    into the game window. This still generates a mouse moved event,
       
   897                    but not as a result of the warp (so it's in the right direction).
       
   898                  */
       
   899                 if (grab_state == QZ_VISIBLE_GRAB && !isInGameWin) {
       
   900 
       
   901                     NSPoint p;
       
   902                     QZ_GetMouseLocation (this, &p);
       
   903 
       
   904                     if (p.x < 0.0)
       
   905                         p.x = 0.0;
       
   906 
       
   907                     if (p.y < 0.0)
       
   908                         p.y = 0.0;
       
   909 
       
   910                     if (p.x >= winRect.size.width)
       
   911                         p.x = winRect.size.width - 1;
       
   912 
       
   913                     if (p.y >= winRect.size.height)
       
   914                         p.y = winRect.size.height - 1;
       
   915 
       
   916                     QZ_PrivateWarpCursor (this, p.x, p.y);
       
   917                 } else if (!isInGameWin
       
   918                            && (SDL_GetAppState () & SDL_APPMOUSEFOCUS)) {
       
   919 
       
   920                     SDL_PrivateAppActive (0, SDL_APPMOUSEFOCUS);
       
   921                     if (grab_state == QZ_INVISIBLE_GRAB)
       
   922                         /*The cursor has left the window even though it is
       
   923                            disassociated from the mouse (and therefore
       
   924                            shouldn't move): this can happen with Wacom
       
   925                            tablets, and it effectively breaks the grab, since
       
   926                            mouse down events now go to background
       
   927                            applications. The only possibility to avoid this
       
   928                            seems to be talking to the tablet driver
       
   929                            (AppleEvents) to constrain its mapped area to the
       
   930                            window, which may not be worth the effort. For
       
   931                            now, handle the condition more gracefully than
       
   932                            before by reassociating cursor and mouse until the
       
   933                            cursor enters the window again, making it obvious
       
   934                            to the user that the grab is broken. */
       
   935                         CGAssociateMouseAndMouseCursorPosition (1);
       
   936                     if (!cursor_should_be_visible)
       
   937                         QZ_ShowMouse (this);
       
   938                 } else if (isInGameWin
       
   939                            && (SDL_GetAppState () &
       
   940                                (SDL_APPMOUSEFOCUS | SDL_APPINPUTFOCUS)) ==
       
   941                            SDL_APPINPUTFOCUS) {
       
   942 
       
   943                     SDL_PrivateAppActive (1, SDL_APPMOUSEFOCUS);
       
   944                     if (!cursor_should_be_visible)
       
   945                         QZ_HideMouse (this);
       
   946                     if (grab_state == QZ_INVISIBLE_GRAB) {      /*see comment above */
       
   947                         QZ_PrivateWarpCursor (this,
       
   948                                               SDL_VideoSurface->w /
       
   949                                               2, SDL_VideoSurface->h / 2);
       
   950                         CGAssociateMouseAndMouseCursorPosition (0);
   807                     }
   951                     }
   808                     else {
   952                 }
   809                         DO_MOUSE_UP (SDL_BUTTON_LEFT);
   953                 break;
   810                     }
   954             case NSScrollWheel:
   811                     break;
   955                 if (isInGameWin) {
   812 
   956                     float dy, dx;
   813                 case NSOtherMouseDown:
   957                     Uint8 button;
   814                 case NSRightMouseDown:
   958                     dy =[event deltaY];
   815                     button = QZ_OtherMouseButtonToSDL([ event buttonNumber ]);
   959                     dx =[event deltaX];
   816                     DO_MOUSE_DOWN (button);
   960                     if (dy > 0.0 || dx > 0.0)   /* Scroll up */
   817                     break;
   961                         button = SDL_BUTTON_WHEELUP;
   818 
   962                     else        /* Scroll down */
   819                 case NSOtherMouseUp:
   963                         button = SDL_BUTTON_WHEELDOWN;
   820                 case NSRightMouseUp:
   964                     /* For now, wheel is sent as a quick down+up */
   821                     button = QZ_OtherMouseButtonToSDL([ event buttonNumber ]);
   965                     SDL_PrivateMouseButton (SDL_PRESSED, button, 0, 0);
   822                     DO_MOUSE_UP (button);
   966                     SDL_PrivateMouseButton (SDL_RELEASED, button, 0, 0);
   823                     break;
   967                 }
   824 
   968                 break;
   825                 case NSSystemDefined:
   969             case NSKeyUp:
   826                     /*
   970                 QZ_DoKey (this, SDL_RELEASED, event);
   827                         Future: up to 32 "mouse" buttons can be handled.
   971                 break;
   828                         if ([event subtype] == 7) {
   972             case NSKeyDown:
   829                             unsigned int buttons;
   973                 QZ_DoKey (this, SDL_PRESSED, event);
   830                             buttons = [ event data2 ];
   974                 break;
   831                     */
   975             case NSFlagsChanged:
   832                     break;
   976                 break;
   833                 case NSLeftMouseDragged:
   977                 /* case NSAppKitDefined: break; */
   834                 case NSRightMouseDragged:
   978                 /* case NSApplicationDefined: break; */
   835                 case NSOtherMouseDragged: /* usually middle mouse dragged */
   979                 /* case NSPeriodic: break; */
   836                 case NSMouseMoved:
   980                 /* case NSCursorUpdate: break; */
   837                     if ( grab_state == QZ_INVISIBLE_GRAB ) {
   981             default:
   838                 
   982               [NSApp sendEvent:event];
   839                         /*
       
   840                             If input is grabbed+hidden, the cursor doesn't move,
       
   841                             so we have to call the lowlevel window server
       
   842                             function. This is less accurate but works OK.                         
       
   843                         */
       
   844                         CGMouseDelta dx1, dy1;
       
   845                         CGGetLastMouseDelta (&dx1, &dy1);
       
   846                         dx += dx1;
       
   847                         dy += dy1;
       
   848                     }
       
   849                     else if (firstMouseEvent) {
       
   850                         
       
   851                         /*
       
   852                             Get the first mouse event in a possible
       
   853                             sequence of mouse moved events. Since we
       
   854                             use absolute coordinates, this serves to
       
   855                             compensate any inaccuracy in deltas, and
       
   856                             provides the first known mouse position,
       
   857                             since everything after this uses deltas
       
   858                         */
       
   859                         NSPoint p;
       
   860                         QZ_GetMouseLocation (this, &p);
       
   861                         SDL_PrivateMouseMotion (0, 0, p.x, p.y);
       
   862                         firstMouseEvent = 0;
       
   863                    }
       
   864                     else {
       
   865                     
       
   866                         /*
       
   867                             Get the amount moved since the last drag or move event,
       
   868                             add it on for one big move event at the end.
       
   869                         */
       
   870                         dx += [ event deltaX ];
       
   871                         dy += [ event deltaY ];
       
   872                     }
       
   873                     
       
   874                     /* 
       
   875                         Handle grab input+cursor visible by warping the cursor back
       
   876                         into the game window. This still generates a mouse moved event,
       
   877                         but not as a result of the warp (so it's in the right direction).
       
   878                     */
       
   879                     if ( grab_state == QZ_VISIBLE_GRAB &&
       
   880                          !isInGameWin ) {
       
   881                        
       
   882                         NSPoint p;
       
   883                         QZ_GetMouseLocation (this, &p);
       
   884 
       
   885                         if ( p.x < 0.0 ) 
       
   886                             p.x = 0.0;
       
   887                         
       
   888                         if ( p.y < 0.0 ) 
       
   889                             p.y = 0.0;
       
   890                         
       
   891                         if ( p.x >= winRect.size.width ) 
       
   892                             p.x = winRect.size.width-1;
       
   893                         
       
   894                         if ( p.y >= winRect.size.height ) 
       
   895                             p.y = winRect.size.height-1;
       
   896                         
       
   897                         QZ_PrivateWarpCursor (this, p.x, p.y);
       
   898                     }
       
   899                     else
       
   900                     if ( !isInGameWin && (SDL_GetAppState() & SDL_APPMOUSEFOCUS) ) {
       
   901                     
       
   902                         SDL_PrivateAppActive (0, SDL_APPMOUSEFOCUS);
       
   903                         if (grab_state == QZ_INVISIBLE_GRAB)
       
   904                             /*The cursor has left the window even though it is
       
   905                               disassociated from the mouse (and therefore
       
   906                               shouldn't move): this can happen with Wacom
       
   907                               tablets, and it effectively breaks the grab, since
       
   908                               mouse down events now go to background
       
   909                               applications. The only possibility to avoid this
       
   910                               seems to be talking to the tablet driver
       
   911                               (AppleEvents) to constrain its mapped area to the
       
   912                               window, which may not be worth the effort. For
       
   913                               now, handle the condition more gracefully than
       
   914                               before by reassociating cursor and mouse until the
       
   915                               cursor enters the window again, making it obvious
       
   916                               to the user that the grab is broken.*/
       
   917                             CGAssociateMouseAndMouseCursorPosition (1);
       
   918                         if (!cursor_should_be_visible)
       
   919                             QZ_ShowMouse (this);
       
   920                     }
       
   921                     else
       
   922                     if ( isInGameWin && (SDL_GetAppState() & (SDL_APPMOUSEFOCUS | SDL_APPINPUTFOCUS)) == SDL_APPINPUTFOCUS ) {
       
   923                     
       
   924                         SDL_PrivateAppActive (1, SDL_APPMOUSEFOCUS);
       
   925                         if (!cursor_should_be_visible)
       
   926                             QZ_HideMouse (this);
       
   927                         if (grab_state == QZ_INVISIBLE_GRAB) { /*see comment above*/
       
   928                             QZ_PrivateWarpCursor (this, SDL_VideoSurface->w / 2, SDL_VideoSurface->h / 2);
       
   929                             CGAssociateMouseAndMouseCursorPosition (0);
       
   930                         }
       
   931                     }
       
   932                     break;
       
   933                 case NSScrollWheel:
       
   934                     if ( isInGameWin ) {
       
   935                         float dy, dx;
       
   936                         Uint8 button;
       
   937                         dy = [ event deltaY ];
       
   938                         dx = [ event deltaX ];
       
   939                         if ( dy > 0.0 || dx > 0.0 ) /* Scroll up */
       
   940                             button = SDL_BUTTON_WHEELUP;
       
   941                         else /* Scroll down */
       
   942                             button = SDL_BUTTON_WHEELDOWN;
       
   943                         /* For now, wheel is sent as a quick down+up */
       
   944                         SDL_PrivateMouseButton (SDL_PRESSED, button, 0, 0);
       
   945                         SDL_PrivateMouseButton (SDL_RELEASED, button, 0, 0);
       
   946                     }
       
   947                     break;
       
   948                 case NSKeyUp:
       
   949                     QZ_DoKey (this, SDL_RELEASED, event);
       
   950                     break;
       
   951                 case NSKeyDown:
       
   952                     QZ_DoKey (this, SDL_PRESSED, event);
       
   953                     break;
       
   954                 case NSFlagsChanged:
       
   955                     break;
       
   956                     /* case NSAppKitDefined: break; */
       
   957                     /* case NSApplicationDefined: break; */
       
   958                     /* case NSPeriodic: break; */
       
   959                     /* case NSCursorUpdate: break; */
       
   960                 default:
       
   961                     [ NSApp sendEvent:event ];
       
   962             }
   983             }
   963         }
   984         }
   964     } while (event != nil);
   985     }
   965     
   986     while (event != nil);
       
   987 
   966     /* handle accumulated mouse moved events */
   988     /* handle accumulated mouse moved events */
   967     if (dx != 0 || dy != 0)
   989     if (dx != 0 || dy != 0)
   968         SDL_PrivateMouseMotion (0, 1, dx, dy);
   990         SDL_PrivateMouseMotion (0, 1, dx, dy);
   969     
   991 
   970     [ pool release ];
   992     [pool release];
   971 }
   993 }
   972 
   994 
   973 void QZ_UpdateMouse (_THIS)
   995 void
       
   996 QZ_UpdateMouse (_THIS)
   974 {
   997 {
   975     NSPoint p;
   998     NSPoint p;
   976     QZ_GetMouseLocation (this, &p);
   999     QZ_GetMouseLocation (this, &p);
   977     SDL_PrivateAppActive (QZ_IsMouseInWindow (this), SDL_APPMOUSEFOCUS);
  1000     SDL_PrivateAppActive (QZ_IsMouseInWindow (this), SDL_APPMOUSEFOCUS);
   978     SDL_PrivateMouseMotion (0, 0, p.x, p.y);
  1001     SDL_PrivateMouseMotion (0, 0, p.x, p.y);