Mercurial > sdl-ios-xcode
annotate src/video/cybergfx/SDL_amigaevents.c @ 172:37e3ca9254c7
Date: Sat, 8 Sep 2001 04:42:23 +0200
From: Max Horn <max@quendi.de>
Subject: SDL/OSX: Joystick; Better key handling
I just finished implementing improved keyhandling for OS X (in fact
the code should be easily ported to the "normal" MacOS part of SDL, I
just had no chance yet). Works like this:
First init the mapping table statically like before. Them, it queries
the OS for the "official" key table, then iterates over all 127
scancode and gets the associates ascii code. It ignores everythng
below 32 (has to, as it would lead to many problems if we did not...
e.g. both ESC and NUM LOCk produce an ascii code 27 on my keyboard),
and all stuff above 127 is mapped to SDLK_WORLD_* simply in the order
it is encountered.
In addition, caps lock is now working, too.
The code work flawless for me, but since I only have one keyboard, I
may have not encountered some serious problem... but I am pretty
confident that it is better than the old code in most cases.
The joystick driver works fine for me, too. I think it can be added
to CVS already. It would simply be helpful if more people would test
it. Hm, I wonder if Maelstrom or GLTron has Joystick support? That
would be a wonderful test application :)
I also took the liberty of modifying some text files like BUGS,
README.CVS, README.MacOSX (which now contains the OS X docs I long
promised)
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Tue, 11 Sep 2001 19:00:18 +0000 |
parents | 75a95f82bc1f |
children | e8157fcb3114 |
rev | line source |
---|---|
0 | 1 /* |
2 SDL - Simple DirectMedia Layer | |
3 Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga | |
4 | |
5 This library is free software; you can redistribute it and/or | |
6 modify it under the terms of the GNU Library General Public | |
7 License as published by the Free Software Foundation; either | |
8 version 2 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 Library General Public License for more details. | |
14 | |
15 You should have received a copy of the GNU Library General Public | |
16 License along with this library; if not, write to the Free | |
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 | |
19 Sam Lantinga | |
20 slouken@devolution.com | |
21 */ | |
22 | |
23 #ifdef SAVE_RCSID | |
24 static char rcsid = | |
25 "@(#) $Id$"; | |
26 #endif | |
27 | |
28 /* Handle the event stream, converting Amiga events into SDL events */ | |
29 #include "SDL.h" | |
30 | |
31 #include "SDL_syswm.h" | |
32 #include "SDL_sysevents.h" | |
33 #include "SDL_sysvideo.h" | |
34 #include "SDL_events_c.h" | |
35 #include "SDL_cgxvideo.h" | |
36 #include "SDL_cgxmodes_c.h" | |
37 #include "SDL_cgximage_c.h" | |
38 #include "SDL_cgxwm_c.h" | |
39 #include "SDL_amigaevents_c.h" | |
40 | |
41 | |
42 /* The translation tables from an Amiga keysym to a SDL keysym */ | |
43 static SDLKey MISC_keymap[256]; | |
44 SDL_keysym *amiga_TranslateKey(int code, SDL_keysym *keysym); | |
45 struct IOStdReq *ConReq=NULL; | |
46 struct MsgPort *ConPort=NULL; | |
47 | |
48 /* Note: The X server buffers and accumulates mouse motion events, so | |
49 the motion event generated by the warp may not appear exactly as we | |
50 expect it to. We work around this (and improve performance) by only | |
51 warping the pointer when it reaches the edge, and then wait for it. | |
52 */ | |
53 #define MOUSE_FUDGE_FACTOR 8 | |
54 | |
55 #if 0 | |
56 | |
57 static inline int amiga_WarpedMotion(_THIS, struct IntuiMessage *m) | |
58 { | |
59 int w, h, i; | |
60 int deltax, deltay; | |
61 int posted; | |
62 | |
63 w = SDL_VideoSurface->w; | |
64 h = SDL_VideoSurface->h; | |
65 deltax = xevent->xmotion.x - mouse_last.x; | |
66 deltay = xevent->xmotion.y - mouse_last.y; | |
67 #ifdef DEBUG_MOTION | |
68 printf("Warped mouse motion: %d,%d\n", deltax, deltay); | |
69 #endif | |
70 mouse_last.x = xevent->xmotion.x; | |
71 mouse_last.y = xevent->xmotion.y; | |
72 posted = SDL_PrivateMouseMotion(0, 1, deltax, deltay); | |
73 | |
74 if ( (xevent->xmotion.x < MOUSE_FUDGE_FACTOR) || | |
75 (xevent->xmotion.x > (w-MOUSE_FUDGE_FACTOR)) || | |
76 (xevent->xmotion.y < MOUSE_FUDGE_FACTOR) || | |
77 (xevent->xmotion.y > (h-MOUSE_FUDGE_FACTOR)) ) { | |
78 /* Get the events that have accumulated */ | |
79 while ( XCheckTypedEvent(SDL_Display, MotionNotify, xevent) ) { | |
80 deltax = xevent->xmotion.x - mouse_last.x; | |
81 deltay = xevent->xmotion.y - mouse_last.y; | |
82 #ifdef DEBUG_MOTION | |
83 printf("Extra mouse motion: %d,%d\n", deltax, deltay); | |
84 #endif | |
85 mouse_last.x = xevent->xmotion.x; | |
86 mouse_last.y = xevent->xmotion.y; | |
87 posted += SDL_PrivateMouseMotion(0, 1, deltax, deltay); | |
88 } | |
89 mouse_last.x = w/2; | |
90 mouse_last.y = h/2; | |
91 XWarpPointer(SDL_Display, None, SDL_Window, 0, 0, 0, 0, | |
92 mouse_last.x, mouse_last.y); | |
93 for ( i=0; i<10; ++i ) { | |
94 XMaskEvent(SDL_Display, PointerMotionMask, xevent); | |
95 if ( (xevent->xmotion.x > | |
96 (mouse_last.x-MOUSE_FUDGE_FACTOR)) && | |
97 (xevent->xmotion.x < | |
98 (mouse_last.x+MOUSE_FUDGE_FACTOR)) && | |
99 (xevent->xmotion.y > | |
100 (mouse_last.y-MOUSE_FUDGE_FACTOR)) && | |
101 (xevent->xmotion.y < | |
102 (mouse_last.y+MOUSE_FUDGE_FACTOR)) ) { | |
103 break; | |
104 } | |
105 #ifdef DEBUG_XEVENTS | |
106 printf("Lost mouse motion: %d,%d\n", xevent->xmotion.x, xevent->xmotion.y); | |
107 #endif | |
108 } | |
109 #ifdef DEBUG_XEVENTS | |
110 if ( i == 10 ) { | |
111 printf("Warning: didn't detect mouse warp motion\n"); | |
112 } | |
113 #endif | |
114 } | |
115 return(posted); | |
116 } | |
117 | |
118 #endif | |
119 | |
120 static int amiga_GetButton(int code) | |
121 { | |
122 switch(code) | |
123 { | |
124 case IECODE_MBUTTON: | |
125 return SDL_BUTTON_MIDDLE; | |
126 case IECODE_RBUTTON: | |
127 return SDL_BUTTON_RIGHT; | |
128 default: | |
129 return SDL_BUTTON_LEFT; | |
130 } | |
131 } | |
132 | |
133 static int amiga_DispatchEvent(_THIS,struct IntuiMessage *msg) | |
134 { | |
135 int class=msg->Class,code=msg->Code; | |
136 int posted; | |
137 | |
138 posted = 0; | |
139 switch (class) { | |
140 /* Gaining mouse coverage? */ | |
141 case IDCMP_ACTIVEWINDOW: | |
142 posted = SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS); | |
143 break; | |
144 | |
145 /* Losing mouse coverage? */ | |
146 case IDCMP_INACTIVEWINDOW: | |
147 posted = SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS); | |
148 break; | |
149 #if 0 | |
150 /* Gaining input focus? */ | |
151 case IDCMP_ACTIVEWINDOW: | |
152 posted = SDL_PrivateAppActive(1, SDL_APPINPUTFOCUS); | |
153 | |
154 /* Queue entry into fullscreen mode */ | |
155 switch_waiting = 0x01 | SDL_FULLSCREEN; | |
156 switch_time = SDL_GetTicks() + 1500; | |
157 break; | |
158 | |
159 /* Losing input focus? */ | |
160 case IDCMP_INACTIVEWINDOW: | |
161 posted = SDL_PrivateAppActive(0, SDL_APPINPUTFOCUS); | |
162 | |
163 /* Queue leaving fullscreen mode */ | |
164 switch_waiting = 0x01; | |
165 switch_time = SDL_GetTicks() + 200; | |
166 break; | |
167 #endif | |
168 /* Mouse motion? */ | |
169 case IDCMP_MOUSEMOVE: | |
170 if ( SDL_VideoSurface ) { | |
171 posted = SDL_PrivateMouseMotion(0, 0, | |
172 msg->MouseX-SDL_Window->BorderLeft, | |
173 msg->MouseY-SDL_Window->BorderTop); | |
174 } | |
175 break; | |
176 | |
177 /* Mouse button press? */ | |
178 case IDCMP_MOUSEBUTTONS: | |
179 | |
180 if(!(code&IECODE_UP_PREFIX)) | |
181 { | |
182 posted = SDL_PrivateMouseButton(SDL_PRESSED, | |
183 amiga_GetButton(code), 0, 0); | |
184 } | |
185 /* Mouse button release? */ | |
186 else | |
187 { | |
188 code&=~IECODE_UP_PREFIX; | |
189 posted = SDL_PrivateMouseButton(SDL_RELEASED, | |
190 amiga_GetButton(code), 0, 0); | |
191 } | |
192 break; | |
193 | |
194 case IDCMP_RAWKEY: | |
195 | |
196 /* Key press? */ | |
197 | |
198 if( !(code&IECODE_UP_PREFIX) ) | |
199 { | |
200 SDL_keysym keysym; | |
201 posted = SDL_PrivateKeyboard(SDL_PRESSED, | |
202 amiga_TranslateKey(code, &keysym)); | |
203 } | |
204 else | |
205 { | |
206 /* Key release? */ | |
207 | |
208 SDL_keysym keysym; | |
209 code&=~IECODE_UP_PREFIX; | |
210 | |
211 /* Check to see if this is a repeated key */ | |
212 /* if ( ! X11_KeyRepeat(SDL_Display, &xevent) ) */ | |
213 | |
214 posted = SDL_PrivateKeyboard(SDL_RELEASED, | |
215 amiga_TranslateKey(code, &keysym)); | |
216 } | |
217 break; | |
218 /* Have we been iconified? */ | |
219 #if 0 | |
220 case UnmapNotify: { | |
221 #ifdef DEBUG_XEVENTS | |
222 printf("UnmapNotify!\n"); | |
223 #endif | |
224 posted=SDL_PrivateAppActive(0, SDL_APPACTIVE|SDL_APPINPUTFOCUS); | |
225 } | |
226 break; | |
227 | |
228 /* Have we been restored? */ | |
229 | |
230 case MapNotify: { | |
231 #ifdef DEBUG_XEVENTS | |
232 printf("MapNotify!\n"); | |
233 #endif | |
234 | |
235 posted = SDL_PrivateAppActive(1, SDL_APPACTIVE); | |
236 | |
237 if ( SDL_VideoSurface && | |
238 (SDL_VideoSurface->flags & SDL_FULLSCREEN) ) | |
239 { | |
240 CGX_EnterFullScreen(this); | |
241 } else { | |
242 X11_GrabInputNoLock(this, this->input_grab); | |
243 } | |
244 if ( SDL_VideoSurface ) { | |
245 CGX_RefreshDisplay(this); | |
246 } | |
247 } | |
248 break; | |
249 case Expose: | |
250 if ( SDL_VideoSurface && (xevent.xexpose.count == 0) ) { | |
251 CGX_RefreshDisplay(this); | |
252 } | |
253 break; | |
254 #endif | |
255 | |
256 /* Have we been resized? */ | |
257 case IDCMP_NEWSIZE: | |
21
75a95f82bc1f
Updated the Amiga OS port of SDL (thanks Gabriele)
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
258 SDL_PrivateResize(SDL_Window->Width-SDL_Window->BorderLeft-SDL_Window->BorderRight, |
75a95f82bc1f
Updated the Amiga OS port of SDL (thanks Gabriele)
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
259 SDL_Window->Height-SDL_Window->BorderTop-SDL_Window->BorderBottom); |
0 | 260 break; |
261 | |
262 /* Have we been requested to quit? */ | |
263 case IDCMP_CLOSEWINDOW: | |
264 posted = SDL_PrivateQuit(); | |
265 break; | |
266 | |
267 /* Do we need to refresh ourselves? */ | |
268 | |
269 default: { | |
270 /* Only post the event if we're watching for it */ | |
271 if ( SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE ) { | |
272 SDL_SysWMmsg wmmsg; | |
273 | |
274 SDL_VERSION(&wmmsg.version); | |
275 #if 0 | |
276 wmmsg.subsystem = SDL_SYSWM_CGX; | |
277 wmmsg.event.xevent = xevent; | |
278 #endif | |
279 posted = SDL_PrivateSysWMEvent(&wmmsg); | |
280 } | |
281 } | |
282 break; | |
283 } | |
284 ReplyMsg((struct Message *)msg); | |
285 | |
286 | |
287 return(posted); | |
288 } | |
289 | |
290 void amiga_PumpEvents(_THIS) | |
291 { | |
292 int pending; | |
293 struct IntuiMessage *m; | |
294 | |
295 /* Keep processing pending events */ | |
296 pending = 0; | |
297 while ( m=(struct IntuiMessage *)GetMsg(SDL_Window->UserPort) ) { | |
298 amiga_DispatchEvent(this,m); | |
299 ++pending; | |
300 } | |
301 } | |
302 | |
303 void amiga_InitKeymap(void) | |
304 { | |
305 int i; | |
306 | |
307 /* Map the miscellaneous keys */ | |
308 for ( i=0; i<SDL_TABLESIZE(MISC_keymap); ++i ) | |
309 MISC_keymap[i] = SDLK_UNKNOWN; | |
310 | |
311 /* These X keysyms have 0xFF as the high byte */ | |
312 MISC_keymap[65] = SDLK_BACKSPACE; | |
313 MISC_keymap[66] = SDLK_TAB; | |
314 MISC_keymap[70] = SDLK_CLEAR; | |
315 MISC_keymap[70] = SDLK_DELETE; | |
316 MISC_keymap[68] = SDLK_RETURN; | |
317 // MISC_keymap[XK_Pause&0xFF] = SDLK_PAUSE; | |
318 MISC_keymap[69] = SDLK_ESCAPE; | |
319 MISC_keymap[70] = SDLK_DELETE; | |
320 /* | |
321 SDLK_SPACE = 32, | |
322 SDLK_MINUS = 45, | |
323 SDLK_LESS = 60, | |
324 SDLK_COMMA = 44, | |
325 SDLK_PERIOD = 46, | |
326 SDLK_0 = 48, | |
327 SDLK_1 = 49, | |
328 SDLK_2 = 50, | |
329 SDLK_3 = 51, | |
330 SDLK_4 = 52, | |
331 SDLK_5 = 53, | |
332 SDLK_6 = 54, | |
333 SDLK_7 = 55, | |
334 SDLK_8 = 56, | |
335 SDLK_9 = 57, | |
336 SDLK_BACKQUOTE = 96, | |
337 SDLK_BACKSLASH = 92, | |
338 SDLK_a = 97, | |
339 SDLK_b = 98, | |
340 SDLK_c = 99, | |
341 SDLK_d = 100, | |
342 SDLK_e = 101, | |
343 SDLK_f = 102, | |
344 SDLK_g = 103, | |
345 SDLK_h = 104, | |
346 SDLK_i = 105, | |
347 SDLK_j = 106, | |
348 SDLK_k = 107, | |
349 SDLK_l = 108, | |
350 SDLK_m = 109, | |
351 SDLK_n = 110, | |
352 SDLK_o = 111, | |
353 SDLK_p = 112, | |
354 SDLK_q = 113, | |
355 SDLK_r = 114, | |
356 SDLK_s = 115, | |
357 SDLK_t = 116, | |
358 SDLK_u = 117, | |
359 SDLK_v = 118, | |
360 SDLK_w = 119, | |
361 SDLK_x = 120, | |
362 SDLK_y = 121, | |
363 SDLK_z = 122, | |
364 */ | |
365 MISC_keymap[15] = SDLK_KP0; /* Keypad 0-9 */ | |
366 MISC_keymap[29] = SDLK_KP1; | |
367 MISC_keymap[30] = SDLK_KP2; | |
368 MISC_keymap[31] = SDLK_KP3; | |
369 MISC_keymap[45] = SDLK_KP4; | |
370 MISC_keymap[46] = SDLK_KP5; | |
371 MISC_keymap[47] = SDLK_KP6; | |
372 MISC_keymap[61] = SDLK_KP7; | |
373 MISC_keymap[62] = SDLK_KP8; | |
374 MISC_keymap[63] = SDLK_KP9; | |
375 MISC_keymap[60] = SDLK_KP_PERIOD; | |
376 MISC_keymap[92] = SDLK_KP_DIVIDE; | |
377 MISC_keymap[93] = SDLK_KP_MULTIPLY; | |
378 MISC_keymap[74] = SDLK_KP_MINUS; | |
379 MISC_keymap[94] = SDLK_KP_PLUS; | |
380 MISC_keymap[67] = SDLK_KP_ENTER; | |
381 // MISC_keymap[XK_KP_Equal&0xFF] = SDLK_KP_EQUALS; | |
382 | |
383 MISC_keymap[76] = SDLK_UP; | |
384 MISC_keymap[77] = SDLK_DOWN; | |
385 MISC_keymap[78] = SDLK_RIGHT; | |
386 MISC_keymap[79] = SDLK_LEFT; | |
387 /* | |
388 MISC_keymap[XK_Insert&0xFF] = SDLK_INSERT; | |
389 MISC_keymap[XK_Home&0xFF] = SDLK_HOME; | |
390 MISC_keymap[XK_End&0xFF] = SDLK_END; | |
391 */ | |
392 // Mappati sulle parentesi del taastierino | |
393 MISC_keymap[90] = SDLK_PAGEUP; | |
394 MISC_keymap[91] = SDLK_PAGEDOWN; | |
395 | |
396 MISC_keymap[80] = SDLK_F1; | |
397 MISC_keymap[81] = SDLK_F2; | |
398 MISC_keymap[82] = SDLK_F3; | |
399 MISC_keymap[83] = SDLK_F4; | |
400 MISC_keymap[84] = SDLK_F5; | |
401 MISC_keymap[85] = SDLK_F6; | |
402 MISC_keymap[86] = SDLK_F7; | |
403 MISC_keymap[87] = SDLK_F8; | |
404 MISC_keymap[88] = SDLK_F9; | |
405 MISC_keymap[89] = SDLK_F10; | |
406 // MISC_keymap[XK_F11&0xFF] = SDLK_F11; | |
407 // MISC_keymap[XK_F12&0xFF] = SDLK_F12; | |
408 // MISC_keymap[XK_F13&0xFF] = SDLK_F13; | |
409 // MISC_keymap[XK_F14&0xFF] = SDLK_F14; | |
410 // MISC_keymap[XK_F15&0xFF] = SDLK_F15; | |
411 | |
412 // MISC_keymap[XK_Num_Lock&0xFF] = SDLK_NUMLOCK; | |
413 MISC_keymap[98] = SDLK_CAPSLOCK; | |
414 // MISC_keymap[XK_Scroll_Lock&0xFF] = SDLK_SCROLLOCK; | |
415 MISC_keymap[97] = SDLK_RSHIFT; | |
416 MISC_keymap[96] = SDLK_LSHIFT; | |
417 MISC_keymap[99] = SDLK_LCTRL; | |
418 MISC_keymap[99] = SDLK_LCTRL; | |
419 MISC_keymap[101] = SDLK_RALT; | |
420 MISC_keymap[100] = SDLK_LALT; | |
421 // MISC_keymap[XK_Meta_R&0xFF] = SDLK_RMETA; | |
422 // MISC_keymap[XK_Meta_L&0xFF] = SDLK_LMETA; | |
423 MISC_keymap[103] = SDLK_LSUPER; /* Left "Windows" */ | |
424 MISC_keymap[102] = SDLK_RSUPER; /* Right "Windows */ | |
425 | |
426 MISC_keymap[95] = SDLK_HELP; | |
427 } | |
428 | |
429 SDL_keysym *amiga_TranslateKey(int code, SDL_keysym *keysym) | |
430 { | |
431 static struct Library *ConsoleDevice=NULL; | |
432 | |
433 /* Get the raw keyboard scancode */ | |
434 keysym->scancode = code; | |
435 keysym->sym = MISC_keymap[code]; | |
436 | |
437 #ifdef DEBUG_KEYS | |
438 fprintf(stderr, "Translating key 0x%.4x (%d)\n", xsym, xkey->keycode); | |
439 #endif | |
440 /* Get the translated SDL virtual keysym */ | |
441 if ( keysym->sym==SDLK_UNKNOWN ) | |
442 { | |
443 if(!ConsoleDevice) | |
444 { | |
445 if(ConPort=CreateMsgPort()) | |
446 { | |
447 if(ConReq=CreateIORequest(ConPort,sizeof(struct IOStdReq))) | |
448 { | |
449 if(!OpenDevice("console.device",-1,(struct IORequest *)ConReq,0)) | |
450 ConsoleDevice=(struct Library *)ConReq->io_Device; | |
451 else | |
452 { | |
453 DeleteIORequest(ConReq); | |
454 ConReq=NULL; | |
455 } | |
456 } | |
457 else | |
458 { | |
459 DeleteMsgPort(ConPort); | |
460 ConPort=NULL; | |
461 } | |
462 } | |
463 } | |
464 | |
465 if(ConsoleDevice) | |
466 { | |
467 struct InputEvent event; | |
468 long actual; | |
469 char buffer[5]; | |
470 | |
471 event.ie_Qualifier=0; | |
472 event.ie_Class=IECLASS_RAWKEY; | |
473 event.ie_SubClass=0L; | |
474 event.ie_Code=code; | |
475 event.ie_X=event.ie_Y=0; | |
476 event.ie_EventAddress=NULL; | |
477 event.ie_NextEvent=NULL; | |
478 event.ie_Prev1DownCode=event.ie_Prev1DownQual=event.ie_Prev2DownCode=event.ie_Prev2DownQual=0; | |
479 | |
480 if( (actual=RawKeyConvert(&event,buffer,5,NULL))>=0) | |
481 { | |
482 if(actual>1) | |
483 { | |
484 D(bug("Warning (%ld) character conversion!\n",actual)); | |
485 } | |
486 else if(actual==1) | |
487 { | |
488 keysym->sym=*buffer; | |
489 D(bug("Converted rawcode %ld to <%lc>\n",code,*buffer)); | |
490 // Bufferizzo x le successive chiamate! | |
491 MISC_keymap[code]=*buffer; | |
492 } | |
493 } | |
494 } | |
495 | |
496 } | |
497 keysym->mod = KMOD_NONE; | |
498 | |
499 /* If UNICODE is on, get the UNICODE value for the key */ | |
500 keysym->unicode = 0; | |
501 if ( SDL_TranslateUNICODE ) { | |
502 #if 0 | |
503 static XComposeStatus state; | |
504 /* Until we handle the IM protocol, use XLookupString() */ | |
505 unsigned char keybuf[32]; | |
506 if ( XLookupString(xkey, (char *)keybuf, sizeof(keybuf), | |
507 NULL, &state) ) { | |
508 keysym->unicode = keybuf[0]; | |
509 } | |
510 #endif | |
511 } | |
512 return(keysym); | |
513 } | |
514 | |
515 void amiga_InitOSKeymap(_THIS) | |
516 { | |
517 amiga_InitKeymap(); | |
518 } |