src/video/photon/SDL_ph_events.c
author Sam Lantinga <slouken@libsdl.org>
Fri, 14 Dec 2001 12:38:15 +0000
changeset 252 e8157fcb3114
parent 220 7861d904fb77
child 266 c6abdda2f666
permissions -rw-r--r--
Updated the source with the correct e-mail address
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997, 1998, 1999, 2000, 2001  Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Library General Public
     7     License as published by the Free Software Foundation; either
     8     version 2 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     Library General Public License for more details.
    14 
    15     You should have received a copy of the GNU Library General Public
    16     License along with this library; if not, write to the Free
    17     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 */
    22 
    23 #ifdef SAVE_RCSID
    24 static char rcsid =
    25  "@(#) $Id$";
    26 #endif
    27 
    28 /* Handle the event stream, converting photon events into SDL events */
    29 
    30 #define DISABLE_X11
    31 
    32 #include <Ph.h>
    33 #include <stdio.h>
    34 #include <setjmp.h>
    35 #include <photon/PkKeyDef.h>
    36 #include <sys/time.h>
    37 
    38 #include "SDL.h"
    39 #include "SDL_syswm.h"
    40 #include "SDL_sysevents.h"
    41 #include "SDL_sysvideo.h"
    42 #include "SDL_events_c.h"
    43 #include "SDL_ph_video.h"
    44 #include "SDL_ph_modes_c.h"
    45 #include "SDL_ph_image_c.h"
    46 #include "SDL_ph_events_c.h"
    47 
    48 
    49 /* The translation tables from a photon keysym to a SDL keysym */
    50 static SDLKey ODD_keymap[256];
    51 static SDLKey MISC_keymap[0xFF + 1];
    52 SDL_keysym *ph_TranslateKey(PhKeyEvent_t *key, SDL_keysym *keysym);
    53 
    54 /* Check to see if this is a repeated key.
    55    (idea shamelessly lifted from GII -- thanks guys! :)
    56  */
    57 
    58 static int ph_KeyRepeat(_THIS, PhKeyEvent_t* keyevent)
    59 {
    60 	PhEvent_t* peekevent;
    61 	PhKeyEvent_t* keyEvent;
    62 	int repeated;
    63 
    64 	repeated = 0;
    65 	switch (PhEventPeek( peekevent, EVENT_SIZE ))
    66 	{
    67 		case Ph_EVENT_MSG: {
    68 			if(peekevent->type == Ph_EV_KEY)
    69 			{
    70 				keyEvent = PhGetData( peekevent );
    71 				if ( !(Pk_KF_Key_Down & keyEvent->key_flags) &&
    72 					(keyEvent->key_cap == keyevent->key_cap) &&
    73 					(peekevent->timestamp == event->timestamp)	
    74 				) {
    75 					repeated = 1;
    76 					 //PhEventNext( peekevent, EVENT_SIZE );  
    77 				}				
    78 			}
    79 		}
    80 		break;
    81 
    82 		case -1: {
    83 			perror( "PhEventPeek failed" );
    84 		}
    85 		break;
    86 
    87 		default: /* no events pending */
    88 	}
    89 	return(repeated);
    90 }
    91 
    92 /* Note:  The X server buffers and accumulates mouse motion events, so
    93    the motion event generated by the warp may not appear exactly as we
    94    expect it to.  We work around this (and improve performance) by only
    95    warping the pointer when it reaches the edge, and then wait for it.
    96 */
    97 /*
    98 #define MOUSE_FUDGE_FACTOR	8
    99 
   100 static inline int X11_WarpedMotion(_THIS, XEvent *xevent)
   101 {
   102 	int w, h, i;
   103 	int deltax, deltay;
   104 	int posted;
   105 
   106 	w = SDL_VideoSurface->w;
   107 	h = SDL_VideoSurface->h;
   108 	deltax = xevent->xmotion.x - mouse_last.x;
   109 	deltay = xevent->xmotion.y - mouse_last.y;
   110 #ifdef DEBUG_MOTION
   111   printf("Warped mouse motion: %d,%d\n", deltax, deltay);
   112 #endif
   113 	mouse_last.x = xevent->xmotion.x;
   114 	mouse_last.y = xevent->xmotion.y;
   115 	posted = SDL_PrivateMouseMotion(0, 1, deltax, deltay);
   116 
   117 	if ( (xevent->xmotion.x < MOUSE_FUDGE_FACTOR) ||
   118 	     (xevent->xmotion.x > (w-MOUSE_FUDGE_FACTOR)) ||
   119 	     (xevent->xmotion.y < MOUSE_FUDGE_FACTOR) ||
   120 	     (xevent->xmotion.y > (h-MOUSE_FUDGE_FACTOR)) ) {
   121 		/* Get the events that have accumulated */
   122 /*		while ( XCheckTypedEvent(SDL_Display, MotionNotify, xevent) ) {
   123 			deltax = xevent->xmotion.x - mouse_last.x;
   124 			deltay = xevent->xmotion.y - mouse_last.y;
   125 #ifdef DEBUG_MOTION
   126   printf("Extra mouse motion: %d,%d\n", deltax, deltay);
   127 #endif
   128 			mouse_last.x = xevent->xmotion.x;
   129 			mouse_last.y = xevent->xmotion.y;
   130 			posted += SDL_PrivateMouseMotion(0, 1, deltax, deltay);
   131 		}
   132 		mouse_last.x = w/2;
   133 		mouse_last.y = h/2;
   134 		XWarpPointer(SDL_Display, None, SDL_Window, 0, 0, 0, 0,
   135 					mouse_last.x, mouse_last.y);
   136 		for ( i=0; i<10; ++i ) {
   137         		XMaskEvent(SDL_Display, PointerMotionMask, xevent);
   138 			if ( (xevent->xmotion.x >
   139 			          (mouse_last.x-MOUSE_FUDGE_FACTOR)) &&
   140 			     (xevent->xmotion.x <
   141 			          (mouse_last.x+MOUSE_FUDGE_FACTOR)) &&
   142 			     (xevent->xmotion.y >
   143 			          (mouse_last.y-MOUSE_FUDGE_FACTOR)) &&
   144 			     (xevent->xmotion.y <
   145 			          (mouse_last.y+MOUSE_FUDGE_FACTOR)) ) {
   146 				break;
   147 			}
   148 #ifdef DEBUG_XEVENTS
   149   printf("Lost mouse motion: %d,%d\n", xevent->xmotion.x, xevent->xmotion.y);
   150 #endif
   151 		}
   152 #ifdef DEBUG_XEVENTS
   153 		if ( i == 10 ) {
   154 			printf("Warning: didn't detect mouse warp motion\n");
   155 		}
   156 #endif
   157 	}
   158 	return(posted);
   159 }
   160 */
   161 
   162 /* Control which motion flags the window has set, a flags value of -1 sets
   163  * MOTION_BUTTON and MOTION_NOBUTTON */
   164 static void set_motion_sensitivity(_THIS, unsigned int flags)
   165 {
   166 	int rid, fields = Ph_EV_PTR_MOTION_BUTTON | Ph_EV_PTR_MOTION_NOBUTTON;
   167 	PhRegion_t region;
   168 
   169 	if( window )
   170 	{
   171 		rid = PtWidgetRid( window );
   172 		if( rid != 0 && PhRegionQuery( rid, &region, NULL, NULL, 0 ) == 0 )
   173 		{
   174 			region.events_sense = ( region.events_sense & ~fields ) |
   175 				( flags & fields );
   176 			PhRegionChange( Ph_REGION_EV_SENSE, 0, &region,
   177 					NULL, NULL );
   178 		}
   179 	}
   180 }
   181 
   182 /* Convert the photon button state value to an SDL value */
   183 static Uint8 ph2sdl_mousebutton( unsigned short button_state )
   184 {
   185 	Uint8 mouse_button = 0;
   186 
   187 	if( button_state & Ph_BUTTON_SELECT )
   188 			mouse_button |= SDL_BUTTON_LEFT;
   189 	if( button_state & Ph_BUTTON_MENU )
   190 			mouse_button |= SDL_BUTTON_RIGHT;
   191 	if( button_state & Ph_BUTTON_ADJUST )
   192 			mouse_button |= SDL_BUTTON_MIDDLE;
   193 
   194 	return( mouse_button );
   195 }
   196 
   197 static int ph_DispatchEvent(_THIS)
   198 {
   199 	int posted;
   200 	PhRect_t* rect;
   201 	PhPointerEvent_t* pointerEvent;
   202 	PhKeyEvent_t* keyEvent;
   203 	PhWindowEvent_t* winEvent;
   204 	int i, buttons;
   205 	SDL_Rect sdlrects[50]; 
   206 	
   207 	posted = 0;
   208 	
   209 	switch (event->type) {
   210 		case Ph_EV_BOUNDARY:
   211 		{
   212 			if (event->subtype == Ph_EV_PTR_ENTER)
   213 				posted = SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS);
   214 			else if (event->subtype ==Ph_EV_PTR_LEAVE)
   215 				posted = SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS);	
   216 		}
   217 		break;
   218 
   219 		case Ph_EV_PTR_MOTION_BUTTON:
   220 		case Ph_EV_PTR_MOTION_NOBUTTON:
   221 		{
   222 			if ( SDL_VideoSurface ) {
   223 				pointerEvent = PhGetData( event );
   224 				rect = PhGetRects( event );
   225 				posted = SDL_PrivateMouseMotion(0, 0,
   226 						rect->ul.x, rect->ul.y);		
   227 			}
   228 		}
   229 		break;
   230 
   231 		case Ph_EV_BUT_PRESS:
   232 		{
   233 			pointerEvent = PhGetData( event );
   234 			buttons = ph2sdl_mousebutton( pointerEvent->buttons );
   235 			if( buttons != 0 )
   236 			posted = SDL_PrivateMouseButton( SDL_PRESSED, buttons,
   237 					0, 0 );
   238 		}
   239 		break;
   240 
   241 		case Ph_EV_BUT_RELEASE:
   242 		{
   243 			pointerEvent = PhGetData(event);
   244 			buttons = ph2sdl_mousebutton(pointerEvent->buttons);
   245 			if( event->subtype == Ph_EV_RELEASE_REAL && 
   246 					buttons != 0 )
   247 			{
   248 				posted = SDL_PrivateMouseButton( SDL_RELEASED,
   249 						buttons, 0, 0 );
   250 			}
   251 			else if( event->subtype == Ph_EV_RELEASE_PHANTOM )
   252 			{
   253 				/* If the mouse is outside the window,
   254 				 * only a phantom release event is sent, so
   255 				 * check if the window doesn't have mouse focus.
   256 				 * Not perfect, maybe checking the mouse button
   257 				 * state for Ph_EV_BOUNDARY events would be
   258 				 * better. */
   259 				if( ( SDL_GetAppState() & SDL_APPMOUSEFOCUS ) == 0 )
   260 				{
   261 					posted = SDL_PrivateMouseButton( SDL_RELEASED,
   262 						buttons, 0, 0 );
   263 				}
   264 			}
   265 		}
   266 		break;
   267 
   268 		case Ph_EV_WM:
   269 		{
   270 			winEvent = PhGetData( event );
   271 			
   272 			/* losing focus */
   273 			if ((winEvent->event_f==Ph_WM_FOCUS)&&
   274 				(winEvent->event_state==Ph_WM_EVSTATE_FOCUSLOST))
   275 			{
   276 				set_motion_sensitivity(this, Ph_EV_PTR_MOTION_BUTTON);
   277 				posted = SDL_PrivateAppActive(0, SDL_APPINPUTFOCUS);	
   278 
   279 				/* Queue leaving fullscreen mode */
   280 				switch_waiting = 0x01;
   281 				switch_time = SDL_GetTicks() + 200;
   282 			}
   283 
   284 			/* gaining focus */
   285 			else if ((winEvent->event_f==Ph_WM_FOCUS)&&
   286 					(winEvent->event_state==Ph_WM_EVSTATE_FOCUS))
   287 			{
   288 				set_motion_sensitivity(this, -1);
   289 				posted = SDL_PrivateAppActive(1, SDL_APPINPUTFOCUS);
   290 
   291 				/* Queue entry into fullscreen mode */
   292 				switch_waiting = 0x01 | SDL_FULLSCREEN;
   293 				switch_time = SDL_GetTicks() + 1500;
   294 			}
   295 
   296 			/* request to quit */
   297 			else if (winEvent->event_f==Ph_WM_CLOSE)
   298 			{
   299 				posted = SDL_PrivateQuit();
   300 			}
   301 		}
   302 		break;
   303 		
   304 		/* window has been resized, moved or removed */
   305 		case Ph_EV_EXPOSE:
   306 		{
   307 			if (SDL_VideoSurface)
   308 			{
   309 				rect = PhGetRects( event );
   310 
   311 				//PgSetClipping(1, rect );
   312 				for(i=0;i<event->num_rects;i++)
   313 				{
   314 					sdlrects[i].x = rect[i].ul.x;
   315 					sdlrects[i].y = rect[i].ul.y;
   316 					sdlrects[i].w = rect[i].lr.x - rect[i].ul.x + 1;
   317 					sdlrects[i].h = rect[i].lr.y - rect[i].ul.y + 1;
   318 				}
   319 
   320 				this->UpdateRects(this, event->num_rects, sdlrects);
   321 
   322 			}
   323 		}
   324 		break;
   325 
   326 		case Ph_EV_KEY:
   327 		{
   328 	
   329 			SDL_keysym keysym;
   330 			
   331 			posted = 0;
   332 			
   333 			keyEvent = PhGetData( event );
   334 
   335 			if (Pk_KF_Key_Down & keyEvent->key_flags)
   336 			{
   337 				
   338 				posted = SDL_PrivateKeyboard(SDL_PRESSED,
   339                 			ph_TranslateKey( keyEvent, &keysym));
   340 			}
   341 			else /* must be key release */
   342  			{
   343  				/* Ignore repeated key release events */
   344 				/*if (! Pk_KF_Key_Repeat & keyEvent->key_flags )*/
   345 				
   346 					posted = SDL_PrivateKeyboard(SDL_RELEASED,
   347         					ph_TranslateKey( keyEvent, &keysym));
   348 				/*}*/
   349 			}
   350 		}
   351 		break;
   352 	}
   353 	
   354 		
   355 	
   356 	return(posted);
   357 }
   358 
   359 /* perform a blocking read if no events available */
   360 int ph_Pending(_THIS)
   361 {
   362 	/* Flush the display connection and look to see if events are queued */
   363 	PgFlush();
   364 
   365      while( 1 )
   366       {   //note this is a non-blocking call
   367           switch( PhEventPeek( event, EVENT_SIZE ) )
   368            {
   369               case Ph_EVENT_MSG:
   370                  
   371                  return 1;
   372                  break;
   373               case -1:
   374                  perror( "PhEventNext failed" );
   375                  break;
   376               default:
   377              	  
   378                 return 0;
   379        }
   380    }
   381 
   382 	/* Oh well, nothing is ready .. */
   383 	return(0);
   384 }
   385 
   386 /*
   387 SAMPLE EVENT PUMP
   388 =================
   389 static void update( int block ){
   390 
   391     int ch,fl;
   392     PhKeyEvent_t *key;
   393 
   394     for( ;; ){
   395 
   396         if( block ){
   397             do{
   398                 fl=PhEventNext( event,EVENT_SIZE );
   399             }while( fl!=Ph_EVENT_MSG );
   400             block=0;
   401         }else{
   402             do{
   403                 fl=PhEventPeek( event,EVENT_SIZE );
   404                 if( !fl ) return;
   405             }while( fl!=Ph_EVENT_MSG );
   406         }
   407 
   408         switch( event->type ){
   409         case Ph_EV_KEY:
   410             key=PhGetData( event );
   411             ch=key->key_cap;    // & 127;
   412             fl=key->key_flags;
   413             if( ch<32 || ch>127 ) break;
   414             if( fl & Pk_KF_Key_Down ){
   415                 if( !(fl & Pk_KF_Key_Repeat) ){
   416                     if( queput-queget<QUE_SIZE ) keyque[ queput++ & QUE_MASK ]=ch;
   417                     keyMatrix[ch]=1;
   418                 }
   419             }else{
   420                 keyMatrix[ch]=0;
   421             }
   422             break;
   423         default:
   424             PtEventHandler( event );
   425         }
   426     }
   427 }
   428 */
   429 
   430 void ph_PumpEvents(_THIS)
   431 {
   432 	int pending;
   433 
   434 	/* Keep processing pending events */
   435 	pending = 0;
   436 	while ( ph_Pending(this) ) {
   437 		ph_DispatchEvent(this);
   438 		++pending;
   439 	}
   440 	if ( switch_waiting ) {
   441 		Uint32 now;
   442 
   443 		now  = SDL_GetTicks();
   444 		if ( pending || !SDL_VideoSurface ) {
   445 			/* Try again later... */
   446 			if ( switch_waiting & SDL_FULLSCREEN ) {
   447 				switch_time = now + 1500;
   448 			} else {
   449 				switch_time = now + 200;
   450 			}
   451 		} else if ( now >= switch_time ) {
   452 			Uint32 go_fullscreen;
   453 
   454 			go_fullscreen = switch_waiting & SDL_FULLSCREEN;
   455 			switch_waiting = 0;
   456 			if ( SDL_VideoSurface->flags & SDL_FULLSCREEN ) {
   457 				if ( go_fullscreen ) {
   458 					ph_EnterFullScreen(this);
   459 				} else {
   460 					ph_LeaveFullScreen(this);
   461 				}
   462 			}
   463 			/* Handle focus in/out when grabbed */
   464 /*
   465 			if ( go_fullscreen ) {
   466 				ph_GrabInputNoLock(this, this->input_grab);
   467 			} else {
   468 				ph_GrabInputNoLock(this, SDL_GRAB_OFF);
   469 			}
   470 */
   471 		}
   472 	}
   473 }
   474 
   475 void ph_InitKeymap(void)
   476 {
   477 	int i;
   478 
   479 	/* Odd keys used in international keyboards */
   480 	for ( i=0; i<SDL_TABLESIZE(ODD_keymap); ++i )
   481 		ODD_keymap[i] = SDLK_UNKNOWN;
   482 
   483 	/* Map the miscellaneous keys */
   484 	for ( i=0; i<SDL_TABLESIZE(MISC_keymap); ++i )
   485 		MISC_keymap[i] = SDLK_UNKNOWN;
   486 
   487 	MISC_keymap[Pk_BackSpace&0xFF] = SDLK_BACKSPACE;
   488 	MISC_keymap[Pk_Tab&0xFF] = SDLK_TAB;
   489 	MISC_keymap[Pk_Clear&0xFF] = SDLK_CLEAR;
   490 	MISC_keymap[Pk_Return&0xFF] = SDLK_RETURN;
   491 	MISC_keymap[Pk_Pause&0xFF] = SDLK_PAUSE;
   492 	MISC_keymap[Pk_Escape&0xFF] = SDLK_ESCAPE;
   493 	MISC_keymap[Pk_Delete&0xFF] = SDLK_DELETE;
   494 
   495 	MISC_keymap[Pk_KP_0&0xFF] = SDLK_KP0;
   496 	MISC_keymap[Pk_KP_1&0xFF] = SDLK_KP1;
   497 	MISC_keymap[Pk_KP_2&0xFF] = SDLK_KP2;
   498 	MISC_keymap[Pk_KP_3&0xFF] = SDLK_KP3;
   499 	MISC_keymap[Pk_KP_4&0xFF] = SDLK_KP4;
   500 	MISC_keymap[Pk_KP_5&0xFF] = SDLK_KP5;
   501 	MISC_keymap[Pk_KP_6&0xFF] = SDLK_KP6;
   502 	MISC_keymap[Pk_KP_7&0xFF] = SDLK_KP7;
   503 	MISC_keymap[Pk_KP_8&0xFF] = SDLK_KP8;
   504 	MISC_keymap[Pk_KP_9&0xFF] = SDLK_KP9;
   505 
   506 	MISC_keymap[Pk_KP_Decimal&0xFF] = SDLK_KP_PERIOD;
   507 	MISC_keymap[Pk_KP_Divide&0xFF] = SDLK_KP_DIVIDE;
   508 	MISC_keymap[Pk_KP_Multiply&0xFF] = SDLK_KP_MULTIPLY;
   509 	MISC_keymap[Pk_KP_Subtract&0xFF] = SDLK_KP_MINUS;
   510 	MISC_keymap[Pk_KP_Add&0xFF] = SDLK_KP_PLUS;
   511 	MISC_keymap[Pk_KP_Enter&0xFF] = SDLK_KP_ENTER;
   512 	MISC_keymap[Pk_KP_Equal&0xFF] = SDLK_KP_EQUALS;
   513 
   514 	MISC_keymap[Pk_Up&0xFF] = SDLK_UP;
   515 	MISC_keymap[Pk_Down&0xFF] = SDLK_DOWN;
   516 	MISC_keymap[Pk_Right&0xFF] = SDLK_RIGHT;
   517 	MISC_keymap[Pk_Left&0xFF] = SDLK_LEFT;
   518 	MISC_keymap[Pk_Insert&0xFF] = SDLK_INSERT;
   519 	MISC_keymap[Pk_Home&0xFF] = SDLK_HOME;
   520 	MISC_keymap[Pk_End&0xFF] = SDLK_END;
   521 	MISC_keymap[Pk_Pg_Up&0xFF] = SDLK_PAGEUP;
   522 	MISC_keymap[Pk_Pg_Down&0xFF] = SDLK_PAGEDOWN;
   523 
   524 	MISC_keymap[Pk_F1&0xFF] = SDLK_F1;
   525 	MISC_keymap[Pk_F2&0xFF] = SDLK_F2;
   526 	MISC_keymap[Pk_F3&0xFF] = SDLK_F3;
   527 	MISC_keymap[Pk_F4&0xFF] = SDLK_F4;
   528 	MISC_keymap[Pk_F5&0xFF] = SDLK_F5;
   529 	MISC_keymap[Pk_F6&0xFF] = SDLK_F6;
   530 	MISC_keymap[Pk_F7&0xFF] = SDLK_F7;
   531 	MISC_keymap[Pk_F8&0xFF] = SDLK_F8;
   532 	MISC_keymap[Pk_F9&0xFF] = SDLK_F9;
   533 	MISC_keymap[Pk_F10&0xFF] = SDLK_F10;
   534 	MISC_keymap[Pk_F11&0xFF] = SDLK_F11;
   535 	MISC_keymap[Pk_F12&0xFF] = SDLK_F12;
   536 	MISC_keymap[Pk_F13&0xFF] = SDLK_F13;
   537 	MISC_keymap[Pk_F14&0xFF] = SDLK_F14;
   538 	MISC_keymap[Pk_F15&0xFF] = SDLK_F15;
   539 
   540 	MISC_keymap[Pk_Num_Lock&0xFF] = SDLK_NUMLOCK;
   541 	MISC_keymap[Pk_Caps_Lock&0xFF] = SDLK_CAPSLOCK;
   542 	MISC_keymap[Pk_Scroll_Lock&0xFF] = SDLK_SCROLLOCK;
   543 	MISC_keymap[Pk_Shift_R&0xFF] = SDLK_RSHIFT;
   544 	MISC_keymap[Pk_Shift_L&0xFF] = SDLK_LSHIFT;
   545 	MISC_keymap[Pk_Control_R&0xFF] = SDLK_RCTRL;
   546 	MISC_keymap[Pk_Control_L&0xFF] = SDLK_LCTRL;
   547 	MISC_keymap[Pk_Alt_R&0xFF] = SDLK_RALT;
   548 	MISC_keymap[Pk_Alt_L&0xFF] = SDLK_LALT;
   549 	MISC_keymap[Pk_Meta_R&0xFF] = SDLK_RMETA;
   550 	MISC_keymap[Pk_Meta_L&0xFF] = SDLK_LMETA;
   551 	MISC_keymap[Pk_Super_L&0xFF] = SDLK_LSUPER; /* Left "Windows" */
   552 	MISC_keymap[Pk_Super_R&0xFF] = SDLK_RSUPER; /* Right "Windows */
   553 	MISC_keymap[Pk_Mode_switch&0xFF] = SDLK_MODE; /* "Alt Gr" key */
   554 
   555 	MISC_keymap[Pk_Help&0xFF] = SDLK_HELP;
   556 	MISC_keymap[Pk_Print&0xFF] = SDLK_PRINT;
   557 //	MISC_keymap[Pk_Sys_Req] = SDLK_SYSREQ;
   558 	MISC_keymap[Pk_Break&0xFF] = SDLK_BREAK;
   559 	MISC_keymap[Pk_Menu&0xFF] = SDLK_MENU;
   560 	MISC_keymap[Pk_Hyper_R&0xFF] = SDLK_MENU;   /* Windows "Menu" key */
   561 }
   562 
   563 static unsigned long cap;
   564 
   565 SDL_keysym *ph_TranslateKey(PhKeyEvent_t *key, SDL_keysym *keysym)
   566 {
   567 /*	
   568 	'sym' is set to the value of the key with modifiers applied to it. 
   569 	This member is valid only if Pk_KF_Sym_Valid is set in the key_flags.
   570 	We will assume it is valid.
   571 */
   572 	cap = key->key_cap;
   573 	switch (cap>>8) {
   574             case 0x00:  /* Latin 1 */
   575             case 0x01:  /* Latin 2 */
   576             case 0x02:  /* Latin 3 */
   577             case 0x03:  /* Latin 4 */
   578             case 0x04:  /* Katakana */
   579             case 0x05:  /* Arabic */
   580             case 0x06:  /* Cyrillic */
   581             case 0x07:  /* Greek */
   582             case 0x08:  /* Technical */
   583             case 0x0A:  /* Publishing */
   584             case 0x0C:  /* Hebrew */
   585             case 0x0D:  /* Thai */
   586                 keysym->sym = (SDLKey)(cap&0xFF);
   587                 /* Map capital letter syms to lowercase */
   588                 if ((keysym->sym >= 'A')&&(keysym->sym <= 'Z'))
   589                     keysym->sym += ('a'-'A');
   590                 break;
   591 //            case 0xFE:
   592 //                keysym->sym = ODD_keymap[sym&0xFF];
   593 //                break;
   594             case 0xF0:
   595                 keysym->sym = MISC_keymap[cap&0xFF];
   596                 break;
   597             default:
   598                 fprintf(stderr,"Photon: Unknown key_cap, cap = 0x%.4x\n", (unsigned int)cap);
   599                 break;
   600 	}
   601 	keysym->scancode = key->key_scan;
   602 	return (keysym);
   603 }
   604 
   605 void ph_InitOSKeymap(_THIS)
   606 {
   607 	ph_InitKeymap();
   608 }
   609