Mercurial > sdl-ios-xcode
view src/video/photon/SDL_ph_events.c @ 283:3d8b6b9f1e18
Date: Mon, 18 Feb 2002 16:46:59 +1200
From: Julian Kinraid <jkinraid@clear.net.nz>
Subject: Patches for photon port of SDL
Hi,
A couple more patches for photon and the nto audio. Adds mouse grabbing
support, fixed cursor images, unicode keyboard events (though no unicode
data on kye release, is that a problem?), hopefully fixing some audio
lag problems, and a few other fixes.
Thanks,
Julian Kinraid
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Wed, 20 Feb 2002 01:05:51 +0000 |
parents | c6abdda2f666 |
children | f6ffac90895c |
line wrap: on
line source
/* 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@libsdl.org */ #ifdef SAVE_RCSID static char rcsid = "@(#) $Id$"; #endif /* Handle the event stream, converting photon events into SDL events */ #define DISABLE_X11 #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! :) */ #if 0 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); } #endif static int ph_WarpedMotion(_THIS, PhEvent_t *winEvent) { PhPointerEvent_t *pointer = PhGetData( winEvent ); PhRect_t *rect = PhGetRects( winEvent ); int centre_x, centre_y; int dx, dy, 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, 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[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 ); if( mouse_relative ) { posted = ph_WarpedMotion(this, event); } else posted = SDL_PrivateMouseMotion(0, 0, rect->ul.x, rect->ul.y); } } break; case Ph_EV_BUT_PRESS: { pointerEvent = PhGetData( event ); buttons = ph2sdl_mousebutton( pointerEvent->buttons ); if( buttons != 0 ) posted = SDL_PrivateMouseButton( SDL_PRESSED, buttons, 0, 0 ); } break; case Ph_EV_BUT_RELEASE: { pointerEvent = PhGetData(event); buttons = ph2sdl_mousebutton(pointerEvent->buttons); if( event->subtype == Ph_EV_RELEASE_REAL && buttons != 0 ) { posted = SDL_PrivateMouseButton( SDL_RELEASED, buttons, 0, 0 ); } else if( event->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( event ); /* 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); /* 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)) { set_motion_sensitivity(this, -1); posted = SDL_PrivateAppActive(1, SDL_APPINPUTFOCUS); #if 0 /* Queue entry into fullscreen mode */ switch_waiting = 0x01 | SDL_FULLSCREEN; switch_time = SDL_GetTicks() + 1500; #endif } /* request to quit */ else if (winEvent->event_f==Ph_WM_CLOSE) { posted = SDL_PrivateQuit(); } else if (winEvent->event_f==Ph_WM_RESIZE) { PhDim_t *size; PtGetResource( window, Pt_ARG_DIM, &size, 0 ); SDL_PrivateResize(size->w,size->h); } } 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 + 1; sdlrects[i].h = rect[i].lr.y - rect[i].ul.y + 1; } 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 0 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); } */ } #endif } } 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. */ /* 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 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); */ 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; utf8len = PhKeyToMb( utf8, key ); if( utf8len > 0 ) { utf8len = mbtowc( &unicode, utf8, utf8len ); if( utf8len > 0) keysym->unicode = unicode; } } return (keysym); } void ph_InitOSKeymap(_THIS) { ph_InitKeymap(); }