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 (at) libsdl.org 21 */ 22 #include "SDL_config.h" 23 24 /* Handle the event stream, converting Amiga events into SDL events */ 25 #include "SDL.h" 26 27 #include "SDL_syswm.h" 28 #include "../SDL_sysvideo.h" 29 #include "../../events/SDL_sysevents.h" 30 #include "../../events/SDL_events_c.h" 31 #include "SDL_cgxvideo.h" 32 #include "SDL_cgxmodes_c.h" 33 #include "SDL_cgximage_c.h" 34 #include "SDL_cgxwm_c.h" 35 #include "SDL_amigaevents_c.h" 36 37 38 /* The translation tables from an Amiga keysym to a SDL keysym */ 39 static SDLKey MISC_keymap[256]; 40 SDL_keysym *amiga_TranslateKey(int code, SDL_keysym *keysym); 41 struct IOStdReq *ConReq=NULL; 42 struct MsgPort *ConPort=NULL; 43 44 /* Note: The X server buffers and accumulates mouse motion events, so 45 the motion event generated by the warp may not appear exactly as we 46 expect it to. We work around this (and improve performance) by only 47 warping the pointer when it reaches the edge, and then wait for it. 48 */ 49 #define MOUSE_FUDGE_FACTOR 8 50 51 #if 0 52 53 static inline int amiga_WarpedMotion(_THIS, struct IntuiMessage *m) 54 { 55 int w, h, i; 56 int deltax, deltay; 57 int posted; 58 59 w = SDL_VideoSurface->w; 60 h = SDL_VideoSurface->h; 61 deltax = xevent->xmotion.x - mouse_last.x; 62 deltay = xevent->xmotion.y - mouse_last.y; 63 #ifdef DEBUG_MOTION 64 printf("Warped mouse motion: %d,%d\n", deltax, deltay); 65 #endif 66 mouse_last.x = xevent->xmotion.x; 67 mouse_last.y = xevent->xmotion.y; 68 posted = SDL_PrivateMouseMotion(0, 1, deltax, deltay); 69 70 if ( (xevent->xmotion.x < MOUSE_FUDGE_FACTOR) || 71 (xevent->xmotion.x > (w-MOUSE_FUDGE_FACTOR)) || 72 (xevent->xmotion.y < MOUSE_FUDGE_FACTOR) || 73 (xevent->xmotion.y > (h-MOUSE_FUDGE_FACTOR)) ) { 74 /* Get the events that have accumulated */ 75 while ( XCheckTypedEvent(SDL_Display, MotionNotify, xevent) ) { 76 deltax = xevent->xmotion.x - mouse_last.x; 77 deltay = xevent->xmotion.y - mouse_last.y; 78 #ifdef DEBUG_MOTION 79 printf("Extra mouse motion: %d,%d\n", deltax, deltay); 80 #endif 81 mouse_last.x = xevent->xmotion.x; 82 mouse_last.y = xevent->xmotion.y; 83 posted += SDL_PrivateMouseMotion(0, 1, deltax, deltay); 84 } 85 mouse_last.x = w/2; 86 mouse_last.y = h/2; 87 XWarpPointer(SDL_Display, None, SDL_Window, 0, 0, 0, 0, 88 mouse_last.x, mouse_last.y); 89 for ( i=0; i<10; ++i ) { 90 XMaskEvent(SDL_Display, PointerMotionMask, xevent); 91 if ( (xevent->xmotion.x > 92 (mouse_last.x-MOUSE_FUDGE_FACTOR)) && 93 (xevent->xmotion.x < 94 (mouse_last.x+MOUSE_FUDGE_FACTOR)) && 95 (xevent->xmotion.y > 96 (mouse_last.y-MOUSE_FUDGE_FACTOR)) && 97 (xevent->xmotion.y < 98 (mouse_last.y+MOUSE_FUDGE_FACTOR)) ) { 99 break; 100 } 101 #ifdef DEBUG_XEVENTS 102 printf("Lost mouse motion: %d,%d\n", xevent->xmotion.x, xevent->xmotion.y); 103 #endif 104 } 105 #ifdef DEBUG_XEVENTS 106 if ( i == 10 ) { 107 printf("Warning: didn't detect mouse warp motion\n"); 108 } 109 #endif 110 } 111 return(posted); 112 } 113 114 #endif 115 116 static int amiga_GetButton(int code) 117 { 118 switch(code) 119 { 120 case IECODE_MBUTTON: 121 return SDL_BUTTON_MIDDLE; 122 case IECODE_RBUTTON: 123 return SDL_BUTTON_RIGHT; 124 default: 125 return SDL_BUTTON_LEFT; 126 } 127 } 128 129 static int amiga_DispatchEvent(_THIS,struct IntuiMessage *msg) 130 { 131 int class=msg->Class,code=msg->Code; 132 int posted; 133 134 posted = 0; 135 switch (class) { 136 /* Gaining mouse coverage? */ 137 case IDCMP_ACTIVEWINDOW: 138 posted = SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS); 139 break; 140 141 /* Losing mouse coverage? */ 142 case IDCMP_INACTIVEWINDOW: 143 posted = SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS); 144 break; 145 #if 0 146 /* Gaining input focus? */ 147 case IDCMP_ACTIVEWINDOW: 148 posted = SDL_PrivateAppActive(1, SDL_APPINPUTFOCUS); 149 150 /* Queue entry into fullscreen mode */ 151 switch_waiting = 0x01 | SDL_FULLSCREEN; 152 switch_time = SDL_GetTicks() + 1500; 153 break; 154 155 /* Losing input focus? */ 156 case IDCMP_INACTIVEWINDOW: 157 posted = SDL_PrivateAppActive(0, SDL_APPINPUTFOCUS); 158 159 /* Queue leaving fullscreen mode */ 160 switch_waiting = 0x01; 161 switch_time = SDL_GetTicks() + 200; 162 break; 163 #endif 164 /* Mouse motion? */ 165 case IDCMP_MOUSEMOVE: 166 if ( SDL_VideoSurface ) { 167 posted = SDL_PrivateMouseMotion(0, 0, 168 msg->MouseX-SDL_Window->BorderLeft, 169 msg->MouseY-SDL_Window->BorderTop); 170 } 171 break; 172 173 /* Mouse button press? */ 174 case IDCMP_MOUSEBUTTONS: 175 176 if(!(code&IECODE_UP_PREFIX)) 177 { 178 posted = SDL_PrivateMouseButton(SDL_PRESSED, 179 amiga_GetButton(code), 0, 0); 180 } 181 /* Mouse button release? */ 182 else 183 { 184 code&=~IECODE_UP_PREFIX; 185 posted = SDL_PrivateMouseButton(SDL_RELEASED, 186 amiga_GetButton(code), 0, 0); 187 } 188 break; 189 190 case IDCMP_RAWKEY: 191 192 /* Key press? */ 193 194 if( !(code&IECODE_UP_PREFIX) ) 195 { 196 SDL_keysym keysym; 197 posted = SDL_PrivateKeyboard(SDL_PRESSED, 198 amiga_TranslateKey(code, &keysym)); 199 } 200 else 201 { 202 /* Key release? */ 203 204 SDL_keysym keysym; 205 code&=~IECODE_UP_PREFIX; 206 207 /* Check to see if this is a repeated key */ 208 /* if ( ! X11_KeyRepeat(SDL_Display, &xevent) ) */ 209 210 posted = SDL_PrivateKeyboard(SDL_RELEASED, 211 amiga_TranslateKey(code, &keysym)); 212 } 213 break; 214 /* Have we been iconified? */ 215 #if 0 216 case UnmapNotify: { 217 #ifdef DEBUG_XEVENTS 218 printf("UnmapNotify!\n"); 219 #endif 220 posted=SDL_PrivateAppActive(0, SDL_APPACTIVE|SDL_APPINPUTFOCUS); 221 } 222 break; 223 224 /* Have we been restored? */ 225 226 case MapNotify: { 227 #ifdef DEBUG_XEVENTS 228 printf("MapNotify!\n"); 229 #endif 230 231 posted = SDL_PrivateAppActive(1, SDL_APPACTIVE); 232 233 if ( SDL_VideoSurface && 234 (SDL_VideoSurface->flags & SDL_FULLSCREEN) ) 235 { 236 CGX_EnterFullScreen(this); 237 } else { 238 X11_GrabInputNoLock(this, this->input_grab); 239 } 240 if ( SDL_VideoSurface ) { 241 CGX_RefreshDisplay(this); 242 } 243 } 244 break; 245 case Expose: 246 if ( SDL_VideoSurface && (xevent.xexpose.count == 0) ) { 247 CGX_RefreshDisplay(this); 248 } 249 break; 250 #endif 251 252 /* Have we been resized? */ 253 case IDCMP_NEWSIZE: 254 SDL_PrivateResize(SDL_Window->Width-SDL_Window->BorderLeft-SDL_Window->BorderRight, 255 SDL_Window->Height-SDL_Window->BorderTop-SDL_Window->BorderBottom); 256 257 break; 258 259 /* Have we been requested to quit? */ 260 case IDCMP_CLOSEWINDOW: 261 posted = SDL_PrivateQuit(); 262 break; 263 264 /* Do we need to refresh ourselves? */ 265 266 default: { 267 /* Only post the event if we're watching for it */ 268 if ( SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE ) { 269 SDL_SysWMmsg wmmsg; 270 271 SDL_VERSION(&wmmsg.version); 272 #if 0 273 wmmsg.subsystem = SDL_SYSWM_CGX; 274 wmmsg.event.xevent = xevent; 275 #endif 276 posted = SDL_PrivateSysWMEvent(&wmmsg); 277 } 278 } 279 break; 280 } 281 ReplyMsg((struct Message *)msg); 282 283 284 return(posted); 285 } 286 287 void amiga_PumpEvents(_THIS) 288 { 289 int pending; 290 struct IntuiMessage *m; 291 292 /* Keep processing pending events */ 293 pending = 0; 294 while ( m=(struct IntuiMessage *)GetMsg(SDL_Window->UserPort) ) { 295 amiga_DispatchEvent(this,m); 296 ++pending; 297 } 298 } 299 300 void amiga_InitKeymap(void) 301 { 302 int i; 303 304 /* Map the miscellaneous keys */ 305 for ( i=0; i<SDL_arraysize(MISC_keymap); ++i ) 306 MISC_keymap[i] = SDLK_UNKNOWN; 307 308 /* These X keysyms have 0xFF as the high byte */ 309 MISC_keymap[65] = SDLK_BACKSPACE; 310 MISC_keymap[66] = SDLK_TAB; 311 MISC_keymap[70] = SDLK_CLEAR; 312 MISC_keymap[70] = SDLK_DELETE; 313 MISC_keymap[68] = SDLK_RETURN; 314 // MISC_keymap[XK_Pause&0xFF] = SDLK_PAUSE; 315 MISC_keymap[69] = SDLK_ESCAPE; 316 MISC_keymap[70] = SDLK_DELETE; 317 /* 318 SDLK_SPACE = 32, 319 SDLK_MINUS = 45, 320 SDLK_LESS = 60, 321 SDLK_COMMA = 44, 322 SDLK_PERIOD = 46, 323 SDLK_0 = 48, 324 SDLK_1 = 49, 325 SDLK_2 = 50, 326 SDLK_3 = 51, 327 SDLK_4 = 52, 328 SDLK_5 = 53, 329 SDLK_6 = 54, 330 SDLK_7 = 55, 331 SDLK_8 = 56, 332 SDLK_9 = 57, 333 SDLK_BACKQUOTE = 96, 334 SDLK_BACKSLASH = 92, 335 SDLK_a = 97, 336 SDLK_b = 98, 337 SDLK_c = 99, 338 SDLK_d = 100, 339 SDLK_e = 101, 340 SDLK_f = 102, 341 SDLK_g = 103, 342 SDLK_h = 104, 343 SDLK_i = 105, 344 SDLK_j = 106, 345 SDLK_k = 107, 346 SDLK_l = 108, 347 SDLK_m = 109, 348 SDLK_n = 110, 349 SDLK_o = 111, 350 SDLK_p = 112, 351 SDLK_q = 113, 352 SDLK_r = 114, 353 SDLK_s = 115, 354 SDLK_t = 116, 355 SDLK_u = 117, 356 SDLK_v = 118, 357 SDLK_w = 119, 358 SDLK_x = 120, 359 SDLK_y = 121, 360 SDLK_z = 122, 361 */ 362 MISC_keymap[15] = SDLK_KP0; /* Keypad 0-9 */ 363 MISC_keymap[29] = SDLK_KP1; 364 MISC_keymap[30] = SDLK_KP2; 365 MISC_keymap[31] = SDLK_KP3; 366 MISC_keymap[45] = SDLK_KP4; 367 MISC_keymap[46] = SDLK_KP5; 368 MISC_keymap[47] = SDLK_KP6; 369 MISC_keymap[61] = SDLK_KP7; 370 MISC_keymap[62] = SDLK_KP8; 371 MISC_keymap[63] = SDLK_KP9; 372 MISC_keymap[60] = SDLK_KP_PERIOD; 373 MISC_keymap[92] = SDLK_KP_DIVIDE; 374 MISC_keymap[93] = SDLK_KP_MULTIPLY; 375 MISC_keymap[74] = SDLK_KP_MINUS; 376 MISC_keymap[94] = SDLK_KP_PLUS; 377 MISC_keymap[67] = SDLK_KP_ENTER; 378 // MISC_keymap[XK_KP_Equal&0xFF] = SDLK_KP_EQUALS; 379 380 MISC_keymap[76] = SDLK_UP; 381 MISC_keymap[77] = SDLK_DOWN; 382 MISC_keymap[78] = SDLK_RIGHT; 383 MISC_keymap[79] = SDLK_LEFT; 384 /* 385 MISC_keymap[XK_Insert&0xFF] = SDLK_INSERT; 386 MISC_keymap[XK_Home&0xFF] = SDLK_HOME; 387 MISC_keymap[XK_End&0xFF] = SDLK_END; 388 */ 389 // Mappati sulle parentesi del taastierino 390 MISC_keymap[90] = SDLK_PAGEUP; 391 MISC_keymap[91] = SDLK_PAGEDOWN; 392 393 MISC_keymap[80] = SDLK_F1; 394 MISC_keymap[81] = SDLK_F2; 395 MISC_keymap[82] = SDLK_F3; 396 MISC_keymap[83] = SDLK_F4; 397 MISC_keymap[84] = SDLK_F5; 398 MISC_keymap[85] = SDLK_F6; 399 MISC_keymap[86] = SDLK_F7; 400 MISC_keymap[87] = SDLK_F8; 401 MISC_keymap[88] = SDLK_F9; 402 MISC_keymap[89] = SDLK_F10; 403 // MISC_keymap[XK_F11&0xFF] = SDLK_F11; 404 // MISC_keymap[XK_F12&0xFF] = SDLK_F12; 405 // MISC_keymap[XK_F13&0xFF] = SDLK_F13; 406 // MISC_keymap[XK_F14&0xFF] = SDLK_F14; 407 // MISC_keymap[XK_F15&0xFF] = SDLK_F15; 408 409 // MISC_keymap[XK_Num_Lock&0xFF] = SDLK_NUMLOCK; 410 MISC_keymap[98] = SDLK_CAPSLOCK; 411 // MISC_keymap[XK_Scroll_Lock&0xFF] = SDLK_SCROLLOCK; 412 MISC_keymap[97] = SDLK_RSHIFT; 413 MISC_keymap[96] = SDLK_LSHIFT; 414 MISC_keymap[99] = SDLK_LCTRL; 415 MISC_keymap[99] = SDLK_LCTRL; 416 MISC_keymap[101] = SDLK_RALT; 417 MISC_keymap[100] = SDLK_LALT; 418 // MISC_keymap[XK_Meta_R&0xFF] = SDLK_RMETA; 419 // MISC_keymap[XK_Meta_L&0xFF] = SDLK_LMETA; 420 MISC_keymap[103] = SDLK_LSUPER; /* Left "Windows" */ 421 MISC_keymap[102] = SDLK_RSUPER; /* Right "Windows */ 422 423 MISC_keymap[95] = SDLK_HELP; 424 } 425 426 SDL_keysym *amiga_TranslateKey(int code, SDL_keysym *keysym) 427 { 428 #ifdef STORMC4_WOS 429 static struct Library *KeymapBase=NULL; /* Linking failed in WOS version if ConsoleDevice was used */ 430 #else 431 static struct Library *ConsoleDevice=NULL; 432 #endif 433 434 /* Get the raw keyboard scancode */ 435 keysym->scancode = code; 436 keysym->sym = MISC_keymap[code]; 437 438 #ifdef DEBUG_KEYS 439 fprintf(stderr, "Translating key 0x%.4x (%d)\n", xsym, xkey->keycode); 440 #endif 441 /* Get the translated SDL virtual keysym */ 442 if ( keysym->sym==SDLK_UNKNOWN ) 443 { 444 #ifdef STORMC4_WOS 445 if(!KeymapBase) 446 #else 447 if(!ConsoleDevice) 448 #endif 449 { 450 #ifdef STORMC4_WOS 451 KeymapBase=OpenLibrary("keymap.library", 0L); 452 #else 453 if(ConPort=CreateMsgPort()) 454 { 455 if(ConReq=CreateIORequest(ConPort,sizeof(struct IOStdReq))) 456 { 457 if(!OpenDevice("console.device",-1,(struct IORequest *)ConReq,0)) 458 ConsoleDevice=(struct Library *)ConReq->io_Device; 459 else 460 { 461 DeleteIORequest(ConReq); 462 ConReq=NULL; 463 } 464 } 465 else 466 { 467 DeleteMsgPort(ConPort); 468 ConPort=NULL; 469 } 470 } 471 #endif 472 } 473 474 #ifdef STORMC4_WOS 475 if(KeymapBase) 476 #else 477 if(ConsoleDevice) 478 #endif 479 { 480 struct InputEvent event; 481 long actual; 482 char buffer[5]; 483 484 event.ie_Qualifier=0; 485 event.ie_Class=IECLASS_RAWKEY; 486 event.ie_SubClass=0L; 487 event.ie_Code=code; 488 event.ie_X=event.ie_Y=0; 489 event.ie_EventAddress=NULL; 490 event.ie_NextEvent=NULL; 491 event.ie_Prev1DownCode=event.ie_Prev1DownQual=event.ie_Prev2DownCode=event.ie_Prev2DownQual=0; 492 493 #ifdef STORMC4_WOS 494 if( (actual=MapRawKey(&event,buffer,5,NULL))>=0) 495 #else 496 if( (actual=RawKeyConvert(&event,buffer,5,NULL))>=0) 497 #endif 498 { 499 if(actual>1) 500 { 501 D(bug("Warning (%ld) character conversion!\n",actual)); 502 } 503 else if(actual==1) 504 { 505 keysym->sym=*buffer; 506 D(bug("Converted rawcode %ld to <%lc>\n",code,*buffer)); 507 // Bufferizzo x le successive chiamate! 508 MISC_keymap[code]=*buffer; 509 } 510 } 511 } 512 513 } 514 keysym->mod = KMOD_NONE; 515 516 /* If UNICODE is on, get the UNICODE value for the key */ 517 keysym->unicode = 0; 518 if ( SDL_TranslateUNICODE ) { 519 #if 0 520 static XComposeStatus state; 521 /* Until we handle the IM protocol, use XLookupString() */ 522 unsigned char keybuf[32]; 523 if ( XLookupString(xkey, (char *)keybuf, sizeof(keybuf), 524 NULL, &state) ) { 525 keysym->unicode = keybuf[0]; 526 } 527 #endif 528 } 529 return(keysym); 530 } 531 532 void amiga_InitOSKeymap(_THIS) 533 { 534 amiga_InitKeymap(); 535 } 536