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