SDL-1.2.14
[sdl_omap.git] / src / video / maccommon / SDL_macevents.c
1 /*
2     SDL - Simple DirectMedia Layer
3     Copyright (C) 1997-2009 Sam Lantinga
4
5     This library is free software; you can redistribute it and/or
6     modify it under the terms of the GNU Lesser General Public
7     License as published by the Free Software Foundation; either
8     version 2.1 of the License, or (at your option) any later version.
9
10     This library is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13     Lesser General Public License for more details.
14
15     You should have received a copy of the GNU Lesser General Public
16     License along with this library; if not, write to the Free Software
17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
19     Sam Lantinga
20     slouken@libsdl.org
21 */
22 #include "SDL_config.h"
23
24 #include <stdio.h>
25
26 #if defined(__APPLE__) && defined(__MACH__)
27 #include <Carbon/Carbon.h>
28 #elif TARGET_API_MAC_CARBON && (UNIVERSAL_INTERFACES_VERSION > 0x0335)
29 #include <Carbon.h>
30 #else
31 #include <Script.h>
32 #include <LowMem.h>
33 #include <Devices.h>
34 #include <DiskInit.h>
35 #include <ToolUtils.h>
36 #endif
37
38 #include "SDL_events.h"
39 #include "SDL_video.h"
40 #include "SDL_syswm.h"
41 #include "../../events/SDL_events_c.h"
42 #include "../../events/SDL_sysevents.h"
43 #include "../SDL_cursor_c.h"
44 #include "SDL_macevents_c.h"
45 #include "SDL_mackeys.h"
46 #include "SDL_macmouse_c.h"
47
48 /* Define this to be able to collapse SDL windows.
49 #define USE_APPEARANCE_MANAGER
50  */
51
52 /* Macintosh resource constants */
53 #define mApple  128                     /* Apple menu resource */
54 #define iAbout  1                       /* About menu item */
55
56 /* Functions to handle the About menu */
57 static void Mac_DoAppleMenu(_THIS, long item);
58
59 /* The translation table from a macintosh key scancode to a SDL keysym */
60 static SDLKey MAC_keymap[256];
61 static SDL_keysym *TranslateKey(int scancode, int modifiers,
62                                 SDL_keysym *keysym, int pressed);
63
64 /* Handle activation and deactivation  -- returns whether an event was posted */
65 static int Mac_HandleActivate(int activate)
66 {
67         if ( activate ) {
68                 /* Show the current SDL application cursor */
69                 SDL_SetCursor(NULL);
70
71                 /* put our mask back case it changed during context switch */
72                 SetEventMask(everyEvent & ~autoKeyMask);
73         } else {
74 #if TARGET_API_MAC_CARBON
75                 { Cursor cursor;
76                         SetCursor(GetQDGlobalsArrow(&cursor));
77                 }
78 #else
79                 SetCursor(&theQD->arrow);
80 #endif
81                 if ( ! Mac_cursor_showing ) {
82                         ShowCursor();
83                         Mac_cursor_showing = 1;
84                 }
85         }
86         return(SDL_PrivateAppActive(activate, SDL_APPINPUTFOCUS));
87 }
88
89 static void myGlobalToLocal(_THIS, Point *pt)
90 {
91         if ( SDL_VideoSurface && !(SDL_VideoSurface->flags&SDL_FULLSCREEN) ) {
92                 GrafPtr saveport;
93                 GetPort(&saveport);
94 #if TARGET_API_MAC_CARBON
95                 SetPort(GetWindowPort(SDL_Window));
96 #else
97                 SetPort(SDL_Window);
98 #endif
99                 GlobalToLocal(pt);
100                 SetPort(saveport);
101         }
102 }
103
104 /* The main MacOS event handler */
105 static int Mac_HandleEvents(_THIS, int wait4it)
106 {
107         static int mouse_button = 1;
108         int i;
109         EventRecord event;
110
111 #if TARGET_API_MAC_CARBON
112         /* There's no GetOSEvent() in the Carbon API. *sigh* */
113 #define cooperative_multitasking 1
114 #else
115         int cooperative_multitasking;
116         /* If we're running fullscreen, we can hog the MacOS events,
117            otherwise we had better play nicely with the other apps.
118         */
119         if ( this->screen && (this->screen->flags & SDL_FULLSCREEN) ) {
120                 cooperative_multitasking = 0;
121         } else {
122                 cooperative_multitasking = 1;
123         }
124 #endif
125
126         /* If we call WaitNextEvent(), MacOS will check other processes
127          * and allow them to run, and perform other high-level processing.
128          */
129         if ( cooperative_multitasking || wait4it ) {
130                 UInt32 wait_time;
131
132                 /* Are we polling or not? */
133                 if ( wait4it ) {
134                         wait_time = 2147483647;
135                 } else {
136                         wait_time = 0;
137                 }
138                 WaitNextEvent(everyEvent, &event, wait_time, nil);
139         } else {
140 #if ! TARGET_API_MAC_CARBON
141                 GetOSEvent(everyEvent, &event);
142 #endif
143         }
144
145 #if TARGET_API_MAC_CARBON
146         /* for some reason, event.where isn't set ? */
147         GetGlobalMouse ( &event.where );
148 #endif
149
150         /* Check for mouse motion */
151         if ( (event.where.h != last_where.h) ||
152              (event.where.v != last_where.v) ) {
153                 Point pt;
154                 pt = last_where = event.where;
155                 myGlobalToLocal(this, &pt);
156                 SDL_PrivateMouseMotion(0, 0, pt.h, pt.v);
157         }
158
159         /* Check the current state of the keyboard */
160         if ( SDL_GetAppState() & SDL_APPINPUTFOCUS ) {
161                 KeyMap keys;
162                 const Uint32 *keysptr = (Uint32 *) &keys;
163                 const Uint32 *last_keysptr = (Uint32 *) &last_keys;
164
165                 /* Check for special non-event keys */
166                 if ( event.modifiers != last_mods ) {
167                         static struct {
168                                 EventModifiers mask;
169                                 SDLKey key;
170                         } mods[] = {
171                                 { alphaLock,            SDLK_CAPSLOCK },
172 #if 0 /* These are handled below in the GetKeys() code */
173                                 { cmdKey,               SDLK_LMETA },
174                                 { shiftKey,             SDLK_LSHIFT },
175                                 { rightShiftKey,        SDLK_RSHIFT },
176                                 { optionKey,            SDLK_LALT },
177                                 { rightOptionKey,       SDLK_RALT },
178                                 { controlKey,           SDLK_LCTRL },
179                                 { rightControlKey,      SDLK_RCTRL },
180 #endif /* 0 */
181                                 { 0,                    0 }
182                         };
183                         SDL_keysym keysym;
184                         Uint8 mode;
185                         EventModifiers mod, mask;
186                 
187
188                         /* Set up the keyboard event */
189                         keysym.scancode = 0;
190                         keysym.sym = SDLK_UNKNOWN;
191                         keysym.mod = KMOD_NONE;
192                         keysym.unicode = 0;
193
194                         /* See what has changed, and generate events */
195                         mod = event.modifiers;
196                         for ( i=0; mods[i].mask; ++i ) {
197                                 mask = mods[i].mask;
198                                 if ( (mod&mask) != (last_mods&mask) ) {
199                                         keysym.sym = mods[i].key;
200                                         if ( (mod&mask) ||
201                                              (mods[i].key == SDLK_CAPSLOCK) ) {
202                                                 mode = SDL_PRESSED;
203                                         } else {
204                                                 mode = SDL_RELEASED;
205                                         }
206                                         SDL_PrivateKeyboard(mode, &keysym);
207                                 }
208                         }
209
210                         /* Save state for next time */
211                         last_mods = mod;
212                 }
213
214                 /* Check for normal event keys, but we have to scan the
215                    actual keyboard state because on Mac OS X a keydown event
216                    is immediately followed by a keyup event.
217                 */
218                 GetKeys(keys);
219                 if ( (keysptr[0] != last_keysptr[0]) ||
220                      (keysptr[1] != last_keysptr[1]) ||
221                      (keysptr[2] != last_keysptr[2]) ||
222                      (keysptr[3] != last_keysptr[3]) ) {
223                         SDL_keysym keysym;
224                         int old_bit, new_bit;
225
226 #ifdef DEBUG_KEYBOARD
227                         fprintf(sterr, "New keys: 0x%x 0x%x 0x%x 0x%x\n",
228                                 new_keys[0], new_keys[1],
229                                 new_keys[2], new_keys[3]);
230 #endif
231                         for ( i=0; i<128; ++i ) {
232                                 old_bit = (((Uint8 *)last_keys)[i/8]>>(i%8)) & 0x01;
233                                 new_bit = (((Uint8 *)keys)[i/8]>>(i%8)) & 0x01;
234                                 if ( old_bit != new_bit ) {
235                                         /* Post the keyboard event */
236 #ifdef DEBUG_KEYBOARD
237                                         fprintf(stderr,"Scancode: 0x%2.2X\n",i);
238 #endif
239                                         SDL_PrivateKeyboard(new_bit,
240                                             TranslateKey(i, event.modifiers,
241                                                          &keysym, new_bit));
242                                 }
243                         }
244
245                         /* Save state for next time */
246                         last_keys[0] = keys[0];
247                         last_keys[1] = keys[1];
248                         last_keys[2] = keys[2];
249                         last_keys[3] = keys[3];
250                 }
251         }
252
253         /* Handle normal events */
254         switch (event.what) {
255           case mouseDown: {
256                 WindowRef win;
257                 short area;
258                                 
259                 area = FindWindow(event.where, &win);
260                 /* Support switching between the SIOUX console
261                    and SDL_Window by clicking in the window.
262                  */
263                 if ( win && (win != FrontWindow()) ) {
264                         SelectWindow(win);
265                 } 
266                 switch (area) {
267                   case inMenuBar: /* Only the apple menu exists */
268                         Mac_DoAppleMenu(this, MenuSelect(event.where));
269                         HiliteMenu(0);
270                         break;
271                   case inDrag:
272 #if TARGET_API_MAC_CARBON
273                         DragWindow(win, event.where, NULL);
274 #else
275                         DragWindow(win, event.where, &theQD->screenBits.bounds);
276 #endif
277                         break;
278                   case inGoAway:
279                         if ( TrackGoAway(win, event.where) ) {
280                                 SDL_PrivateQuit();
281                         }
282                         break;
283                   case inContent:
284                         myGlobalToLocal(this, &event.where);
285                         /* Treat command-click as right mouse button */
286                         if ( event.modifiers & optionKey ) {
287                                 mouse_button = 2;
288                         } else if ( event.modifiers & cmdKey ) {
289                                 mouse_button = 3;
290                         } else {
291                                 mouse_button = 1;
292                         }
293                         SDL_PrivateMouseButton(SDL_PRESSED,
294                                 mouse_button, event.where.h, event.where.v);
295                         break;
296                   case inGrow: {
297                         int newSize;
298
299                         /* Don't allow resize if video mode isn't resizable */
300                         if ( ! SDL_PublicSurface ||
301                              ! (SDL_PublicSurface->flags & SDL_RESIZABLE) ) {
302                                 break;
303                         }
304 #if TARGET_API_MAC_CARBON
305                         newSize = GrowWindow(win, event.where, NULL);
306 #else
307                         newSize = GrowWindow(win, event.where, &theQD->screenBits.bounds);
308 #endif
309                         if ( newSize ) {
310 #if !TARGET_API_MAC_CARBON
311                                 EraseRect ( &theQD->screenBits.bounds );
312 #endif
313                                 SizeWindow ( win, LoWord (newSize), HiWord (newSize), 1 );
314                                 SDL_PrivateResize ( LoWord (newSize), HiWord (newSize) );
315                         }
316                         } break;
317                   case inZoomIn:
318                   case inZoomOut:
319                         if ( TrackBox (win, event.where, area )) {
320                                 Rect rect;
321 #if !TARGET_API_MAC_CARBON
322                                 EraseRect ( &theQD->screenBits.bounds );
323 #endif
324                                 ZoomWindow ( win, area, 0);
325                                 if ( area == inZoomIn ) {
326                                         GetWindowUserState(SDL_Window, &rect);
327                                 } else {
328                                         GetWindowStandardState(SDL_Window, &rect);
329                                 }
330                                 SDL_PrivateResize (rect.right-rect.left,
331                                                    rect.bottom-rect.top);
332                         }
333                         break;
334 #if TARGET_API_MAC_CARBON
335                   case inCollapseBox:
336                         if ( TrackBox (win, event.where, area )) {
337                                 if ( IsWindowCollapsable(win) ) {
338                                         CollapseWindow (win, !IsWindowCollapsed(win));
339                                         /* There should be something done like in inGrow case, but... */
340                                 }
341                         }
342                         break;
343 #endif /* TARGET_API_MAC_CARBON */
344                   case inSysWindow:
345 #if TARGET_API_MAC_CARBON
346                         /* Never happens in Carbon? */
347 #else
348                         SystemClick(&event, win);
349 #endif
350                         break;
351                   default:
352                         break;
353                 }
354           }
355           break;
356           case mouseUp: {
357                 myGlobalToLocal(this, &event.where);
358                 /* Release the mouse button we simulated in the last press.
359                    The drawback of this methos is we cannot press more than
360                    one button. However, this doesn't matter, since there is
361                    only a single logical mouse button, even if you have a
362                    multi-button mouse, this doesn't matter at all.
363                  */
364                 SDL_PrivateMouseButton(SDL_RELEASED,
365                         mouse_button, event.where.h, event.where.v);
366           }
367           break;
368 #if 0 /* Handled above the switch statement */
369           case keyDown: {
370                 SDL_keysym keysym;
371
372                 SDL_PrivateKeyboard(SDL_PRESSED,
373                         TranslateKey((event.message&keyCodeMask)>>8
374                                      event.modifiers, &keysym, 1));
375           }
376           break;
377           case keyUp: {
378                 SDL_keysym keysym;
379
380                 SDL_PrivateKeyboard(SDL_RELEASED,
381                         TranslateKey((event.message&keyCodeMask)>>8
382                                      event.modifiers, &keysym, 0));
383           }
384           break;
385 #endif
386           case updateEvt: {
387                 BeginUpdate(SDL_Window);
388         #if SDL_VIDEO_OPENGL
389                 if (SDL_VideoSurface->flags & SDL_OPENGL)
390                         SDL_GL_SwapBuffers();
391                 else
392         #endif
393                 if ( (SDL_VideoSurface->flags & SDL_HWSURFACE) ==
394                                                 SDL_SWSURFACE ) {
395                         SDL_UpdateRect(SDL_VideoSurface, 0, 0, 0, 0);
396                 }
397                 EndUpdate(SDL_Window);
398           }
399           /* If this was an update event for the SIOUX console, we return 0
400              in order to stop an endless series of updates being triggered.
401           */
402           if ( (WindowRef) event.message != SDL_Window ) {
403                 return 0;
404           }
405           break;
406           case activateEvt: {
407                 Mac_HandleActivate(!!(event.modifiers & activeFlag));
408           }
409           break;
410           case diskEvt: {
411 #if TARGET_API_MAC_CARBON
412                 /* What are we supposed to do? */;
413 #else
414                 if ( ((event.message>>16)&0xFFFF) != noErr ) {
415                         Point spot;
416                         SetPt(&spot, 0x0070, 0x0050);
417                         DIBadMount(spot, event.message);
418                 }
419 #endif
420           }
421           break;
422           case osEvt: {
423                 switch ((event.message>>24) & 0xFF) {
424 #if 0 /* Handled above the switch statement */
425                   case mouseMovedMessage: {
426                         myGlobalToLocal(this, &event.where);
427                         SDL_PrivateMouseMotion(0, 0,
428                                         event.where.h, event.where.v);
429                   }
430                   break;
431 #endif /* 0 */
432                   case suspendResumeMessage: {
433                         Mac_HandleActivate(!!(event.message & resumeFlag));
434                   }
435                   break;
436                 }
437           }
438           break;
439           default: {
440                 ;
441           }
442           break;
443         }
444         return (event.what != nullEvent);
445 }
446
447
448 void Mac_PumpEvents(_THIS)
449 {
450         /* Process pending MacOS events */
451         while ( Mac_HandleEvents(this, 0) ) {
452                 /* Loop and check again */;
453         }
454 }
455
456 void Mac_InitOSKeymap(_THIS)
457 {
458         const void *KCHRPtr;
459         UInt32 state;
460         UInt32 value;
461         int i;
462         int world = SDLK_WORLD_0;
463
464         /* Map the MAC keysyms */
465         for ( i=0; i<SDL_arraysize(MAC_keymap); ++i )
466                 MAC_keymap[i] = SDLK_UNKNOWN;
467
468         /* Defined MAC_* constants */
469         MAC_keymap[MK_ESCAPE] = SDLK_ESCAPE;
470         MAC_keymap[MK_F1] = SDLK_F1;
471         MAC_keymap[MK_F2] = SDLK_F2;
472         MAC_keymap[MK_F3] = SDLK_F3;
473         MAC_keymap[MK_F4] = SDLK_F4;
474         MAC_keymap[MK_F5] = SDLK_F5;
475         MAC_keymap[MK_F6] = SDLK_F6;
476         MAC_keymap[MK_F7] = SDLK_F7;
477         MAC_keymap[MK_F8] = SDLK_F8;
478         MAC_keymap[MK_F9] = SDLK_F9;
479         MAC_keymap[MK_F10] = SDLK_F10;
480         MAC_keymap[MK_F11] = SDLK_F11;
481         MAC_keymap[MK_F12] = SDLK_F12;
482         MAC_keymap[MK_PRINT] = SDLK_PRINT;
483         MAC_keymap[MK_SCROLLOCK] = SDLK_SCROLLOCK;
484         MAC_keymap[MK_PAUSE] = SDLK_PAUSE;
485         MAC_keymap[MK_POWER] = SDLK_POWER;
486         MAC_keymap[MK_BACKQUOTE] = SDLK_BACKQUOTE;
487         MAC_keymap[MK_1] = SDLK_1;
488         MAC_keymap[MK_2] = SDLK_2;
489         MAC_keymap[MK_3] = SDLK_3;
490         MAC_keymap[MK_4] = SDLK_4;
491         MAC_keymap[MK_5] = SDLK_5;
492         MAC_keymap[MK_6] = SDLK_6;
493         MAC_keymap[MK_7] = SDLK_7;
494         MAC_keymap[MK_8] = SDLK_8;
495         MAC_keymap[MK_9] = SDLK_9;
496         MAC_keymap[MK_0] = SDLK_0;
497         MAC_keymap[MK_MINUS] = SDLK_MINUS;
498         MAC_keymap[MK_EQUALS] = SDLK_EQUALS;
499         MAC_keymap[MK_BACKSPACE] = SDLK_BACKSPACE;
500         MAC_keymap[MK_INSERT] = SDLK_INSERT;
501         MAC_keymap[MK_HOME] = SDLK_HOME;
502         MAC_keymap[MK_PAGEUP] = SDLK_PAGEUP;
503         MAC_keymap[MK_NUMLOCK] = SDLK_NUMLOCK;
504         MAC_keymap[MK_KP_EQUALS] = SDLK_KP_EQUALS;
505         MAC_keymap[MK_KP_DIVIDE] = SDLK_KP_DIVIDE;
506         MAC_keymap[MK_KP_MULTIPLY] = SDLK_KP_MULTIPLY;
507         MAC_keymap[MK_TAB] = SDLK_TAB;
508         MAC_keymap[MK_q] = SDLK_q;
509         MAC_keymap[MK_w] = SDLK_w;
510         MAC_keymap[MK_e] = SDLK_e;
511         MAC_keymap[MK_r] = SDLK_r;
512         MAC_keymap[MK_t] = SDLK_t;
513         MAC_keymap[MK_y] = SDLK_y;
514         MAC_keymap[MK_u] = SDLK_u;
515         MAC_keymap[MK_i] = SDLK_i;
516         MAC_keymap[MK_o] = SDLK_o;
517         MAC_keymap[MK_p] = SDLK_p;
518         MAC_keymap[MK_LEFTBRACKET] = SDLK_LEFTBRACKET;
519         MAC_keymap[MK_RIGHTBRACKET] = SDLK_RIGHTBRACKET;
520         MAC_keymap[MK_BACKSLASH] = SDLK_BACKSLASH;
521         MAC_keymap[MK_DELETE] = SDLK_DELETE;
522         MAC_keymap[MK_END] = SDLK_END;
523         MAC_keymap[MK_PAGEDOWN] = SDLK_PAGEDOWN;
524         MAC_keymap[MK_KP7] = SDLK_KP7;
525         MAC_keymap[MK_KP8] = SDLK_KP8;
526         MAC_keymap[MK_KP9] = SDLK_KP9;
527         MAC_keymap[MK_KP_MINUS] = SDLK_KP_MINUS;
528         MAC_keymap[MK_CAPSLOCK] = SDLK_CAPSLOCK;
529         MAC_keymap[MK_a] = SDLK_a;
530         MAC_keymap[MK_s] = SDLK_s;
531         MAC_keymap[MK_d] = SDLK_d;
532         MAC_keymap[MK_f] = SDLK_f;
533         MAC_keymap[MK_g] = SDLK_g;
534         MAC_keymap[MK_h] = SDLK_h;
535         MAC_keymap[MK_j] = SDLK_j;
536         MAC_keymap[MK_k] = SDLK_k;
537         MAC_keymap[MK_l] = SDLK_l;
538         MAC_keymap[MK_SEMICOLON] = SDLK_SEMICOLON;
539         MAC_keymap[MK_QUOTE] = SDLK_QUOTE;
540         MAC_keymap[MK_RETURN] = SDLK_RETURN;
541         MAC_keymap[MK_KP4] = SDLK_KP4;
542         MAC_keymap[MK_KP5] = SDLK_KP5;
543         MAC_keymap[MK_KP6] = SDLK_KP6;
544         MAC_keymap[MK_KP_PLUS] = SDLK_KP_PLUS;
545         MAC_keymap[MK_LSHIFT] = SDLK_LSHIFT;
546         MAC_keymap[MK_z] = SDLK_z;
547         MAC_keymap[MK_x] = SDLK_x;
548         MAC_keymap[MK_c] = SDLK_c;
549         MAC_keymap[MK_v] = SDLK_v;
550         MAC_keymap[MK_b] = SDLK_b;
551         MAC_keymap[MK_n] = SDLK_n;
552         MAC_keymap[MK_m] = SDLK_m;
553         MAC_keymap[MK_COMMA] = SDLK_COMMA;
554         MAC_keymap[MK_PERIOD] = SDLK_PERIOD;
555         MAC_keymap[MK_SLASH] = SDLK_SLASH;
556 #if 0   /* These are the same as the left versions - use left by default */
557         MAC_keymap[MK_RSHIFT] = SDLK_RSHIFT;
558 #endif
559         MAC_keymap[MK_UP] = SDLK_UP;
560         MAC_keymap[MK_KP1] = SDLK_KP1;
561         MAC_keymap[MK_KP2] = SDLK_KP2;
562         MAC_keymap[MK_KP3] = SDLK_KP3;
563         MAC_keymap[MK_KP_ENTER] = SDLK_KP_ENTER;
564         MAC_keymap[MK_LCTRL] = SDLK_LCTRL;
565         MAC_keymap[MK_LALT] = SDLK_LALT;
566         MAC_keymap[MK_LMETA] = SDLK_LMETA;
567         MAC_keymap[MK_SPACE] = SDLK_SPACE;
568 #if 0   /* These are the same as the left versions - use left by default */
569         MAC_keymap[MK_RMETA] = SDLK_RMETA;
570         MAC_keymap[MK_RALT] = SDLK_RALT;
571         MAC_keymap[MK_RCTRL] = SDLK_RCTRL;
572 #endif
573         MAC_keymap[MK_LEFT] = SDLK_LEFT;
574         MAC_keymap[MK_DOWN] = SDLK_DOWN;
575         MAC_keymap[MK_RIGHT] = SDLK_RIGHT;
576         MAC_keymap[MK_KP0] = SDLK_KP0;
577         MAC_keymap[MK_KP_PERIOD] = SDLK_KP_PERIOD;
578
579 #if defined(__APPLE__) && defined(__MACH__)
580         /* Wierd, these keys are on my iBook under Mac OS X
581            Note that the left arrow keysym is the same as left ctrl!?
582          */
583         MAC_keymap[MK_IBOOK_ENTER] = SDLK_KP_ENTER;
584         MAC_keymap[MK_IBOOK_RIGHT] = SDLK_RIGHT;
585         MAC_keymap[MK_IBOOK_DOWN] = SDLK_DOWN;
586         MAC_keymap[MK_IBOOK_UP] = SDLK_UP;
587         MAC_keymap[MK_IBOOK_LEFT] = SDLK_LEFT;
588 #endif /* Mac OS X */
589
590         /* Up there we setup a static scancode->keysym map. However, it will not
591          * work very well on international keyboard. Hence we now query MacOS
592          * for its own keymap to adjust our own mapping table. However, this is
593          * bascially only useful for ascii char keys. This is also the reason
594          * why we keep the static table, too.
595          */
596         
597         /* Get a pointer to the systems cached KCHR */
598         KCHRPtr = (void *)GetScriptManagerVariable(smKCHRCache);
599         if (KCHRPtr)
600         {
601                 /* Loop over all 127 possible scan codes */
602                 for (i = 0; i < 0x7F; i++)
603                 {
604                         /* We pretend a clean start to begin with (i.e. no dead keys active */
605                         state = 0;
606                         
607                         /* Now translate the key code to a key value */
608                         value = KeyTranslate(KCHRPtr, i, &state) & 0xff;
609                         
610                         /* If the state become 0, it was a dead key. We need to translate again,
611                         passing in the new state, to get the actual key value */
612                         if (state != 0)
613                                 value = KeyTranslate(KCHRPtr, i, &state) & 0xff;
614                         
615                         /* Now we should have an ascii value, or 0. Try to figure out to which SDL symbol it maps */
616                         if (value >= 128)        /* Some non-ASCII char, map it to SDLK_WORLD_* */
617                                 MAC_keymap[i] = world++;
618                         else if (value >= 32)    /* non-control ASCII char */
619                                 MAC_keymap[i] = value;
620                 }
621         }
622         
623         /* The keypad codes are re-setup here, because the loop above cannot
624          * distinguish between a key on the keypad and a regular key. We maybe
625          * could get around this problem in another fashion: NSEvent's flags
626          * include a "NSNumericPadKeyMask" bit; we could check that and modify
627          * the symbol we return on the fly. However, this flag seems to exhibit
628          * some weird behaviour related to the num lock key
629          */
630         MAC_keymap[MK_KP0] = SDLK_KP0;
631         MAC_keymap[MK_KP1] = SDLK_KP1;
632         MAC_keymap[MK_KP2] = SDLK_KP2;
633         MAC_keymap[MK_KP3] = SDLK_KP3;
634         MAC_keymap[MK_KP4] = SDLK_KP4;
635         MAC_keymap[MK_KP5] = SDLK_KP5;
636         MAC_keymap[MK_KP6] = SDLK_KP6;
637         MAC_keymap[MK_KP7] = SDLK_KP7;
638         MAC_keymap[MK_KP8] = SDLK_KP8;
639         MAC_keymap[MK_KP9] = SDLK_KP9;
640         MAC_keymap[MK_KP_MINUS] = SDLK_KP_MINUS;
641         MAC_keymap[MK_KP_PLUS] = SDLK_KP_PLUS;
642         MAC_keymap[MK_KP_PERIOD] = SDLK_KP_PERIOD;
643         MAC_keymap[MK_KP_EQUALS] = SDLK_KP_EQUALS;
644         MAC_keymap[MK_KP_DIVIDE] = SDLK_KP_DIVIDE;
645         MAC_keymap[MK_KP_MULTIPLY] = SDLK_KP_MULTIPLY;
646         MAC_keymap[MK_KP_ENTER] = SDLK_KP_ENTER;
647 }
648
649 static SDL_keysym *TranslateKey(int scancode, int modifiers,
650                                 SDL_keysym *keysym, int pressed)
651 {
652         /* Set the keysym information */
653         keysym->scancode = scancode;
654         keysym->sym = MAC_keymap[keysym->scancode];
655         keysym->mod = KMOD_NONE;
656         keysym->unicode = 0;
657         if ( pressed && SDL_TranslateUNICODE ) {
658                 static unsigned long state = 0;
659                 static Ptr keymap = nil;
660                 Ptr new_keymap;
661
662                 /* Get the current keyboard map resource */
663                 new_keymap = (Ptr)GetScriptManagerVariable(smKCHRCache);
664                 if ( new_keymap != keymap ) {
665                         keymap = new_keymap;
666                         state = 0;
667                 }
668                 keysym->unicode = KeyTranslate(keymap,
669                         keysym->scancode|modifiers, &state) & 0xFFFF;
670         }
671         return(keysym);
672 }
673
674 void Mac_InitEvents(_THIS)
675 {
676         /* Create apple menu bar */
677         apple_menu = GetMenu(mApple);
678         if ( apple_menu != nil ) {
679                 AppendResMenu(apple_menu, 'DRVR');
680                 InsertMenu(apple_menu, 0);
681         }
682         DrawMenuBar();
683
684         /* Get rid of spurious events at startup */
685         FlushEvents(everyEvent, 0);
686         
687         /* Allow every event but keyrepeat */
688         SetEventMask(everyEvent & ~autoKeyMask);
689 }
690
691 void Mac_QuitEvents(_THIS)
692 {
693         ClearMenuBar();
694         if ( apple_menu != nil ) {
695                 ReleaseResource((char **)apple_menu);
696         }
697
698         /* Clean up pending events */
699         FlushEvents(everyEvent, 0);
700 }
701
702 static void Mac_DoAppleMenu(_THIS, long choice)
703 {
704 #if !TARGET_API_MAC_CARBON  /* No Apple menu in OS X */
705         short menu, item;
706
707         item = (choice&0xFFFF);
708         choice >>= 16;
709         menu = (choice&0xFFFF);
710         
711         switch (menu) {
712                 case mApple: {
713                         switch (item) {
714                                 case iAbout: {
715                                         /* Run the about box */;
716                                 }
717                                 break;
718                                 default: {
719                                         Str255 name;
720                                         
721                                         GetMenuItemText(apple_menu, item, name);
722                                         OpenDeskAcc(name);
723                                 }
724                                 break;
725                         }
726                 }
727                 break;
728                 default: {
729                         /* Ignore other menus */;
730                 }
731         }
732 #endif /* !TARGET_API_MAC_CARBON */
733 }
734
735 #if !TARGET_API_MAC_CARBON
736 /* Since we don't initialize QuickDraw, we need to get a pointer to qd */
737 struct QDGlobals *theQD = NULL;
738 #endif
739
740 /* Exported to the macmain code */
741 void SDL_InitQuickDraw(struct QDGlobals *the_qd)
742 {
743 #if !TARGET_API_MAC_CARBON
744         theQD = the_qd;
745 #endif
746 }