1 /*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2006 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 */
Mac_HandleActivate(int activate)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
myGlobalToLocal(_THIS,Point * pt)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 */
Mac_HandleEvents(_THIS,int wait4it)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
Mac_PumpEvents(_THIS)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
Mac_InitOSKeymap(_THIS)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
TranslateKey(int scancode,int modifiers,SDL_keysym * keysym,int pressed)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
Mac_InitEvents(_THIS)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
Mac_QuitEvents(_THIS)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
Mac_DoAppleMenu(_THIS,long choice)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 */
SDL_InitQuickDraw(struct QDGlobals * the_qd)741 void SDL_InitQuickDraw(struct QDGlobals *the_qd)
742 {
743 #if !TARGET_API_MAC_CARBON
744 theQD = the_qd;
745 #endif
746 }
747