|
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 */ |
|
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 } |