2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2009 Sam Lantinga
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.
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.
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
22 #include "SDL_config.h"
24 /* Handle the event stream, converting photon events into SDL events */
31 #include <photon/PkKeyDef.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"
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);
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)
53 PhRect_t *rect = PhGetRects( winEvent );
55 int centre_x, centre_y;
60 centre_x = SDL_VideoSurface->w / 2;
61 centre_y = SDL_VideoSurface->h / 2;
63 dx = rect->ul.x - centre_x;
64 dy = rect->ul.y - centre_y;
66 posted = SDL_PrivateMouseMotion( 0, 1, dx, dy );
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);
75 /* Control which motion flags the window has set, a flags value of -1 sets
76 * MOTION_BUTTON and MOTION_NOBUTTON */
78 static void set_motion_sensitivity(_THIS, unsigned int flags)
81 int fields = Ph_EV_PTR_MOTION_BUTTON | Ph_EV_PTR_MOTION_NOBUTTON;
86 rid = PtWidgetRid(window);
87 if( rid != 0 && PhRegionQuery(rid, ®ion, NULL, NULL, 0) == 0 )
89 region.events_sense=(region.events_sense & ~fields)|(flags & fields);
90 PhRegionChange(Ph_REGION_EV_SENSE, 0, ®ion, NULL, NULL);
95 /* Convert the photon button state value to an SDL value */
96 static Uint8 ph2sdl_mousebutton(unsigned short button_state)
98 Uint8 mouse_button = 0;
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;
107 return (mouse_button);
110 static int ph_DispatchEvent(_THIS)
114 PhPointerEvent_t* pointerEvent;
115 PhKeyEvent_t* keyEvent;
116 PhWindowEvent_t* winEvent;
118 SDL_Rect sdlrects[PH_SDL_MAX_RECTS];
122 switch (phevent->type)
126 if (phevent->subtype == Ph_EV_PTR_ENTER)
128 posted = SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS);
130 else if (phevent->subtype ==Ph_EV_PTR_LEAVE)
132 posted = SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS);
137 case Ph_EV_PTR_MOTION_BUTTON:
138 case Ph_EV_PTR_MOTION_NOBUTTON:
140 if (SDL_VideoSurface)
142 pointerEvent = PhGetData(phevent);
143 rect = PhGetRects(phevent);
147 posted = ph_WarpedMotion(this, phevent);
151 posted = SDL_PrivateMouseMotion(0, 0, rect->ul.x, rect->ul.y);
157 case Ph_EV_BUT_PRESS:
159 pointerEvent = PhGetData(phevent);
160 buttons = ph2sdl_mousebutton(pointerEvent->buttons);
163 posted = SDL_PrivateMouseButton(SDL_PRESSED, buttons, 0, 0);
168 case Ph_EV_BUT_RELEASE:
170 pointerEvent = PhGetData(phevent);
171 buttons = ph2sdl_mousebutton(pointerEvent->buttons);
172 if (phevent->subtype == Ph_EV_RELEASE_REAL && buttons != 0)
174 posted = SDL_PrivateMouseButton(SDL_RELEASED, buttons, 0, 0);
176 else if(phevent->subtype == Ph_EV_RELEASE_PHANTOM)
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
184 if ((SDL_GetAppState() & SDL_APPMOUSEFOCUS) == 0)
186 posted = SDL_PrivateMouseButton(SDL_RELEASED, buttons, 0, 0);
194 winEvent = PhGetData(phevent);
197 if ((winEvent->event_f==Ph_WM_FOCUS) && (winEvent->event_state==Ph_WM_EVSTATE_FOCUSLOST))
199 set_motion_sensitivity(this, Ph_EV_PTR_MOTION_BUTTON);
200 posted = SDL_PrivateAppActive(0, SDL_APPINPUTFOCUS);
203 else if ((winEvent->event_f==Ph_WM_FOCUS) && (winEvent->event_state==Ph_WM_EVSTATE_FOCUS))
205 set_motion_sensitivity(this, -1);
206 posted = SDL_PrivateAppActive(1, SDL_APPINPUTFOCUS);
209 else if (winEvent->event_f==Ph_WM_CLOSE)
211 posted = SDL_PrivateQuit();
213 /* request hide/unhide */
214 else if (winEvent->event_f==Ph_WM_HIDE)
218 /* got unhide window event */
219 /* TODO: restore application's palette if in palette mode */
224 /* got hide window event */
225 /* TODO: restore original palette if in palette mode */
229 /* request to resize */
230 else if (winEvent->event_f==Ph_WM_RESIZE)
232 currently_maximized=0;
233 #if (_NTO_VERSION < 630)
234 SDL_PrivateResize(winEvent->size.w+1, winEvent->size.h+1);
236 /* QNX 6.3.0 have this bug fixed */
237 SDL_PrivateResize(winEvent->size.w, winEvent->size.h);
238 #endif /* _NTO_VERSION */
240 /* request to move */
241 else if (winEvent->event_f==Ph_WM_MOVE)
243 if (current_overlay!=NULL)
245 int lockedstate=current_overlay->hwdata->locked;
246 int chromastate=current_overlay->hwdata->ischromakey;
250 current_overlay->hwdata->locked=1;
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);
263 current_overlay->hwdata->ischromakey=chromastate;
264 current_overlay->hwdata->locked=lockedstate;
268 /* maximize request */
269 else if (winEvent->event_f==Ph_WM_MAX)
271 /* window already moved and resized here */
272 currently_maximized=1;
274 /* restore request */
275 else if (winEvent->event_f==Ph_WM_RESTORE)
277 /* window already moved and resized here */
278 currently_maximized=0;
283 /* window has been resized, moved or removed */
286 if (phevent->num_rects!=0)
290 if (SDL_VideoSurface)
292 rect = PhGetRects(phevent);
293 if (phevent->num_rects>PH_SDL_MAX_RECTS)
295 /* sorry, buffers underrun, we'll update only first PH_SDL_MAX_RECTS rects */
296 numrects=PH_SDL_MAX_RECTS;
299 for(i=0; i<phevent->num_rects; i++)
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;
307 this->UpdateRects(this, phevent->num_rects, sdlrects);
309 if (current_overlay!=NULL)
311 int lockedstate=current_overlay->hwdata->locked;
315 current_overlay->hwdata->locked=1;
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);
328 current_overlay->hwdata->forcedredraw=0;
329 current_overlay->hwdata->locked=lockedstate;
343 keyEvent = PhGetData(phevent);
345 if (Pk_KF_Key_Down & keyEvent->key_flags)
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))
350 posted = SDL_PrivateMouseButton(SDL_PRESSED, SDL_BUTTON_WHEELUP, 0, 0);
353 if ((keyEvent->key_cap==Pk_Down) && (keyEvent->key_scan==0) && ((keyEvent->key_flags & Pk_KF_Scan_Valid)==Pk_KF_Scan_Valid))
355 posted = SDL_PrivateMouseButton(SDL_PRESSED, SDL_BUTTON_WHEELDOWN, 0, 0);
358 posted = SDL_PrivateKeyboard(SDL_PRESSED, ph_TranslateKey(keyEvent, &keysym));
360 else /* must be key release */
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))
365 posted = SDL_PrivateMouseButton(SDL_RELEASED, SDL_BUTTON_WHEELUP, 0, 0);
368 if ((keyEvent->key_cap==Pk_Down) && (keyEvent->key_scan==0) && ((keyEvent->key_flags & Pk_KF_Scan_Valid)==Pk_KF_Scan_Valid))
370 posted = SDL_PrivateMouseButton(SDL_RELEASED, SDL_BUTTON_WHEELDOWN, 0, 0);
373 posted = SDL_PrivateKeyboard(SDL_RELEASED, ph_TranslateKey( keyEvent, &keysym));
380 if (phevent->subtype==Ph_OFFSCREEN_INVALID)
382 unsigned long* EvInfoData;
384 EvInfoData=(unsigned long*)PhGetData(phevent);
388 case Pg_VIDEO_MODE_SWITCHED:
392 case Pg_ENTERED_DIRECT:
396 case Pg_EXITED_DIRECT:
400 case Pg_DRIVER_STARTED:
413 /* perform a blocking read if no events available */
414 int ph_Pending(_THIS)
416 /* Flush the display connection and look to see if events are queued */
421 switch(PhEventPeek(phevent, EVENT_SIZE))
426 SDL_SetError("ph_Pending(): PhEventNext failed.\n");
433 /* Oh well, nothing is ready .. */
437 void ph_PumpEvents(_THIS)
439 /* Flush the display connection and look to see if events are queued */
442 while (ph_Pending(this))
444 PtEventHandler(phevent);
445 ph_DispatchEvent(this);
449 void ph_InitKeymap(void)
453 /* Odd keys used in international keyboards */
454 for (i=0; i<SDL_arraysize(ODD_keymap); ++i)
456 ODD_keymap[i] = SDLK_UNKNOWN;
459 /* Map the miscellaneous keys */
460 for (i=0; i<SDL_arraysize(MISC_keymap); ++i)
462 MISC_keymap[i] = SDLK_UNKNOWN;
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;
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;
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;
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;
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;
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 */
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 */
538 MISC_keymap[Pk_Hyper_R&0xFF] = SDLK_RSUPER; /* Right "Windows" */
540 /* Left "Windows" key, but it can't be catched by application */
541 MISC_keymap[Pk_Hyper_L&0xFF] = SDLK_LSUPER;
544 static unsigned long cap;
546 SDL_keysym *ph_TranslateKey(PhKeyEvent_t *key, SDL_keysym *keysym)
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. */
552 /* FIXME: This needs to check whether the cap & scancode is valid */
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');
576 keysym->sym = MISC_keymap[cap&0xFF];
579 keysym->sym = SDLK_UNKNOWN;
583 keysym->scancode = key->key_scan;
586 if (SDL_TranslateUNICODE)
588 char utf8[MB_CUR_MAX];
592 switch (keysym->scancode)
595 case 0x01: keysym->unicode = 27;
598 case 0x0E: keysym->unicode = 127;
601 case 0x1C: keysym->unicode = 10;
604 utf8len = PhKeyToMb(utf8, key);
607 utf8len = mbtowc(&unicode, utf8, utf8len);
610 keysym->unicode = unicode;
621 void ph_InitOSKeymap(_THIS)