Mercurial > sdl-ios-xcode
diff src/video/photon/SDL_ph_events.c @ 0:74212992fb08
Initial revision
author | Sam Lantinga <slouken@lokigames.com> |
---|---|
date | Thu, 26 Apr 2001 16:45:43 +0000 |
parents | |
children | 8cc4dbfab9ab |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/video/photon/SDL_ph_events.c Thu Apr 26 16:45:43 2001 +0000 @@ -0,0 +1,563 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@devolution.com +*/ + +#ifdef SAVE_RCSID +static char rcsid = + "@(#) $Id$"; +#endif + +/* Handle the event stream, converting photon events into SDL events */ + +#include <Ph.h> +#include <stdio.h> +#include <setjmp.h> +#include <photon/PkKeyDef.h> +#include <sys/time.h> + +#include "SDL.h" +#include "SDL_syswm.h" +#include "SDL_sysevents.h" +#include "SDL_sysvideo.h" +#include "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" + + +/* 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_KeyRepeat(_THIS, PhKeyEvent_t* keyevent) +{ + PhEvent_t* peekevent; + PhKeyEvent_t* keyEvent; + int repeated; + + repeated = 0; + switch (PhEventPeek( peekevent, EVENT_SIZE )) + { + case Ph_EVENT_MSG: { + if(peekevent->type == Ph_EV_KEY) + { + keyEvent = PhGetData( peekevent ); + if ( !(Pk_KF_Key_Down & keyEvent->key_flags) && + (keyEvent->key_cap == keyevent->key_cap) && + (peekevent->timestamp == event->timestamp) + ) { + repeated = 1; + //PhEventNext( peekevent, EVENT_SIZE ); + } + } + } + break; + + case -1: { + perror( "PhEventPeek failed" ); + } + break; + + default: /* no events pending */ + } + return(repeated); +} + +/* Note: The X server buffers and accumulates mouse motion events, so + the motion event generated by the warp may not appear exactly as we + expect it to. We work around this (and improve performance) by only + warping the pointer when it reaches the edge, and then wait for it. +*/ +/* +#define MOUSE_FUDGE_FACTOR 8 + +static inline int X11_WarpedMotion(_THIS, XEvent *xevent) +{ + int w, h, i; + int deltax, deltay; + int posted; + + w = SDL_VideoSurface->w; + h = SDL_VideoSurface->h; + deltax = xevent->xmotion.x - mouse_last.x; + deltay = xevent->xmotion.y - mouse_last.y; +#ifdef DEBUG_MOTION + printf("Warped mouse motion: %d,%d\n", deltax, deltay); +#endif + mouse_last.x = xevent->xmotion.x; + mouse_last.y = xevent->xmotion.y; + posted = SDL_PrivateMouseMotion(0, 1, deltax, deltay); + + if ( (xevent->xmotion.x < MOUSE_FUDGE_FACTOR) || + (xevent->xmotion.x > (w-MOUSE_FUDGE_FACTOR)) || + (xevent->xmotion.y < MOUSE_FUDGE_FACTOR) || + (xevent->xmotion.y > (h-MOUSE_FUDGE_FACTOR)) ) { + /* Get the events that have accumulated */ +/* while ( XCheckTypedEvent(SDL_Display, MotionNotify, xevent) ) { + deltax = xevent->xmotion.x - mouse_last.x; + deltay = xevent->xmotion.y - mouse_last.y; +#ifdef DEBUG_MOTION + printf("Extra mouse motion: %d,%d\n", deltax, deltay); +#endif + mouse_last.x = xevent->xmotion.x; + mouse_last.y = xevent->xmotion.y; + posted += SDL_PrivateMouseMotion(0, 1, deltax, deltay); + } + mouse_last.x = w/2; + mouse_last.y = h/2; + XWarpPointer(SDL_Display, None, SDL_Window, 0, 0, 0, 0, + mouse_last.x, mouse_last.y); + for ( i=0; i<10; ++i ) { + XMaskEvent(SDL_Display, PointerMotionMask, xevent); + if ( (xevent->xmotion.x > + (mouse_last.x-MOUSE_FUDGE_FACTOR)) && + (xevent->xmotion.x < + (mouse_last.x+MOUSE_FUDGE_FACTOR)) && + (xevent->xmotion.y > + (mouse_last.y-MOUSE_FUDGE_FACTOR)) && + (xevent->xmotion.y < + (mouse_last.y+MOUSE_FUDGE_FACTOR)) ) { + break; + } +#ifdef DEBUG_XEVENTS + printf("Lost mouse motion: %d,%d\n", xevent->xmotion.x, xevent->xmotion.y); +#endif + } +#ifdef DEBUG_XEVENTS + if ( i == 10 ) { + printf("Warning: didn't detect mouse warp motion\n"); + } +#endif + } + return(posted); +} +*/ + +static int ph_DispatchEvent(_THIS) +{ + int posted; + PhRect_t* rect; + PhPointerEvent_t* pointerEvent; + PhKeyEvent_t* keyEvent; + PhWindowEvent_t* winEvent; + int i; + SDL_Rect sdlrects[50]; + + posted = 0; + + switch (event->type) { + case Ph_EV_BOUNDARY: + { + + if (event->subtype == Ph_EV_PTR_ENTER) + posted = SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS); + else if (event->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( event ); + rect = PhGetRects( event ); + posted = SDL_PrivateMouseMotion(0, 1, + pointerEvent->pos.x - rect[0].ul.x, + pointerEvent->pos.y - rect[0].ul.y); + } + } + break; + + case Ph_EV_BUT_PRESS: + { + + pointerEvent = PhGetData( event ); + /* TODO: is 'buttons' the right mapping? */ + posted = SDL_PrivateMouseButton(SDL_PRESSED, + pointerEvent->buttons, 0, 0); + } + break; + + case Ph_EV_BUT_RELEASE: + { + + pointerEvent = PhGetData( event ); + posted = SDL_PrivateMouseButton(SDL_RELEASED, + pointerEvent->buttons, 0, 0); + } + break; + + case Ph_EV_WM: + { + + + winEvent = PhGetData( event ); + + /* losing focus */ + if ((winEvent->event_f==Ph_WM_FOCUS)&& + (winEvent->event_state==Ph_WM_EVSTATE_FOCUSLOST)) + { + posted = SDL_PrivateAppActive(0, SDL_APPINPUTFOCUS); + + /* Queue leaving fullscreen mode */ + switch_waiting = 0x01; + switch_time = SDL_GetTicks() + 200; + } + + /* gaining focus */ + else if ((winEvent->event_f==Ph_WM_FOCUS)&& + (winEvent->event_state==Ph_WM_EVSTATE_FOCUS)) + { + posted = SDL_PrivateAppActive(1, SDL_APPINPUTFOCUS); + + /* Queue entry into fullscreen mode */ + switch_waiting = 0x01 | SDL_FULLSCREEN; + switch_time = SDL_GetTicks() + 1500; + } + + /* request to quit */ + else if (winEvent->event_f==Ph_WM_CLOSE) + { + posted = SDL_PrivateQuit(); + } + } + break; + + /* window has been resized, moved or removed */ + case Ph_EV_EXPOSE: + { + + if (SDL_VideoSurface) + { + + + rect = PhGetRects( event ); + + //PgSetClipping(1, rect ); + for(i=0;i<event->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; + sdlrects[i].h = rect[i].lr.y - rect[i].ul.y; + + } + + this->UpdateRects(this, event->num_rects, sdlrects); + + } + } + break; + + case Ph_EV_KEY: + { + + SDL_keysym keysym; + + posted = 0; + + keyEvent = PhGetData( event ); + + if (Pk_KF_Key_Down & keyEvent->key_flags) + { + + posted = SDL_PrivateKeyboard(SDL_PRESSED, + ph_TranslateKey( keyEvent, &keysym)); + } + else /* must be key release */ + { + /* Ignore repeated key release events */ + /*if (! Pk_KF_Key_Repeat & keyEvent->key_flags )*/ + + posted = SDL_PrivateKeyboard(SDL_RELEASED, + ph_TranslateKey( keyEvent, &keysym)); + /*}*/ + } + } + 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 ) + { //note this is a non-blocking call + switch( PhEventPeek( event, EVENT_SIZE ) ) + { + case Ph_EVENT_MSG: + + return 1; + break; + case -1: + perror( "PhEventNext failed" ); + break; + default: + + return 0; + } + } + + /* Oh well, nothing is ready .. */ + return(0); +} + +/* +SAMPLE EVENT PUMP +================= +static void update( int block ){ + + int ch,fl; + PhKeyEvent_t *key; + + for( ;; ){ + + if( block ){ + do{ + fl=PhEventNext( event,EVENT_SIZE ); + }while( fl!=Ph_EVENT_MSG ); + block=0; + }else{ + do{ + fl=PhEventPeek( event,EVENT_SIZE ); + if( !fl ) return; + }while( fl!=Ph_EVENT_MSG ); + } + + switch( event->type ){ + case Ph_EV_KEY: + key=PhGetData( event ); + ch=key->key_cap; // & 127; + fl=key->key_flags; + if( ch<32 || ch>127 ) break; + if( fl & Pk_KF_Key_Down ){ + if( !(fl & Pk_KF_Key_Repeat) ){ + if( queput-queget<QUE_SIZE ) keyque[ queput++ & QUE_MASK ]=ch; + keyMatrix[ch]=1; + } + }else{ + keyMatrix[ch]=0; + } + break; + default: + PtEventHandler( event ); + } + } +} +*/ + +void ph_PumpEvents(_THIS) +{ + int pending; + + /* Keep processing pending events */ + pending = 0; + while ( ph_Pending(this) ) { + ph_DispatchEvent(this); + ++pending; + } + if ( switch_waiting ) { + Uint32 now; + + now = SDL_GetTicks(); + if ( pending || !SDL_VideoSurface ) { + /* Try again later... */ + if ( switch_waiting & SDL_FULLSCREEN ) { + switch_time = now + 1500; + } else { + switch_time = now + 200; + } + } else if ( now >= switch_time ) { + Uint32 go_fullscreen; + + go_fullscreen = switch_waiting & SDL_FULLSCREEN; + switch_waiting = 0; + if ( SDL_VideoSurface->flags & SDL_FULLSCREEN ) { + if ( go_fullscreen ) { + ph_EnterFullScreen(this); + } else { + ph_LeaveFullScreen(this); + } + } + /* Handle focus in/out when grabbed */ +/* + if ( go_fullscreen ) { + ph_GrabInputNoLock(this, this->input_grab); + } else { + ph_GrabInputNoLock(this, SDL_GRAB_OFF); + } +*/ + } + } +} + +void ph_InitKeymap(void) +{ + int i; + + /* Odd keys used in international keyboards */ + for ( i=0; i<SDL_TABLESIZE(ODD_keymap); ++i ) + ODD_keymap[i] = SDLK_UNKNOWN; + + /* Map the miscellaneous keys */ + for ( i=0; i<SDL_TABLESIZE(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; /* Left "Windows" */ + MISC_keymap[Pk_Super_R&0xFF] = SDLK_RSUPER; /* Right "Windows */ + 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_Sys_Req] = SDLK_SYSREQ; + MISC_keymap[Pk_Break&0xFF] = SDLK_BREAK; + MISC_keymap[Pk_Menu&0xFF] = SDLK_MENU; + MISC_keymap[Pk_Hyper_R&0xFF] = SDLK_MENU; /* Windows "Menu" key */ +} + +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. +*/ + 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 0xFE: +// keysym->sym = ODD_keymap[sym&0xFF]; +// break; + case 0xF0: + keysym->sym = MISC_keymap[cap&0xFF]; + break; + default: + fprintf(stderr,"Photon: Unknown key_cap, cap = 0x%.4x\n", (unsigned int)cap); + break; + } + return (keysym); +} + +void ph_InitOSKeymap(_THIS) +{ + + ph_InitKeymap(); +} +