diff options
Diffstat (limited to 'distrib/sdl-1.2.15/src/video/photon/SDL_ph_events.c')
-rw-r--r-- | distrib/sdl-1.2.15/src/video/photon/SDL_ph_events.c | 624 |
1 files changed, 624 insertions, 0 deletions
diff --git a/distrib/sdl-1.2.15/src/video/photon/SDL_ph_events.c b/distrib/sdl-1.2.15/src/video/photon/SDL_ph_events.c new file mode 100644 index 0000000..9b7538c --- /dev/null +++ b/distrib/sdl-1.2.15/src/video/photon/SDL_ph_events.c @@ -0,0 +1,624 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Handle the event stream, converting photon events into SDL events */ + +#include <stdio.h> +#include <setjmp.h> +#include <sys/time.h> + +#include <Ph.h> +#include <photon/PkKeyDef.h> + +#include "SDL.h" +#include "SDL_syswm.h" +#include "../SDL_sysvideo.h" +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" +#include "SDL_ph_video.h" +#include "SDL_ph_modes_c.h" +#include "SDL_ph_image_c.h" +#include "SDL_ph_events_c.h" +#include "SDL_phyuv_c.h" + +/* The translation tables from a photon keysym to a SDL keysym */ +static SDLKey ODD_keymap[256]; +static SDLKey MISC_keymap[0xFF + 1]; +SDL_keysym *ph_TranslateKey(PhKeyEvent_t *key, SDL_keysym *keysym); + +/* Check to see if this is a repeated key. + (idea shamelessly lifted from GII -- thanks guys! :) */ +static int ph_WarpedMotion(_THIS, PhEvent_t *winEvent) +{ + PhRect_t *rect = PhGetRects( winEvent ); + + int centre_x, centre_y; + int dx, dy; + short abs_x, abs_y; + int posted; + + centre_x = SDL_VideoSurface->w / 2; + centre_y = SDL_VideoSurface->h / 2; + + dx = rect->ul.x - centre_x; + dy = rect->ul.y - centre_y; + + posted = SDL_PrivateMouseMotion( 0, 1, dx, dy ); + + /* Move mouse cursor to middle of the window */ + PtGetAbsPosition( window, &abs_x, &abs_y ); + PhMoveCursorAbs(PhInputGroup(NULL), abs_x + centre_x, abs_y + centre_y); + + return (posted); +} + +/* Control which motion flags the window has set, a flags value of -1 sets + * MOTION_BUTTON and MOTION_NOBUTTON */ + +static void set_motion_sensitivity(_THIS, unsigned int flags) +{ + int rid; + int fields = Ph_EV_PTR_MOTION_BUTTON | Ph_EV_PTR_MOTION_NOBUTTON; + PhRegion_t region; + + if( window ) + { + rid = PtWidgetRid(window); + if( rid != 0 && PhRegionQuery(rid, ®ion, NULL, NULL, 0) == 0 ) + { + region.events_sense=(region.events_sense & ~fields)|(flags & fields); + PhRegionChange(Ph_REGION_EV_SENSE, 0, ®ion, NULL, NULL); + } + } +} + +/* Convert the photon button state value to an SDL value */ +static Uint8 ph2sdl_mousebutton(unsigned short button_state) +{ + Uint8 mouse_button = 0; + + if (button_state & Ph_BUTTON_SELECT) + mouse_button |= SDL_BUTTON_LEFT; + if (button_state & Ph_BUTTON_MENU) + mouse_button |= SDL_BUTTON_RIGHT; + if (button_state & Ph_BUTTON_ADJUST) + mouse_button |= SDL_BUTTON_MIDDLE; + + return (mouse_button); +} + +static int ph_DispatchEvent(_THIS) +{ + int posted; + PhRect_t* rect; + PhPointerEvent_t* pointerEvent; + PhKeyEvent_t* keyEvent; + PhWindowEvent_t* winEvent; + int i, buttons; + SDL_Rect sdlrects[PH_SDL_MAX_RECTS]; + + posted = 0; + + switch (phevent->type) + { + case Ph_EV_BOUNDARY: + { + if (phevent->subtype == Ph_EV_PTR_ENTER) + { + posted = SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS); + } + else if (phevent->subtype ==Ph_EV_PTR_LEAVE) + { + posted = SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS); + } + } + break; + + case Ph_EV_PTR_MOTION_BUTTON: + case Ph_EV_PTR_MOTION_NOBUTTON: + { + if (SDL_VideoSurface) + { + pointerEvent = PhGetData(phevent); + rect = PhGetRects(phevent); + + if (mouse_relative) + { + posted = ph_WarpedMotion(this, phevent); + } + else + { + posted = SDL_PrivateMouseMotion(0, 0, rect->ul.x, rect->ul.y); + } + } + } + break; + + case Ph_EV_BUT_PRESS: + { + pointerEvent = PhGetData(phevent); + buttons = ph2sdl_mousebutton(pointerEvent->buttons); + if (buttons != 0) + { + posted = SDL_PrivateMouseButton(SDL_PRESSED, buttons, 0, 0); + } + } + break; + + case Ph_EV_BUT_RELEASE: + { + pointerEvent = PhGetData(phevent); + buttons = ph2sdl_mousebutton(pointerEvent->buttons); + if (phevent->subtype == Ph_EV_RELEASE_REAL && buttons != 0) + { + posted = SDL_PrivateMouseButton(SDL_RELEASED, buttons, 0, 0); + } + else if(phevent->subtype == Ph_EV_RELEASE_PHANTOM) + { + /* If the mouse is outside the window, + * only a phantom release event is sent, so + * check if the window doesn't have mouse focus. + * Not perfect, maybe checking the mouse button + * state for Ph_EV_BOUNDARY events would be + * better. */ + if ((SDL_GetAppState() & SDL_APPMOUSEFOCUS) == 0) + { + posted = SDL_PrivateMouseButton(SDL_RELEASED, buttons, 0, 0); + } + } + } + break; + + case Ph_EV_WM: + { + winEvent = PhGetData(phevent); + + /* losing focus */ + if ((winEvent->event_f==Ph_WM_FOCUS) && (winEvent->event_state==Ph_WM_EVSTATE_FOCUSLOST)) + { + set_motion_sensitivity(this, Ph_EV_PTR_MOTION_BUTTON); + posted = SDL_PrivateAppActive(0, SDL_APPINPUTFOCUS); + } + /* gaining focus */ + else if ((winEvent->event_f==Ph_WM_FOCUS) && (winEvent->event_state==Ph_WM_EVSTATE_FOCUS)) + { + set_motion_sensitivity(this, -1); + posted = SDL_PrivateAppActive(1, SDL_APPINPUTFOCUS); + } + /* request quit */ + else if (winEvent->event_f==Ph_WM_CLOSE) + { + posted = SDL_PrivateQuit(); + } + /* request hide/unhide */ + else if (winEvent->event_f==Ph_WM_HIDE) + { + if (currently_hided) + { + /* got unhide window event */ + /* TODO: restore application's palette if in palette mode */ + currently_hided=0; + } + else + { + /* got hide window event */ + /* TODO: restore original palette if in palette mode */ + currently_hided=1; + } + } + /* request to resize */ + else if (winEvent->event_f==Ph_WM_RESIZE) + { + currently_maximized=0; + #if (_NTO_VERSION < 630) + SDL_PrivateResize(winEvent->size.w+1, winEvent->size.h+1); + #else + /* QNX 6.3.0 have this bug fixed */ + SDL_PrivateResize(winEvent->size.w, winEvent->size.h); + #endif /* _NTO_VERSION */ + } + /* request to move */ + else if (winEvent->event_f==Ph_WM_MOVE) + { + if (current_overlay!=NULL) + { + int lockedstate=current_overlay->hwdata->locked; + int chromastate=current_overlay->hwdata->ischromakey; + int error; + SDL_Rect src, dst; + + current_overlay->hwdata->locked=1; + src.x = 0; + src.y = 0; + src.w = current_overlay->w; + src.y = current_overlay->h; + dst.x=current_overlay->hwdata->CurrentViewPort.pos.x; + dst.y=current_overlay->hwdata->CurrentViewPort.pos.y; + dst.w=current_overlay->hwdata->CurrentViewPort.size.w; + dst.h=current_overlay->hwdata->CurrentViewPort.size.h; + current_overlay->hwdata->ischromakey=0; + error=ph_DisplayYUVOverlay(this, current_overlay, &src, &dst); + if (!error) + { + current_overlay->hwdata->ischromakey=chromastate; + current_overlay->hwdata->locked=lockedstate; + } + } + } + /* maximize request */ + else if (winEvent->event_f==Ph_WM_MAX) + { + /* window already moved and resized here */ + currently_maximized=1; + } + /* restore request */ + else if (winEvent->event_f==Ph_WM_RESTORE) + { + /* window already moved and resized here */ + currently_maximized=0; + } + } + break; + + /* window has been resized, moved or removed */ + case Ph_EV_EXPOSE: + { + if (phevent->num_rects!=0) + { + int numrects; + + if (SDL_VideoSurface) + { + rect = PhGetRects(phevent); + if (phevent->num_rects>PH_SDL_MAX_RECTS) + { + /* sorry, buffers underrun, we'll update only first PH_SDL_MAX_RECTS rects */ + numrects=PH_SDL_MAX_RECTS; + } + + for(i=0; i<phevent->num_rects; i++) + { + sdlrects[i].x = rect[i].ul.x; + sdlrects[i].y = rect[i].ul.y; + sdlrects[i].w = rect[i].lr.x - rect[i].ul.x + 1; + sdlrects[i].h = rect[i].lr.y - rect[i].ul.y + 1; + } + + this->UpdateRects(this, phevent->num_rects, sdlrects); + + if (current_overlay!=NULL) + { + int lockedstate=current_overlay->hwdata->locked; + int error; + SDL_Rect src, dst; + + current_overlay->hwdata->locked=1; + src.x = 0; + src.y = 0; + src.w = current_overlay->w; + src.y = current_overlay->h; + dst.x=current_overlay->hwdata->CurrentViewPort.pos.x; + dst.y=current_overlay->hwdata->CurrentViewPort.pos.y; + dst.w=current_overlay->hwdata->CurrentViewPort.size.w; + dst.h=current_overlay->hwdata->CurrentViewPort.size.h; + current_overlay->hwdata->forcedredraw=1; + error=ph_DisplayYUVOverlay(this, current_overlay, &src, &dst); + if (!error) + { + current_overlay->hwdata->forcedredraw=0; + current_overlay->hwdata->locked=lockedstate; + } + } + } + } + } + break; + + case Ph_EV_KEY: + { + SDL_keysym keysym; + + posted = 0; + + keyEvent = PhGetData(phevent); + + if (Pk_KF_Key_Down & keyEvent->key_flags) + { + /* split the wheel events from real key events */ + if ((keyEvent->key_cap==Pk_Up) && (keyEvent->key_scan==0) && ((keyEvent->key_flags & Pk_KF_Scan_Valid)==Pk_KF_Scan_Valid)) + { + posted = SDL_PrivateMouseButton(SDL_PRESSED, SDL_BUTTON_WHEELUP, 0, 0); + break; + } + if ((keyEvent->key_cap==Pk_Down) && (keyEvent->key_scan==0) && ((keyEvent->key_flags & Pk_KF_Scan_Valid)==Pk_KF_Scan_Valid)) + { + posted = SDL_PrivateMouseButton(SDL_PRESSED, SDL_BUTTON_WHEELDOWN, 0, 0); + break; + } + posted = SDL_PrivateKeyboard(SDL_PRESSED, ph_TranslateKey(keyEvent, &keysym)); + } + else /* must be key release */ + { + /* split the wheel events from real key events */ + if ((keyEvent->key_cap==Pk_Up) && (keyEvent->key_scan==0) && ((keyEvent->key_flags & Pk_KF_Scan_Valid)==Pk_KF_Scan_Valid)) + { + posted = SDL_PrivateMouseButton(SDL_RELEASED, SDL_BUTTON_WHEELUP, 0, 0); + break; + } + if ((keyEvent->key_cap==Pk_Down) && (keyEvent->key_scan==0) && ((keyEvent->key_flags & Pk_KF_Scan_Valid)==Pk_KF_Scan_Valid)) + { + posted = SDL_PrivateMouseButton(SDL_RELEASED, SDL_BUTTON_WHEELDOWN, 0, 0); + break; + } + posted = SDL_PrivateKeyboard(SDL_RELEASED, ph_TranslateKey( keyEvent, &keysym)); + } + } + break; + + case Ph_EV_INFO: + { + if (phevent->subtype==Ph_OFFSCREEN_INVALID) + { + unsigned long* EvInfoData; + + EvInfoData=(unsigned long*)PhGetData(phevent); + + switch (*EvInfoData) + { + case Pg_VIDEO_MODE_SWITCHED: + { + } + break; + case Pg_ENTERED_DIRECT: + { + } + break; + case Pg_EXITED_DIRECT: + { + } + break; + case Pg_DRIVER_STARTED: + { + } + break; + } + } + } + break; + } + + return(posted); +} + +/* perform a blocking read if no events available */ +int ph_Pending(_THIS) +{ + /* Flush the display connection and look to see if events are queued */ + PgFlush(); + + while (1) + { + switch(PhEventPeek(phevent, EVENT_SIZE)) + { + case Ph_EVENT_MSG: + return 1; + case -1: + SDL_SetError("ph_Pending(): PhEventNext failed.\n"); + return 0; + default: + return 0; + } + } + + /* Oh well, nothing is ready .. */ + return(0); +} + +void ph_PumpEvents(_THIS) +{ + /* Flush the display connection and look to see if events are queued */ + PgFlush(); + + while (ph_Pending(this)) + { + PtEventHandler(phevent); + ph_DispatchEvent(this); + } +} + +void ph_InitKeymap(void) +{ + int i; + + /* Odd keys used in international keyboards */ + for (i=0; i<SDL_arraysize(ODD_keymap); ++i) + { + ODD_keymap[i] = SDLK_UNKNOWN; + } + + /* Map the miscellaneous keys */ + for (i=0; i<SDL_arraysize(MISC_keymap); ++i) + { + MISC_keymap[i] = SDLK_UNKNOWN; + } + + MISC_keymap[Pk_BackSpace&0xFF] = SDLK_BACKSPACE; + MISC_keymap[Pk_Tab&0xFF] = SDLK_TAB; + MISC_keymap[Pk_Clear&0xFF] = SDLK_CLEAR; + MISC_keymap[Pk_Return&0xFF] = SDLK_RETURN; + MISC_keymap[Pk_Pause&0xFF] = SDLK_PAUSE; + MISC_keymap[Pk_Escape&0xFF] = SDLK_ESCAPE; + MISC_keymap[Pk_Delete&0xFF] = SDLK_DELETE; + + MISC_keymap[Pk_KP_0&0xFF] = SDLK_KP0; + MISC_keymap[Pk_KP_1&0xFF] = SDLK_KP1; + MISC_keymap[Pk_KP_2&0xFF] = SDLK_KP2; + MISC_keymap[Pk_KP_3&0xFF] = SDLK_KP3; + MISC_keymap[Pk_KP_4&0xFF] = SDLK_KP4; + MISC_keymap[Pk_KP_5&0xFF] = SDLK_KP5; + MISC_keymap[Pk_KP_6&0xFF] = SDLK_KP6; + MISC_keymap[Pk_KP_7&0xFF] = SDLK_KP7; + MISC_keymap[Pk_KP_8&0xFF] = SDLK_KP8; + MISC_keymap[Pk_KP_9&0xFF] = SDLK_KP9; + + MISC_keymap[Pk_KP_Decimal&0xFF] = SDLK_KP_PERIOD; + MISC_keymap[Pk_KP_Divide&0xFF] = SDLK_KP_DIVIDE; + MISC_keymap[Pk_KP_Multiply&0xFF] = SDLK_KP_MULTIPLY; + MISC_keymap[Pk_KP_Subtract&0xFF] = SDLK_KP_MINUS; + MISC_keymap[Pk_KP_Add&0xFF] = SDLK_KP_PLUS; + MISC_keymap[Pk_KP_Enter&0xFF] = SDLK_KP_ENTER; + MISC_keymap[Pk_KP_Equal&0xFF] = SDLK_KP_EQUALS; + + MISC_keymap[Pk_Up&0xFF] = SDLK_UP; + MISC_keymap[Pk_Down&0xFF] = SDLK_DOWN; + MISC_keymap[Pk_Right&0xFF] = SDLK_RIGHT; + MISC_keymap[Pk_Left&0xFF] = SDLK_LEFT; + MISC_keymap[Pk_Insert&0xFF] = SDLK_INSERT; + MISC_keymap[Pk_Home&0xFF] = SDLK_HOME; + MISC_keymap[Pk_End&0xFF] = SDLK_END; + MISC_keymap[Pk_Pg_Up&0xFF] = SDLK_PAGEUP; + MISC_keymap[Pk_Pg_Down&0xFF] = SDLK_PAGEDOWN; + + MISC_keymap[Pk_F1&0xFF] = SDLK_F1; + MISC_keymap[Pk_F2&0xFF] = SDLK_F2; + MISC_keymap[Pk_F3&0xFF] = SDLK_F3; + MISC_keymap[Pk_F4&0xFF] = SDLK_F4; + MISC_keymap[Pk_F5&0xFF] = SDLK_F5; + MISC_keymap[Pk_F6&0xFF] = SDLK_F6; + MISC_keymap[Pk_F7&0xFF] = SDLK_F7; + MISC_keymap[Pk_F8&0xFF] = SDLK_F8; + MISC_keymap[Pk_F9&0xFF] = SDLK_F9; + MISC_keymap[Pk_F10&0xFF] = SDLK_F10; + MISC_keymap[Pk_F11&0xFF] = SDLK_F11; + MISC_keymap[Pk_F12&0xFF] = SDLK_F12; + MISC_keymap[Pk_F13&0xFF] = SDLK_F13; + MISC_keymap[Pk_F14&0xFF] = SDLK_F14; + MISC_keymap[Pk_F15&0xFF] = SDLK_F15; + + MISC_keymap[Pk_Num_Lock&0xFF] = SDLK_NUMLOCK; + MISC_keymap[Pk_Caps_Lock&0xFF] = SDLK_CAPSLOCK; + MISC_keymap[Pk_Scroll_Lock&0xFF] = SDLK_SCROLLOCK; + MISC_keymap[Pk_Shift_R&0xFF] = SDLK_RSHIFT; + MISC_keymap[Pk_Shift_L&0xFF] = SDLK_LSHIFT; + MISC_keymap[Pk_Control_R&0xFF] = SDLK_RCTRL; + MISC_keymap[Pk_Control_L&0xFF] = SDLK_LCTRL; + MISC_keymap[Pk_Alt_R&0xFF] = SDLK_RALT; + MISC_keymap[Pk_Alt_L&0xFF] = SDLK_LALT; + MISC_keymap[Pk_Meta_R&0xFF] = SDLK_RMETA; + MISC_keymap[Pk_Meta_L&0xFF] = SDLK_LMETA; + MISC_keymap[Pk_Super_L&0xFF] = SDLK_LSUPER; + MISC_keymap[Pk_Super_R&0xFF] = SDLK_RSUPER; + MISC_keymap[Pk_Mode_switch&0xFF] = SDLK_MODE; /* "Alt Gr" key */ + + MISC_keymap[Pk_Help&0xFF] = SDLK_HELP; + MISC_keymap[Pk_Print&0xFF] = SDLK_PRINT; + MISC_keymap[Pk_Break&0xFF] = SDLK_BREAK; + MISC_keymap[Pk_Menu&0xFF] = SDLK_MENU; /* Windows "Menu" key */ + + MISC_keymap[Pk_Hyper_R&0xFF] = SDLK_RSUPER; /* Right "Windows" */ + + /* Left "Windows" key, but it can't be catched by application */ + MISC_keymap[Pk_Hyper_L&0xFF] = SDLK_LSUPER; +} + +static unsigned long cap; + +SDL_keysym *ph_TranslateKey(PhKeyEvent_t *key, SDL_keysym *keysym) +{ + /* 'sym' is set to the value of the key with modifiers applied to it. + This member is valid only if Pk_KF_Sym_Valid is set in the key_flags. + We will assume it is valid. */ + + /* FIXME: This needs to check whether the cap & scancode is valid */ + + cap = key->key_cap; + + switch (cap>>8) + { + case 0x00: /* Latin 1 */ + case 0x01: /* Latin 2 */ + case 0x02: /* Latin 3 */ + case 0x03: /* Latin 4 */ + case 0x04: /* Katakana */ + case 0x05: /* Arabic */ + case 0x06: /* Cyrillic */ + case 0x07: /* Greek */ + case 0x08: /* Technical */ + case 0x0A: /* Publishing */ + case 0x0C: /* Hebrew */ + case 0x0D: /* Thai */ + keysym->sym = (SDLKey)(cap&0xFF); + /* Map capital letter syms to lowercase */ + if ((keysym->sym >= 'A')&&(keysym->sym <= 'Z')) + keysym->sym += ('a'-'A'); + break; + case 0xF0: + keysym->sym = MISC_keymap[cap&0xFF]; + break; + default: + keysym->sym = SDLK_UNKNOWN; + break; + } + + keysym->scancode = key->key_scan; + keysym->unicode = 0; + + if (SDL_TranslateUNICODE) + { + char utf8[MB_CUR_MAX]; + int utf8len; + wchar_t unicode; + + switch (keysym->scancode) + { + /* Esc key */ + case 0x01: keysym->unicode = 27; + break; + /* BackSpace key */ + case 0x0E: keysym->unicode = 127; + break; + /* Enter key */ + case 0x1C: keysym->unicode = 10; + break; + default: + utf8len = PhKeyToMb(utf8, key); + if (utf8len > 0) + { + utf8len = mbtowc(&unicode, utf8, utf8len); + if (utf8len > 0) + { + keysym->unicode = unicode; + } + } + break; + } + + } + + return (keysym); +} + +void ph_InitOSKeymap(_THIS) +{ + ph_InitKeymap(); +} |