| 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 | /* Handle the event stream, converting photon events into SDL events */ |
| 25 | |
| 26 | #include <stdio.h> |
| 27 | #include <setjmp.h> |
| 28 | #include <sys/time.h> |
| 29 | |
| 30 | #include <Ph.h> |
| 31 | #include <photon/PkKeyDef.h> |
| 32 | |
| 33 | #include "SDL.h" |
| 34 | #include "SDL_syswm.h" |
| 35 | #include "../SDL_sysvideo.h" |
| 36 | #include "../../events/SDL_sysevents.h" |
| 37 | #include "../../events/SDL_events_c.h" |
| 38 | #include "SDL_ph_video.h" |
| 39 | #include "SDL_ph_modes_c.h" |
| 40 | #include "SDL_ph_image_c.h" |
| 41 | #include "SDL_ph_events_c.h" |
| 42 | #include "SDL_phyuv_c.h" |
| 43 | |
| 44 | /* The translation tables from a photon keysym to a SDL keysym */ |
| 45 | static SDLKey ODD_keymap[256]; |
| 46 | static SDLKey MISC_keymap[0xFF + 1]; |
| 47 | SDL_keysym *ph_TranslateKey(PhKeyEvent_t *key, SDL_keysym *keysym); |
| 48 | |
| 49 | /* Check to see if this is a repeated key. |
| 50 | (idea shamelessly lifted from GII -- thanks guys! :) */ |
| 51 | static int ph_WarpedMotion(_THIS, PhEvent_t *winEvent) |
| 52 | { |
| 53 | PhRect_t *rect = PhGetRects( winEvent ); |
| 54 | |
| 55 | int centre_x, centre_y; |
| 56 | int dx, dy; |
| 57 | short abs_x, abs_y; |
| 58 | int posted; |
| 59 | |
| 60 | centre_x = SDL_VideoSurface->w / 2; |
| 61 | centre_y = SDL_VideoSurface->h / 2; |
| 62 | |
| 63 | dx = rect->ul.x - centre_x; |
| 64 | dy = rect->ul.y - centre_y; |
| 65 | |
| 66 | posted = SDL_PrivateMouseMotion( 0, 1, dx, dy ); |
| 67 | |
| 68 | /* Move mouse cursor to middle of the window */ |
| 69 | PtGetAbsPosition( window, &abs_x, &abs_y ); |
| 70 | PhMoveCursorAbs(PhInputGroup(NULL), abs_x + centre_x, abs_y + centre_y); |
| 71 | |
| 72 | return (posted); |
| 73 | } |
| 74 | |
| 75 | /* Control which motion flags the window has set, a flags value of -1 sets |
| 76 | * MOTION_BUTTON and MOTION_NOBUTTON */ |
| 77 | |
| 78 | static void set_motion_sensitivity(_THIS, unsigned int flags) |
| 79 | { |
| 80 | int rid; |
| 81 | int fields = Ph_EV_PTR_MOTION_BUTTON | Ph_EV_PTR_MOTION_NOBUTTON; |
| 82 | PhRegion_t region; |
| 83 | |
| 84 | if( window ) |
| 85 | { |
| 86 | rid = PtWidgetRid(window); |
| 87 | if( rid != 0 && PhRegionQuery(rid, ®ion, NULL, NULL, 0) == 0 ) |
| 88 | { |
| 89 | region.events_sense=(region.events_sense & ~fields)|(flags & fields); |
| 90 | PhRegionChange(Ph_REGION_EV_SENSE, 0, ®ion, NULL, NULL); |
| 91 | } |
| 92 | } |
| 93 | } |
| 94 | |
| 95 | /* Convert the photon button state value to an SDL value */ |
| 96 | static Uint8 ph2sdl_mousebutton(unsigned short button_state) |
| 97 | { |
| 98 | Uint8 mouse_button = 0; |
| 99 | |
| 100 | if (button_state & Ph_BUTTON_SELECT) |
| 101 | mouse_button |= SDL_BUTTON_LEFT; |
| 102 | if (button_state & Ph_BUTTON_MENU) |
| 103 | mouse_button |= SDL_BUTTON_RIGHT; |
| 104 | if (button_state & Ph_BUTTON_ADJUST) |
| 105 | mouse_button |= SDL_BUTTON_MIDDLE; |
| 106 | |
| 107 | return (mouse_button); |
| 108 | } |
| 109 | |
| 110 | static int ph_DispatchEvent(_THIS) |
| 111 | { |
| 112 | int posted; |
| 113 | PhRect_t* rect; |
| 114 | PhPointerEvent_t* pointerEvent; |
| 115 | PhKeyEvent_t* keyEvent; |
| 116 | PhWindowEvent_t* winEvent; |
| 117 | int i, buttons; |
| 118 | SDL_Rect sdlrects[PH_SDL_MAX_RECTS]; |
| 119 | |
| 120 | posted = 0; |
| 121 | |
| 122 | switch (phevent->type) |
| 123 | { |
| 124 | case Ph_EV_BOUNDARY: |
| 125 | { |
| 126 | if (phevent->subtype == Ph_EV_PTR_ENTER) |
| 127 | { |
| 128 | posted = SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS); |
| 129 | } |
| 130 | else if (phevent->subtype ==Ph_EV_PTR_LEAVE) |
| 131 | { |
| 132 | posted = SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS); |
| 133 | } |
| 134 | } |
| 135 | break; |
| 136 | |
| 137 | case Ph_EV_PTR_MOTION_BUTTON: |
| 138 | case Ph_EV_PTR_MOTION_NOBUTTON: |
| 139 | { |
| 140 | if (SDL_VideoSurface) |
| 141 | { |
| 142 | pointerEvent = PhGetData(phevent); |
| 143 | rect = PhGetRects(phevent); |
| 144 | |
| 145 | if (mouse_relative) |
| 146 | { |
| 147 | posted = ph_WarpedMotion(this, phevent); |
| 148 | } |
| 149 | else |
| 150 | { |
| 151 | posted = SDL_PrivateMouseMotion(0, 0, rect->ul.x, rect->ul.y); |
| 152 | } |
| 153 | } |
| 154 | } |
| 155 | break; |
| 156 | |
| 157 | case Ph_EV_BUT_PRESS: |
| 158 | { |
| 159 | pointerEvent = PhGetData(phevent); |
| 160 | buttons = ph2sdl_mousebutton(pointerEvent->buttons); |
| 161 | if (buttons != 0) |
| 162 | { |
| 163 | posted = SDL_PrivateMouseButton(SDL_PRESSED, buttons, 0, 0); |
| 164 | } |
| 165 | } |
| 166 | break; |
| 167 | |
| 168 | case Ph_EV_BUT_RELEASE: |
| 169 | { |
| 170 | pointerEvent = PhGetData(phevent); |
| 171 | buttons = ph2sdl_mousebutton(pointerEvent->buttons); |
| 172 | if (phevent->subtype == Ph_EV_RELEASE_REAL && buttons != 0) |
| 173 | { |
| 174 | posted = SDL_PrivateMouseButton(SDL_RELEASED, buttons, 0, 0); |
| 175 | } |
| 176 | else if(phevent->subtype == Ph_EV_RELEASE_PHANTOM) |
| 177 | { |
| 178 | /* If the mouse is outside the window, |
| 179 | * only a phantom release event is sent, so |
| 180 | * check if the window doesn't have mouse focus. |
| 181 | * Not perfect, maybe checking the mouse button |
| 182 | * state for Ph_EV_BOUNDARY events would be |
| 183 | * better. */ |
| 184 | if ((SDL_GetAppState() & SDL_APPMOUSEFOCUS) == 0) |
| 185 | { |
| 186 | posted = SDL_PrivateMouseButton(SDL_RELEASED, buttons, 0, 0); |
| 187 | } |
| 188 | } |
| 189 | } |
| 190 | break; |
| 191 | |
| 192 | case Ph_EV_WM: |
| 193 | { |
| 194 | winEvent = PhGetData(phevent); |
| 195 | |
| 196 | /* losing focus */ |
| 197 | if ((winEvent->event_f==Ph_WM_FOCUS) && (winEvent->event_state==Ph_WM_EVSTATE_FOCUSLOST)) |
| 198 | { |
| 199 | set_motion_sensitivity(this, Ph_EV_PTR_MOTION_BUTTON); |
| 200 | posted = SDL_PrivateAppActive(0, SDL_APPINPUTFOCUS); |
| 201 | } |
| 202 | /* gaining focus */ |
| 203 | else if ((winEvent->event_f==Ph_WM_FOCUS) && (winEvent->event_state==Ph_WM_EVSTATE_FOCUS)) |
| 204 | { |
| 205 | set_motion_sensitivity(this, -1); |
| 206 | posted = SDL_PrivateAppActive(1, SDL_APPINPUTFOCUS); |
| 207 | } |
| 208 | /* request quit */ |
| 209 | else if (winEvent->event_f==Ph_WM_CLOSE) |
| 210 | { |
| 211 | posted = SDL_PrivateQuit(); |
| 212 | } |
| 213 | /* request hide/unhide */ |
| 214 | else if (winEvent->event_f==Ph_WM_HIDE) |
| 215 | { |
| 216 | if (currently_hided) |
| 217 | { |
| 218 | /* got unhide window event */ |
| 219 | /* TODO: restore application's palette if in palette mode */ |
| 220 | currently_hided=0; |
| 221 | } |
| 222 | else |
| 223 | { |
| 224 | /* got hide window event */ |
| 225 | /* TODO: restore original palette if in palette mode */ |
| 226 | currently_hided=1; |
| 227 | } |
| 228 | } |
| 229 | /* request to resize */ |
| 230 | else if (winEvent->event_f==Ph_WM_RESIZE) |
| 231 | { |
| 232 | currently_maximized=0; |
| 233 | #if (_NTO_VERSION < 630) |
| 234 | SDL_PrivateResize(winEvent->size.w+1, winEvent->size.h+1); |
| 235 | #else |
| 236 | /* QNX 6.3.0 have this bug fixed */ |
| 237 | SDL_PrivateResize(winEvent->size.w, winEvent->size.h); |
| 238 | #endif /* _NTO_VERSION */ |
| 239 | } |
| 240 | /* request to move */ |
| 241 | else if (winEvent->event_f==Ph_WM_MOVE) |
| 242 | { |
| 243 | if (current_overlay!=NULL) |
| 244 | { |
| 245 | int lockedstate=current_overlay->hwdata->locked; |
| 246 | int chromastate=current_overlay->hwdata->ischromakey; |
| 247 | int error; |
| 248 | SDL_Rect src, dst; |
| 249 | |
| 250 | current_overlay->hwdata->locked=1; |
| 251 | src.x = 0; |
| 252 | src.y = 0; |
| 253 | src.w = current_overlay->w; |
| 254 | src.y = current_overlay->h; |
| 255 | dst.x=current_overlay->hwdata->CurrentViewPort.pos.x; |
| 256 | dst.y=current_overlay->hwdata->CurrentViewPort.pos.y; |
| 257 | dst.w=current_overlay->hwdata->CurrentViewPort.size.w; |
| 258 | dst.h=current_overlay->hwdata->CurrentViewPort.size.h; |
| 259 | current_overlay->hwdata->ischromakey=0; |
| 260 | error=ph_DisplayYUVOverlay(this, current_overlay, &src, &dst); |
| 261 | if (!error) |
| 262 | { |
| 263 | current_overlay->hwdata->ischromakey=chromastate; |
| 264 | current_overlay->hwdata->locked=lockedstate; |
| 265 | } |
| 266 | } |
| 267 | } |
| 268 | /* maximize request */ |
| 269 | else if (winEvent->event_f==Ph_WM_MAX) |
| 270 | { |
| 271 | /* window already moved and resized here */ |
| 272 | currently_maximized=1; |
| 273 | } |
| 274 | /* restore request */ |
| 275 | else if (winEvent->event_f==Ph_WM_RESTORE) |
| 276 | { |
| 277 | /* window already moved and resized here */ |
| 278 | currently_maximized=0; |
| 279 | } |
| 280 | } |
| 281 | break; |
| 282 | |
| 283 | /* window has been resized, moved or removed */ |
| 284 | case Ph_EV_EXPOSE: |
| 285 | { |
| 286 | if (phevent->num_rects!=0) |
| 287 | { |
| 288 | int numrects; |
| 289 | |
| 290 | if (SDL_VideoSurface) |
| 291 | { |
| 292 | rect = PhGetRects(phevent); |
| 293 | if (phevent->num_rects>PH_SDL_MAX_RECTS) |
| 294 | { |
| 295 | /* sorry, buffers underrun, we'll update only first PH_SDL_MAX_RECTS rects */ |
| 296 | numrects=PH_SDL_MAX_RECTS; |
| 297 | } |
| 298 | |
| 299 | for(i=0; i<phevent->num_rects; i++) |
| 300 | { |
| 301 | sdlrects[i].x = rect[i].ul.x; |
| 302 | sdlrects[i].y = rect[i].ul.y; |
| 303 | sdlrects[i].w = rect[i].lr.x - rect[i].ul.x + 1; |
| 304 | sdlrects[i].h = rect[i].lr.y - rect[i].ul.y + 1; |
| 305 | } |
| 306 | |
| 307 | this->UpdateRects(this, phevent->num_rects, sdlrects); |
| 308 | |
| 309 | if (current_overlay!=NULL) |
| 310 | { |
| 311 | int lockedstate=current_overlay->hwdata->locked; |
| 312 | int error; |
| 313 | SDL_Rect src, dst; |
| 314 | |
| 315 | current_overlay->hwdata->locked=1; |
| 316 | src.x = 0; |
| 317 | src.y = 0; |
| 318 | src.w = current_overlay->w; |
| 319 | src.y = current_overlay->h; |
| 320 | dst.x=current_overlay->hwdata->CurrentViewPort.pos.x; |
| 321 | dst.y=current_overlay->hwdata->CurrentViewPort.pos.y; |
| 322 | dst.w=current_overlay->hwdata->CurrentViewPort.size.w; |
| 323 | dst.h=current_overlay->hwdata->CurrentViewPort.size.h; |
| 324 | current_overlay->hwdata->forcedredraw=1; |
| 325 | error=ph_DisplayYUVOverlay(this, current_overlay, &src, &dst); |
| 326 | if (!error) |
| 327 | { |
| 328 | current_overlay->hwdata->forcedredraw=0; |
| 329 | current_overlay->hwdata->locked=lockedstate; |
| 330 | } |
| 331 | } |
| 332 | } |
| 333 | } |
| 334 | } |
| 335 | break; |
| 336 | |
| 337 | case Ph_EV_KEY: |
| 338 | { |
| 339 | SDL_keysym keysym; |
| 340 | |
| 341 | posted = 0; |
| 342 | |
| 343 | keyEvent = PhGetData(phevent); |
| 344 | |
| 345 | if (Pk_KF_Key_Down & keyEvent->key_flags) |
| 346 | { |
| 347 | /* split the wheel events from real key events */ |
| 348 | if ((keyEvent->key_cap==Pk_Up) && (keyEvent->key_scan==0) && ((keyEvent->key_flags & Pk_KF_Scan_Valid)==Pk_KF_Scan_Valid)) |
| 349 | { |
| 350 | posted = SDL_PrivateMouseButton(SDL_PRESSED, SDL_BUTTON_WHEELUP, 0, 0); |
| 351 | break; |
| 352 | } |
| 353 | if ((keyEvent->key_cap==Pk_Down) && (keyEvent->key_scan==0) && ((keyEvent->key_flags & Pk_KF_Scan_Valid)==Pk_KF_Scan_Valid)) |
| 354 | { |
| 355 | posted = SDL_PrivateMouseButton(SDL_PRESSED, SDL_BUTTON_WHEELDOWN, 0, 0); |
| 356 | break; |
| 357 | } |
| 358 | posted = SDL_PrivateKeyboard(SDL_PRESSED, ph_TranslateKey(keyEvent, &keysym)); |
| 359 | } |
| 360 | else /* must be key release */ |
| 361 | { |
| 362 | /* split the wheel events from real key events */ |
| 363 | if ((keyEvent->key_cap==Pk_Up) && (keyEvent->key_scan==0) && ((keyEvent->key_flags & Pk_KF_Scan_Valid)==Pk_KF_Scan_Valid)) |
| 364 | { |
| 365 | posted = SDL_PrivateMouseButton(SDL_RELEASED, SDL_BUTTON_WHEELUP, 0, 0); |
| 366 | break; |
| 367 | } |
| 368 | if ((keyEvent->key_cap==Pk_Down) && (keyEvent->key_scan==0) && ((keyEvent->key_flags & Pk_KF_Scan_Valid)==Pk_KF_Scan_Valid)) |
| 369 | { |
| 370 | posted = SDL_PrivateMouseButton(SDL_RELEASED, SDL_BUTTON_WHEELDOWN, 0, 0); |
| 371 | break; |
| 372 | } |
| 373 | posted = SDL_PrivateKeyboard(SDL_RELEASED, ph_TranslateKey( keyEvent, &keysym)); |
| 374 | } |
| 375 | } |
| 376 | break; |
| 377 | |
| 378 | case Ph_EV_INFO: |
| 379 | { |
| 380 | if (phevent->subtype==Ph_OFFSCREEN_INVALID) |
| 381 | { |
| 382 | unsigned long* EvInfoData; |
| 383 | |
| 384 | EvInfoData=(unsigned long*)PhGetData(phevent); |
| 385 | |
| 386 | switch (*EvInfoData) |
| 387 | { |
| 388 | case Pg_VIDEO_MODE_SWITCHED: |
| 389 | { |
| 390 | } |
| 391 | break; |
| 392 | case Pg_ENTERED_DIRECT: |
| 393 | { |
| 394 | } |
| 395 | break; |
| 396 | case Pg_EXITED_DIRECT: |
| 397 | { |
| 398 | } |
| 399 | break; |
| 400 | case Pg_DRIVER_STARTED: |
| 401 | { |
| 402 | } |
| 403 | break; |
| 404 | } |
| 405 | } |
| 406 | } |
| 407 | break; |
| 408 | } |
| 409 | |
| 410 | return(posted); |
| 411 | } |
| 412 | |
| 413 | /* perform a blocking read if no events available */ |
| 414 | int ph_Pending(_THIS) |
| 415 | { |
| 416 | /* Flush the display connection and look to see if events are queued */ |
| 417 | PgFlush(); |
| 418 | |
| 419 | while (1) |
| 420 | { |
| 421 | switch(PhEventPeek(phevent, EVENT_SIZE)) |
| 422 | { |
| 423 | case Ph_EVENT_MSG: |
| 424 | return 1; |
| 425 | case -1: |
| 426 | SDL_SetError("ph_Pending(): PhEventNext failed.\n"); |
| 427 | return 0; |
| 428 | default: |
| 429 | return 0; |
| 430 | } |
| 431 | } |
| 432 | |
| 433 | /* Oh well, nothing is ready .. */ |
| 434 | return(0); |
| 435 | } |
| 436 | |
| 437 | void ph_PumpEvents(_THIS) |
| 438 | { |
| 439 | /* Flush the display connection and look to see if events are queued */ |
| 440 | PgFlush(); |
| 441 | |
| 442 | while (ph_Pending(this)) |
| 443 | { |
| 444 | PtEventHandler(phevent); |
| 445 | ph_DispatchEvent(this); |
| 446 | } |
| 447 | } |
| 448 | |
| 449 | void ph_InitKeymap(void) |
| 450 | { |
| 451 | int i; |
| 452 | |
| 453 | /* Odd keys used in international keyboards */ |
| 454 | for (i=0; i<SDL_arraysize(ODD_keymap); ++i) |
| 455 | { |
| 456 | ODD_keymap[i] = SDLK_UNKNOWN; |
| 457 | } |
| 458 | |
| 459 | /* Map the miscellaneous keys */ |
| 460 | for (i=0; i<SDL_arraysize(MISC_keymap); ++i) |
| 461 | { |
| 462 | MISC_keymap[i] = SDLK_UNKNOWN; |
| 463 | } |
| 464 | |
| 465 | MISC_keymap[Pk_BackSpace&0xFF] = SDLK_BACKSPACE; |
| 466 | MISC_keymap[Pk_Tab&0xFF] = SDLK_TAB; |
| 467 | MISC_keymap[Pk_Clear&0xFF] = SDLK_CLEAR; |
| 468 | MISC_keymap[Pk_Return&0xFF] = SDLK_RETURN; |
| 469 | MISC_keymap[Pk_Pause&0xFF] = SDLK_PAUSE; |
| 470 | MISC_keymap[Pk_Escape&0xFF] = SDLK_ESCAPE; |
| 471 | MISC_keymap[Pk_Delete&0xFF] = SDLK_DELETE; |
| 472 | |
| 473 | MISC_keymap[Pk_KP_0&0xFF] = SDLK_KP0; |
| 474 | MISC_keymap[Pk_KP_1&0xFF] = SDLK_KP1; |
| 475 | MISC_keymap[Pk_KP_2&0xFF] = SDLK_KP2; |
| 476 | MISC_keymap[Pk_KP_3&0xFF] = SDLK_KP3; |
| 477 | MISC_keymap[Pk_KP_4&0xFF] = SDLK_KP4; |
| 478 | MISC_keymap[Pk_KP_5&0xFF] = SDLK_KP5; |
| 479 | MISC_keymap[Pk_KP_6&0xFF] = SDLK_KP6; |
| 480 | MISC_keymap[Pk_KP_7&0xFF] = SDLK_KP7; |
| 481 | MISC_keymap[Pk_KP_8&0xFF] = SDLK_KP8; |
| 482 | MISC_keymap[Pk_KP_9&0xFF] = SDLK_KP9; |
| 483 | |
| 484 | MISC_keymap[Pk_KP_Decimal&0xFF] = SDLK_KP_PERIOD; |
| 485 | MISC_keymap[Pk_KP_Divide&0xFF] = SDLK_KP_DIVIDE; |
| 486 | MISC_keymap[Pk_KP_Multiply&0xFF] = SDLK_KP_MULTIPLY; |
| 487 | MISC_keymap[Pk_KP_Subtract&0xFF] = SDLK_KP_MINUS; |
| 488 | MISC_keymap[Pk_KP_Add&0xFF] = SDLK_KP_PLUS; |
| 489 | MISC_keymap[Pk_KP_Enter&0xFF] = SDLK_KP_ENTER; |
| 490 | MISC_keymap[Pk_KP_Equal&0xFF] = SDLK_KP_EQUALS; |
| 491 | |
| 492 | MISC_keymap[Pk_Up&0xFF] = SDLK_UP; |
| 493 | MISC_keymap[Pk_Down&0xFF] = SDLK_DOWN; |
| 494 | MISC_keymap[Pk_Right&0xFF] = SDLK_RIGHT; |
| 495 | MISC_keymap[Pk_Left&0xFF] = SDLK_LEFT; |
| 496 | MISC_keymap[Pk_Insert&0xFF] = SDLK_INSERT; |
| 497 | MISC_keymap[Pk_Home&0xFF] = SDLK_HOME; |
| 498 | MISC_keymap[Pk_End&0xFF] = SDLK_END; |
| 499 | MISC_keymap[Pk_Pg_Up&0xFF] = SDLK_PAGEUP; |
| 500 | MISC_keymap[Pk_Pg_Down&0xFF] = SDLK_PAGEDOWN; |
| 501 | |
| 502 | MISC_keymap[Pk_F1&0xFF] = SDLK_F1; |
| 503 | MISC_keymap[Pk_F2&0xFF] = SDLK_F2; |
| 504 | MISC_keymap[Pk_F3&0xFF] = SDLK_F3; |
| 505 | MISC_keymap[Pk_F4&0xFF] = SDLK_F4; |
| 506 | MISC_keymap[Pk_F5&0xFF] = SDLK_F5; |
| 507 | MISC_keymap[Pk_F6&0xFF] = SDLK_F6; |
| 508 | MISC_keymap[Pk_F7&0xFF] = SDLK_F7; |
| 509 | MISC_keymap[Pk_F8&0xFF] = SDLK_F8; |
| 510 | MISC_keymap[Pk_F9&0xFF] = SDLK_F9; |
| 511 | MISC_keymap[Pk_F10&0xFF] = SDLK_F10; |
| 512 | MISC_keymap[Pk_F11&0xFF] = SDLK_F11; |
| 513 | MISC_keymap[Pk_F12&0xFF] = SDLK_F12; |
| 514 | MISC_keymap[Pk_F13&0xFF] = SDLK_F13; |
| 515 | MISC_keymap[Pk_F14&0xFF] = SDLK_F14; |
| 516 | MISC_keymap[Pk_F15&0xFF] = SDLK_F15; |
| 517 | |
| 518 | MISC_keymap[Pk_Num_Lock&0xFF] = SDLK_NUMLOCK; |
| 519 | MISC_keymap[Pk_Caps_Lock&0xFF] = SDLK_CAPSLOCK; |
| 520 | MISC_keymap[Pk_Scroll_Lock&0xFF] = SDLK_SCROLLOCK; |
| 521 | MISC_keymap[Pk_Shift_R&0xFF] = SDLK_RSHIFT; |
| 522 | MISC_keymap[Pk_Shift_L&0xFF] = SDLK_LSHIFT; |
| 523 | MISC_keymap[Pk_Control_R&0xFF] = SDLK_RCTRL; |
| 524 | MISC_keymap[Pk_Control_L&0xFF] = SDLK_LCTRL; |
| 525 | MISC_keymap[Pk_Alt_R&0xFF] = SDLK_RALT; |
| 526 | MISC_keymap[Pk_Alt_L&0xFF] = SDLK_LALT; |
| 527 | MISC_keymap[Pk_Meta_R&0xFF] = SDLK_RMETA; |
| 528 | MISC_keymap[Pk_Meta_L&0xFF] = SDLK_LMETA; |
| 529 | MISC_keymap[Pk_Super_L&0xFF] = SDLK_LSUPER; |
| 530 | MISC_keymap[Pk_Super_R&0xFF] = SDLK_RSUPER; |
| 531 | MISC_keymap[Pk_Mode_switch&0xFF] = SDLK_MODE; /* "Alt Gr" key */ |
| 532 | |
| 533 | MISC_keymap[Pk_Help&0xFF] = SDLK_HELP; |
| 534 | MISC_keymap[Pk_Print&0xFF] = SDLK_PRINT; |
| 535 | MISC_keymap[Pk_Break&0xFF] = SDLK_BREAK; |
| 536 | MISC_keymap[Pk_Menu&0xFF] = SDLK_MENU; /* Windows "Menu" key */ |
| 537 | |
| 538 | MISC_keymap[Pk_Hyper_R&0xFF] = SDLK_RSUPER; /* Right "Windows" */ |
| 539 | |
| 540 | /* Left "Windows" key, but it can't be catched by application */ |
| 541 | MISC_keymap[Pk_Hyper_L&0xFF] = SDLK_LSUPER; |
| 542 | } |
| 543 | |
| 544 | static unsigned long cap; |
| 545 | |
| 546 | SDL_keysym *ph_TranslateKey(PhKeyEvent_t *key, SDL_keysym *keysym) |
| 547 | { |
| 548 | /* 'sym' is set to the value of the key with modifiers applied to it. |
| 549 | This member is valid only if Pk_KF_Sym_Valid is set in the key_flags. |
| 550 | We will assume it is valid. */ |
| 551 | |
| 552 | /* FIXME: This needs to check whether the cap & scancode is valid */ |
| 553 | |
| 554 | cap = key->key_cap; |
| 555 | |
| 556 | switch (cap>>8) |
| 557 | { |
| 558 | case 0x00: /* Latin 1 */ |
| 559 | case 0x01: /* Latin 2 */ |
| 560 | case 0x02: /* Latin 3 */ |
| 561 | case 0x03: /* Latin 4 */ |
| 562 | case 0x04: /* Katakana */ |
| 563 | case 0x05: /* Arabic */ |
| 564 | case 0x06: /* Cyrillic */ |
| 565 | case 0x07: /* Greek */ |
| 566 | case 0x08: /* Technical */ |
| 567 | case 0x0A: /* Publishing */ |
| 568 | case 0x0C: /* Hebrew */ |
| 569 | case 0x0D: /* Thai */ |
| 570 | keysym->sym = (SDLKey)(cap&0xFF); |
| 571 | /* Map capital letter syms to lowercase */ |
| 572 | if ((keysym->sym >= 'A')&&(keysym->sym <= 'Z')) |
| 573 | keysym->sym += ('a'-'A'); |
| 574 | break; |
| 575 | case 0xF0: |
| 576 | keysym->sym = MISC_keymap[cap&0xFF]; |
| 577 | break; |
| 578 | default: |
| 579 | keysym->sym = SDLK_UNKNOWN; |
| 580 | break; |
| 581 | } |
| 582 | |
| 583 | keysym->scancode = key->key_scan; |
| 584 | keysym->unicode = 0; |
| 585 | |
| 586 | if (SDL_TranslateUNICODE) |
| 587 | { |
| 588 | char utf8[MB_CUR_MAX]; |
| 589 | int utf8len; |
| 590 | wchar_t unicode; |
| 591 | |
| 592 | switch (keysym->scancode) |
| 593 | { |
| 594 | /* Esc key */ |
| 595 | case 0x01: keysym->unicode = 27; |
| 596 | break; |
| 597 | /* BackSpace key */ |
| 598 | case 0x0E: keysym->unicode = 127; |
| 599 | break; |
| 600 | /* Enter key */ |
| 601 | case 0x1C: keysym->unicode = 10; |
| 602 | break; |
| 603 | default: |
| 604 | utf8len = PhKeyToMb(utf8, key); |
| 605 | if (utf8len > 0) |
| 606 | { |
| 607 | utf8len = mbtowc(&unicode, utf8, utf8len); |
| 608 | if (utf8len > 0) |
| 609 | { |
| 610 | keysym->unicode = unicode; |
| 611 | } |
| 612 | } |
| 613 | break; |
| 614 | } |
| 615 | |
| 616 | } |
| 617 | |
| 618 | return (keysym); |
| 619 | } |
| 620 | |
| 621 | void ph_InitOSKeymap(_THIS) |
| 622 | { |
| 623 | ph_InitKeymap(); |
| 624 | } |