src/video/x11/SDL_x11events.c
author Sam Lantinga <slouken@libsdl.org>
Fri, 10 Feb 2006 07:03:22 +0000
changeset 1359 1e4ba2e063b4
parent 1358 c71e05b4dc2e
child 1361 19418e4422cb
permissions -rw-r--r--
*** empty log message ***
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2006 Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Lesser General Public
     7     License as published by the Free Software Foundation; either
     8     version 2.1 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     Lesser General Public License for more details.
    14 
    15     You should have received a copy of the GNU Lesser General Public
    16     License along with this library; if not, write to the Free Software
    17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 */
    22 
    23 /* Handle the event stream, converting X11 events into SDL events */
    24 
    25 #include <setjmp.h>
    26 #include <X11/Xlib.h>
    27 #include <X11/Xutil.h>
    28 #include <X11/keysym.h>
    29 #ifdef __SVR4
    30 #include <X11/Sunkeysym.h>
    31 #endif
    32 #include <sys/types.h>
    33 #include <sys/time.h>
    34 #include <unistd.h>
    35 
    36 #include "SDL_timer.h"
    37 #include "SDL_syswm.h"
    38 #include "SDL_sysevents.h"
    39 #include "SDL_sysvideo.h"
    40 #include "SDL_events_c.h"
    41 #include "SDL_x11video.h"
    42 #include "SDL_x11dga_c.h"
    43 #include "SDL_x11modes_c.h"
    44 #include "SDL_x11image_c.h"
    45 #include "SDL_x11gamma_c.h"
    46 #include "SDL_x11wm_c.h"
    47 #include "SDL_x11mouse_c.h"
    48 #include "SDL_x11events_c.h"
    49 
    50 
    51 /* Define this if you want to debug X11 events */
    52 /*#define DEBUG_XEVENTS*/
    53 
    54 /* The translation tables from an X11 keysym to a SDL keysym */
    55 static SDLKey ODD_keymap[256];
    56 static SDLKey MISC_keymap[256];
    57 SDLKey X11_TranslateKeycode(Display *display, KeyCode kc);
    58 
    59 
    60 #ifdef X_HAVE_UTF8_STRING
    61 Uint32 Utf8ToUcs4(const Uint8 *utf8)
    62 {
    63 	Uint32 c;
    64 	int i = 1;
    65 	int noOctets = 0;
    66 	int firstOctetMask = 0;
    67 	unsigned char firstOctet = utf8[0];
    68 	if (firstOctet < 0x80) {
    69 		/*
    70 		  Characters in the range:
    71 		    00000000 to 01111111 (ASCII Range)
    72 		  are stored in one octet:
    73 		    0xxxxxxx (The same as its ASCII representation)
    74 		  The least 6 significant bits of the first octet is the most 6 significant nonzero bits
    75 		  of the UCS4 representation.
    76 		*/
    77 		noOctets = 1;
    78 		firstOctetMask = 0x7F;  /* 0(1111111) - The most significant bit is ignored */
    79 	} else if ((firstOctet & 0xE0) /* get the most 3 significant bits by AND'ing with 11100000 */
    80 	              == 0xC0 ) {  /* see if those 3 bits are 110. If so, the char is in this range */
    81 		/*
    82 		  Characters in the range:
    83 		    00000000 10000000 to 00000111 11111111
    84 		  are stored in two octets:
    85 		    110xxxxx 10xxxxxx
    86 		  The least 5 significant bits of the first octet is the most 5 significant nonzero bits
    87 		  of the UCS4 representation.
    88 		*/
    89 		noOctets = 2;
    90 		firstOctetMask = 0x1F;  /* 000(11111) - The most 3 significant bits are ignored */
    91 	} else if ((firstOctet & 0xF0) /* get the most 4 significant bits by AND'ing with 11110000 */
    92 	              == 0xE0) {  /* see if those 4 bits are 1110. If so, the char is in this range */
    93 		/*
    94 		  Characters in the range:
    95 		    00001000 00000000 to 11111111 11111111
    96 		  are stored in three octets:
    97 		    1110xxxx 10xxxxxx 10xxxxxx
    98 		  The least 4 significant bits of the first octet is the most 4 significant nonzero bits
    99 		  of the UCS4 representation.
   100 		*/
   101 		noOctets = 3;
   102 		firstOctetMask = 0x0F; /* 0000(1111) - The most 4 significant bits are ignored */
   103 	} else if ((firstOctet & 0xF8) /* get the most 5 significant bits by AND'ing with 11111000 */
   104 	              == 0xF0) {  /* see if those 5 bits are 11110. If so, the char is in this range */
   105 		/*
   106 		  Characters in the range:
   107 		    00000001 00000000 00000000 to 00011111 11111111 11111111
   108 		  are stored in four octets:
   109 		    11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
   110 		  The least 3 significant bits of the first octet is the most 3 significant nonzero bits
   111 		  of the UCS4 representation.
   112 		*/
   113 		noOctets = 4;
   114 		firstOctetMask = 0x07; /* 11110(111) - The most 5 significant bits are ignored */
   115 	} else if ((firstOctet & 0xFC) /* get the most 6 significant bits by AND'ing with 11111100 */
   116 	              == 0xF8) { /* see if those 6 bits are 111110. If so, the char is in this range */
   117 		/*
   118 		  Characters in the range:
   119 		    00000000 00100000 00000000 00000000 to
   120 		    00000011 11111111 11111111 11111111
   121 		  are stored in five octets:
   122 		    111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
   123 		  The least 2 significant bits of the first octet is the most 2 significant nonzero bits
   124 		  of the UCS4 representation.
   125 		*/
   126 		noOctets = 5;
   127 		firstOctetMask = 0x03; /* 111110(11) - The most 6 significant bits are ignored */
   128 	} else if ((firstOctet & 0xFE) /* get the most 7 significant bits by AND'ing with 11111110 */
   129 	              == 0xFC) { /* see if those 7 bits are 1111110. If so, the char is in this range */
   130 		/*
   131 		  Characters in the range:
   132 		    00000100 00000000 00000000 00000000 to
   133 		    01111111 11111111 11111111 11111111
   134 		  are stored in six octets:
   135 		    1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
   136 		  The least significant bit of the first octet is the most significant nonzero bit
   137 		  of the UCS4 representation.
   138 		*/
   139 		noOctets = 6;
   140 		firstOctetMask = 0x01; /* 1111110(1) - The most 7 significant bits are ignored */
   141 	} else
   142 		return 0;  /* The given chunk is not a valid UTF-8 encoded Unicode character */
   143 	
   144 	/*
   145 	  The least noOctets significant bits of the first octet is the most 2 significant nonzero bits
   146 	  of the UCS4 representation.
   147 	  The first 6 bits of the UCS4 representation is the least 8-noOctets-1 significant bits of
   148 	  firstOctet if the character is not ASCII. If so, it's the least 7 significant bits of firstOctet.
   149 	  This done by AND'ing firstOctet with its mask to trim the bits used for identifying the
   150 	  number of continuing octets (if any) and leave only the free bits (the x's)
   151 	  Sample:
   152 	  1-octet:    0xxxxxxx  &  01111111 = 0xxxxxxx
   153 	  2-octets:  110xxxxx  &  00011111 = 000xxxxx
   154 	*/
   155 	c = firstOctet & firstOctetMask;
   156 	
   157 	/* Now, start filling c.ucs4 with the bits from the continuing octets from utf8. */
   158 	for (i = 1; i < noOctets; i++) {
   159 		/* A valid continuing octet is of the form 10xxxxxx */
   160 		if ((utf8[i] & 0xC0) /* get the most 2 significant bits by AND'ing with 11000000 */
   161 		    != 0x80) /* see if those 2 bits are 10. If not, the is a malformed sequence. */
   162 			/*The given chunk is a partial sequence at the end of a string that could
   163 			   begin a valid character */
   164 			return 0;
   165 		
   166 		/* Make room for the next 6-bits */
   167 		c <<= 6;
   168 		
   169 		/*
   170 		  Take only the least 6 significance bits of the current octet (utf8[i]) and fill the created room
   171 		  of c.ucs4 with them.
   172 		  This done by AND'ing utf8[i] with 00111111 and the OR'ing the result with c.ucs4.
   173 		*/
   174 		c |= utf8[i] & 0x3F;
   175 	}
   176 	return c;
   177 }
   178 #endif
   179 
   180 /* Check to see if this is a repeated key.
   181    (idea shamelessly lifted from GII -- thanks guys! :)
   182  */
   183 static int X11_KeyRepeat(Display *display, XEvent *event)
   184 {
   185 	XEvent peekevent;
   186 	int repeated;
   187 
   188 	repeated = 0;
   189 	if ( pXPending(display) ) {
   190 		pXPeekEvent(display, &peekevent);
   191 		if ( (peekevent.type == KeyPress) &&
   192 		     (peekevent.xkey.keycode == event->xkey.keycode) &&
   193 		     ((peekevent.xkey.time-event->xkey.time) < 2) ) {
   194 			repeated = 1;
   195 			pXNextEvent(display, &peekevent);
   196 		}
   197 	}
   198 	return(repeated);
   199 }
   200 
   201 /* Note:  The X server buffers and accumulates mouse motion events, so
   202    the motion event generated by the warp may not appear exactly as we
   203    expect it to.  We work around this (and improve performance) by only
   204    warping the pointer when it reaches the edge, and then wait for it.
   205 */
   206 #define MOUSE_FUDGE_FACTOR	8
   207 
   208 static __inline__ int X11_WarpedMotion(_THIS, XEvent *xevent)
   209 {
   210 	int w, h, i;
   211 	int deltax, deltay;
   212 	int posted;
   213 
   214 	w = SDL_VideoSurface->w;
   215 	h = SDL_VideoSurface->h;
   216 	deltax = xevent->xmotion.x - mouse_last.x;
   217 	deltay = xevent->xmotion.y - mouse_last.y;
   218 #ifdef DEBUG_MOTION
   219   printf("Warped mouse motion: %d,%d\n", deltax, deltay);
   220 #endif
   221 	mouse_last.x = xevent->xmotion.x;
   222 	mouse_last.y = xevent->xmotion.y;
   223 	posted = SDL_PrivateMouseMotion(0, 1, deltax, deltay);
   224 
   225 	if ( (xevent->xmotion.x < MOUSE_FUDGE_FACTOR) ||
   226 	     (xevent->xmotion.x > (w-MOUSE_FUDGE_FACTOR)) ||
   227 	     (xevent->xmotion.y < MOUSE_FUDGE_FACTOR) ||
   228 	     (xevent->xmotion.y > (h-MOUSE_FUDGE_FACTOR)) ) {
   229 		/* Get the events that have accumulated */
   230 		while ( pXCheckTypedEvent(SDL_Display, MotionNotify, xevent) ) {
   231 			deltax = xevent->xmotion.x - mouse_last.x;
   232 			deltay = xevent->xmotion.y - mouse_last.y;
   233 #ifdef DEBUG_MOTION
   234   printf("Extra mouse motion: %d,%d\n", deltax, deltay);
   235 #endif
   236 			mouse_last.x = xevent->xmotion.x;
   237 			mouse_last.y = xevent->xmotion.y;
   238 			posted += SDL_PrivateMouseMotion(0, 1, deltax, deltay);
   239 		}
   240 		mouse_last.x = w/2;
   241 		mouse_last.y = h/2;
   242 		pXWarpPointer(SDL_Display, None, SDL_Window, 0, 0, 0, 0,
   243 					mouse_last.x, mouse_last.y);
   244 		for ( i=0; i<10; ++i ) {
   245         		pXMaskEvent(SDL_Display, PointerMotionMask, xevent);
   246 			if ( (xevent->xmotion.x >
   247 			          (mouse_last.x-MOUSE_FUDGE_FACTOR)) &&
   248 			     (xevent->xmotion.x <
   249 			          (mouse_last.x+MOUSE_FUDGE_FACTOR)) &&
   250 			     (xevent->xmotion.y >
   251 			          (mouse_last.y-MOUSE_FUDGE_FACTOR)) &&
   252 			     (xevent->xmotion.y <
   253 			          (mouse_last.y+MOUSE_FUDGE_FACTOR)) ) {
   254 				break;
   255 			}
   256 #ifdef DEBUG_XEVENTS
   257   printf("Lost mouse motion: %d,%d\n", xevent->xmotion.x, xevent->xmotion.y);
   258 #endif
   259 		}
   260 #ifdef DEBUG_XEVENTS
   261 		if ( i == 10 ) {
   262 			printf("Warning: didn't detect mouse warp motion\n");
   263 		}
   264 #endif
   265 	}
   266 	return(posted);
   267 }
   268 
   269 static int X11_DispatchEvent(_THIS)
   270 {
   271 	int posted;
   272 	XEvent xevent;
   273 
   274 	SDL_memset(&xevent, '\0', sizeof (XEvent));  /* valgrind fix. --ryan. */
   275 	pXNextEvent(SDL_Display, &xevent);
   276 
   277 	posted = 0;
   278 	switch (xevent.type) {
   279 
   280 	    /* Gaining mouse coverage? */
   281 	    case EnterNotify: {
   282 #ifdef DEBUG_XEVENTS
   283 printf("EnterNotify! (%d,%d)\n", xevent.xcrossing.x, xevent.xcrossing.y);
   284 if ( xevent.xcrossing.mode == NotifyGrab )
   285 printf("Mode: NotifyGrab\n");
   286 if ( xevent.xcrossing.mode == NotifyUngrab )
   287 printf("Mode: NotifyUngrab\n");
   288 #endif
   289 		if ( (xevent.xcrossing.mode != NotifyGrab) &&
   290 		     (xevent.xcrossing.mode != NotifyUngrab) ) {
   291 			if ( this->input_grab == SDL_GRAB_OFF ) {
   292 				posted = SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS);
   293 			} else {
   294 				posted = SDL_PrivateMouseMotion(0, 0,
   295 						xevent.xcrossing.x,
   296 						xevent.xcrossing.y);
   297 			}
   298 		}
   299 	    }
   300 	    break;
   301 
   302 	    /* Losing mouse coverage? */
   303 	    case LeaveNotify: {
   304 #ifdef DEBUG_XEVENTS
   305 printf("LeaveNotify! (%d,%d)\n", xevent.xcrossing.x, xevent.xcrossing.y);
   306 if ( xevent.xcrossing.mode == NotifyGrab )
   307 printf("Mode: NotifyGrab\n");
   308 if ( xevent.xcrossing.mode == NotifyUngrab )
   309 printf("Mode: NotifyUngrab\n");
   310 #endif
   311 		if ( (xevent.xcrossing.mode != NotifyGrab) &&
   312 		     (xevent.xcrossing.mode != NotifyUngrab) &&
   313 		     (xevent.xcrossing.detail != NotifyInferior) ) {
   314 			if ( this->input_grab == SDL_GRAB_OFF ) {
   315 				posted = SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS);
   316 			} else {
   317 				posted = SDL_PrivateMouseMotion(0, 0,
   318 						xevent.xcrossing.x,
   319 						xevent.xcrossing.y);
   320 			}
   321 		}
   322 	    }
   323 	    break;
   324 
   325 	    /* Gaining input focus? */
   326 	    case FocusIn: {
   327 #ifdef DEBUG_XEVENTS
   328 printf("FocusIn!\n");
   329 #endif
   330 		posted = SDL_PrivateAppActive(1, SDL_APPINPUTFOCUS);
   331 
   332 #ifdef X_HAVE_UTF8_STRING
   333 		if ( SDL_IC != NULL ) {
   334 			pXSetICFocus(SDL_IC);
   335 		}
   336 #endif
   337 		/* Queue entry into fullscreen mode */
   338 		switch_waiting = 0x01 | SDL_FULLSCREEN;
   339 		switch_time = SDL_GetTicks() + 1500;
   340 	    }
   341 	    break;
   342 
   343 	    /* Losing input focus? */
   344 	    case FocusOut: {
   345 #ifdef DEBUG_XEVENTS
   346 printf("FocusOut!\n");
   347 #endif
   348 		posted = SDL_PrivateAppActive(0, SDL_APPINPUTFOCUS);
   349 
   350 #ifdef X_HAVE_UTF8_STRING
   351 		if ( SDL_IC != NULL ) {
   352 			pXUnsetICFocus(SDL_IC);
   353 		}
   354 #endif
   355 		/* Queue leaving fullscreen mode */
   356 		switch_waiting = 0x01;
   357 		switch_time = SDL_GetTicks() + 200;
   358 	    }
   359 	    break;
   360 
   361 	    /* Generated upon EnterWindow and FocusIn */
   362 	    case KeymapNotify: {
   363 #ifdef DEBUG_XEVENTS
   364 printf("KeymapNotify!\n");
   365 #endif
   366 		X11_SetKeyboardState(SDL_Display,  xevent.xkeymap.key_vector);
   367 	    }
   368 	    break;
   369 
   370 	    /* Mouse motion? */
   371 	    case MotionNotify: {
   372 		if ( SDL_VideoSurface ) {
   373 			if ( mouse_relative ) {
   374 				if ( using_dga & DGA_MOUSE ) {
   375 #ifdef DEBUG_MOTION
   376   printf("DGA motion: %d,%d\n", xevent.xmotion.x_root, xevent.xmotion.y_root);
   377 #endif
   378 					posted = SDL_PrivateMouseMotion(0, 1,
   379 							xevent.xmotion.x_root,
   380 							xevent.xmotion.y_root);
   381 				} else {
   382 					posted = X11_WarpedMotion(this,&xevent);
   383 				}
   384 			} else {
   385 #ifdef DEBUG_MOTION
   386   printf("X11 motion: %d,%d\n", xevent.xmotion.x, xevent.xmotion.y);
   387 #endif
   388 				posted = SDL_PrivateMouseMotion(0, 0,
   389 						xevent.xmotion.x,
   390 						xevent.xmotion.y);
   391 			}
   392 		}
   393 	    }
   394 	    break;
   395 
   396 	    /* Mouse button press? */
   397 	    case ButtonPress: {
   398 		posted = SDL_PrivateMouseButton(SDL_PRESSED, 
   399 					xevent.xbutton.button, 0, 0);
   400 	    }
   401 	    break;
   402 
   403 	    /* Mouse button release? */
   404 	    case ButtonRelease: {
   405 		posted = SDL_PrivateMouseButton(SDL_RELEASED, 
   406 					xevent.xbutton.button, 0, 0);
   407 	    }
   408 	    break;
   409 
   410 	    /* Key press? */
   411 	    case KeyPress: {
   412 		static SDL_keysym saved_keysym;
   413 		SDL_keysym keysym;
   414 		KeyCode keycode = xevent.xkey.keycode;
   415 
   416 #ifdef DEBUG_XEVENTS
   417 printf("KeyPress (X11 keycode = 0x%X)\n", xevent.xkey.keycode);
   418 #endif
   419 		/* Get the translated SDL virtual keysym */
   420 		if ( keycode ) {
   421 			keysym.scancode = keycode;
   422 			keysym.sym = X11_TranslateKeycode(SDL_Display, keycode);
   423 			keysym.mod = KMOD_NONE;
   424 			keysym.unicode = 0;
   425 		} else {
   426 			keysym = saved_keysym;
   427 		}
   428 
   429 		/* If we're not doing translation, we're done! */
   430 		if ( !SDL_TranslateUNICODE ) {
   431 			posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym);
   432 			break;
   433 		}
   434 
   435 		if ( pXFilterEvent(&xevent, None) ) {
   436 			if ( xevent.xkey.keycode ) {
   437 				posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym);
   438 			} else {
   439 				/* Save event to be associated with IM text
   440 				   In 1.3 we'll have a text event instead.. */
   441 				saved_keysym = keysym;
   442 			}
   443 			break;
   444 		}
   445 
   446 		/* Look up the translated value for the key event */
   447 #ifdef X_HAVE_UTF8_STRING
   448 		if ( SDL_IC != NULL ) {
   449 			static Status state;
   450 			/* A UTF-8 character can be at most 6 bytes */
   451 			char keybuf[6];
   452 			if ( pXutf8LookupString(SDL_IC, &xevent.xkey,
   453 			                        keybuf, sizeof(keybuf),
   454 			                        NULL, &state) ) {
   455 				keysym.unicode = Utf8ToUcs4((Uint8*)keybuf);
   456 			}
   457 		}
   458 		else
   459 #endif
   460 		{
   461 			static XComposeStatus state;
   462 			char keybuf[32];
   463 
   464 			if ( pXLookupString(&xevent.xkey,
   465 			                    keybuf, sizeof(keybuf),
   466 			                    NULL, &state) ) {
   467 				/*
   468 				* FIXME: XLookupString() may yield more than one
   469 				* character, so we need a mechanism to allow for
   470 				* this (perhaps null keypress events with a
   471 				* unicode value)
   472 				*/
   473 				keysym.unicode = (Uint8)keybuf[0];
   474 			}
   475 		}
   476 		posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym);
   477 	    }
   478 	    break;
   479 
   480 	    /* Key release? */
   481 	    case KeyRelease: {
   482 		SDL_keysym keysym;
   483 		KeyCode keycode = xevent.xkey.keycode;
   484 
   485 #ifdef DEBUG_XEVENTS
   486 printf("KeyRelease (X11 keycode = 0x%X)\n", xevent.xkey.keycode);
   487 #endif
   488 		/* Check to see if this is a repeated key */
   489 		if ( X11_KeyRepeat(SDL_Display, &xevent) ) {
   490 			break;
   491 		}
   492 
   493 		/* Get the translated SDL virtual keysym */
   494 		keysym.scancode = keycode;
   495 		keysym.sym = X11_TranslateKeycode(SDL_Display, keycode);
   496 		keysym.mod = KMOD_NONE;
   497 		keysym.unicode = 0;
   498 
   499 		posted = SDL_PrivateKeyboard(SDL_RELEASED, &keysym);
   500 	    }
   501 	    break;
   502 
   503 	    /* Have we been iconified? */
   504 	    case UnmapNotify: {
   505 #ifdef DEBUG_XEVENTS
   506 printf("UnmapNotify!\n");
   507 #endif
   508 		/* If we're active, make ourselves inactive */
   509 		if ( SDL_GetAppState() & SDL_APPACTIVE ) {
   510 			/* Swap out the gamma before we go inactive */
   511 			X11_SwapVidModeGamma(this);
   512 
   513 			/* Send an internal deactivate event */
   514 			posted = SDL_PrivateAppActive(0,
   515 					SDL_APPACTIVE|SDL_APPINPUTFOCUS);
   516 		}
   517 	    }
   518 	    break;
   519 
   520 	    /* Have we been restored? */
   521 	    case MapNotify: {
   522 #ifdef DEBUG_XEVENTS
   523 printf("MapNotify!\n");
   524 #endif
   525 		/* If we're not active, make ourselves active */
   526 		if ( !(SDL_GetAppState() & SDL_APPACTIVE) ) {
   527 			/* Send an internal activate event */
   528 			posted = SDL_PrivateAppActive(1, SDL_APPACTIVE);
   529 
   530 			/* Now that we're active, swap the gamma back */
   531 			X11_SwapVidModeGamma(this);
   532 		}
   533 
   534 		if ( SDL_VideoSurface &&
   535 		     (SDL_VideoSurface->flags & SDL_FULLSCREEN) ) {
   536 			X11_EnterFullScreen(this);
   537 		} else {
   538 			X11_GrabInputNoLock(this, this->input_grab);
   539 		}
   540 		X11_CheckMouseModeNoLock(this);
   541 
   542 		if ( SDL_VideoSurface ) {
   543 			X11_RefreshDisplay(this);
   544 		}
   545 	    }
   546 	    break;
   547 
   548 	    /* Have we been resized or moved? */
   549 	    case ConfigureNotify: {
   550 #ifdef DEBUG_XEVENTS
   551 printf("ConfigureNotify! (resize: %dx%d)\n", xevent.xconfigure.width, xevent.xconfigure.height);
   552 #endif
   553 		if ( SDL_VideoSurface ) {
   554 		    if ((xevent.xconfigure.width != SDL_VideoSurface->w) ||
   555 		        (xevent.xconfigure.height != SDL_VideoSurface->h)) {
   556 			/* FIXME: Find a better fix for the bug with KDE 1.2 */
   557 			if ( ! ((xevent.xconfigure.width == 32) &&
   558 			        (xevent.xconfigure.height == 32)) ) {
   559 				SDL_PrivateResize(xevent.xconfigure.width,
   560 				                  xevent.xconfigure.height);
   561 			}
   562 		    } else {
   563 			/* OpenGL windows need to know about the change */
   564 			if ( SDL_VideoSurface->flags & SDL_OPENGL ) {
   565 				SDL_PrivateExpose();
   566 			}
   567 		    }
   568 		}
   569 	    }
   570 	    break;
   571 
   572 	    /* Have we been requested to quit (or another client message?) */
   573 	    case ClientMessage: {
   574 		if ( (xevent.xclient.format == 32) &&
   575 		     (xevent.xclient.data.l[0] == WM_DELETE_WINDOW) )
   576 		{
   577 			posted = SDL_PrivateQuit();
   578 		} else
   579 		if ( SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE ) {
   580 			SDL_SysWMmsg wmmsg;
   581 
   582 			SDL_VERSION(&wmmsg.version);
   583 			wmmsg.subsystem = SDL_SYSWM_X11;
   584 			wmmsg.event.xevent = xevent;
   585 			posted = SDL_PrivateSysWMEvent(&wmmsg);
   586 		}
   587 	    }
   588 	    break;
   589 
   590 	    /* Do we need to refresh ourselves? */
   591 	    case Expose: {
   592 #ifdef DEBUG_XEVENTS
   593 printf("Expose (count = %d)\n", xevent.xexpose.count);
   594 #endif
   595 		if ( SDL_VideoSurface && (xevent.xexpose.count == 0) ) {
   596 			X11_RefreshDisplay(this);
   597 		}
   598 	    }
   599 	    break;
   600 
   601 	    default: {
   602 #ifdef DEBUG_XEVENTS
   603 printf("Unhandled event %d\n", xevent.type);
   604 #endif
   605 		/* Only post the event if we're watching for it */
   606 		if ( SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE ) {
   607 			SDL_SysWMmsg wmmsg;
   608 
   609 			SDL_VERSION(&wmmsg.version);
   610 			wmmsg.subsystem = SDL_SYSWM_X11;
   611 			wmmsg.event.xevent = xevent;
   612 			posted = SDL_PrivateSysWMEvent(&wmmsg);
   613 		}
   614 	    }
   615 	    break;
   616 	}
   617 	return(posted);
   618 }
   619 
   620 /* Ack!  XPending() actually performs a blocking read if no events available */
   621 int X11_Pending(Display *display)
   622 {
   623 	/* Flush the display connection and look to see if events are queued */
   624 	pXFlush(display);
   625 	if ( pXEventsQueued(display, QueuedAlready) ) {
   626 		return(1);
   627 	}
   628 
   629 	/* More drastic measures are required -- see if X is ready to talk */
   630 	{
   631 		static struct timeval zero_time;	/* static == 0 */
   632 		int x11_fd;
   633 		fd_set fdset;
   634 
   635 		x11_fd = ConnectionNumber(display);
   636 		FD_ZERO(&fdset);
   637 		FD_SET(x11_fd, &fdset);
   638 		if ( select(x11_fd+1, &fdset, NULL, NULL, &zero_time) == 1 ) {
   639 			return(pXPending(display));
   640 		}
   641 	}
   642 
   643 	/* Oh well, nothing is ready .. */
   644 	return(0);
   645 }
   646 
   647 void X11_PumpEvents(_THIS)
   648 {
   649 	int pending;
   650 
   651 	/* Keep processing pending events */
   652 	pending = 0;
   653 	while ( X11_Pending(SDL_Display) ) {
   654 		X11_DispatchEvent(this);
   655 		++pending;
   656 	}
   657 	if ( switch_waiting ) {
   658 		Uint32 now;
   659 
   660 		now  = SDL_GetTicks();
   661 		if ( pending || !SDL_VideoSurface ) {
   662 			/* Try again later... */
   663 			if ( switch_waiting & SDL_FULLSCREEN ) {
   664 				switch_time = now + 1500;
   665 			} else {
   666 				switch_time = now + 200;
   667 			}
   668 		} else if ( now >= switch_time ) {
   669 			Uint32 go_fullscreen;
   670 
   671 			go_fullscreen = switch_waiting & SDL_FULLSCREEN;
   672 			switch_waiting = 0;
   673 			if ( SDL_VideoSurface->flags & SDL_FULLSCREEN ) {
   674 				if ( go_fullscreen ) {
   675 					X11_EnterFullScreen(this);
   676 				} else {
   677 					X11_LeaveFullScreen(this);
   678 				}
   679 			}
   680 			/* Handle focus in/out when grabbed */
   681 			if ( go_fullscreen ) {
   682 				X11_GrabInputNoLock(this, this->input_grab);
   683 			} else {
   684 				X11_GrabInputNoLock(this, SDL_GRAB_OFF);
   685 			}
   686 			X11_CheckMouseModeNoLock(this);
   687 		}
   688 	}
   689 }
   690 
   691 void X11_InitKeymap(void)
   692 {
   693 	int i;
   694 
   695 	/* Odd keys used in international keyboards */
   696 	for ( i=0; i<SDL_TABLESIZE(ODD_keymap); ++i )
   697 		ODD_keymap[i] = SDLK_UNKNOWN;
   698 
   699  	/* Some of these might be mappable to an existing SDLK_ code */
   700  	ODD_keymap[XK_dead_grave&0xFF] = SDLK_COMPOSE;
   701  	ODD_keymap[XK_dead_acute&0xFF] = SDLK_COMPOSE;
   702  	ODD_keymap[XK_dead_tilde&0xFF] = SDLK_COMPOSE;
   703  	ODD_keymap[XK_dead_macron&0xFF] = SDLK_COMPOSE;
   704  	ODD_keymap[XK_dead_breve&0xFF] = SDLK_COMPOSE;
   705  	ODD_keymap[XK_dead_abovedot&0xFF] = SDLK_COMPOSE;
   706  	ODD_keymap[XK_dead_diaeresis&0xFF] = SDLK_COMPOSE;
   707  	ODD_keymap[XK_dead_abovering&0xFF] = SDLK_COMPOSE;
   708  	ODD_keymap[XK_dead_doubleacute&0xFF] = SDLK_COMPOSE;
   709  	ODD_keymap[XK_dead_caron&0xFF] = SDLK_COMPOSE;
   710  	ODD_keymap[XK_dead_cedilla&0xFF] = SDLK_COMPOSE;
   711  	ODD_keymap[XK_dead_ogonek&0xFF] = SDLK_COMPOSE;
   712  	ODD_keymap[XK_dead_iota&0xFF] = SDLK_COMPOSE;
   713  	ODD_keymap[XK_dead_voiced_sound&0xFF] = SDLK_COMPOSE;
   714  	ODD_keymap[XK_dead_semivoiced_sound&0xFF] = SDLK_COMPOSE;
   715  	ODD_keymap[XK_dead_belowdot&0xFF] = SDLK_COMPOSE;
   716 #ifdef XK_dead_hook
   717  	ODD_keymap[XK_dead_hook&0xFF] = SDLK_COMPOSE;
   718 #endif
   719 #ifdef XK_dead_horn
   720  	ODD_keymap[XK_dead_horn&0xFF] = SDLK_COMPOSE;
   721 #endif
   722 
   723 #ifdef XK_dead_circumflex
   724 	/* These X keysyms have 0xFE as the high byte */
   725 	ODD_keymap[XK_dead_circumflex&0xFF] = SDLK_CARET;
   726 #endif
   727 #ifdef XK_ISO_Level3_Shift
   728 	ODD_keymap[XK_ISO_Level3_Shift&0xFF] = SDLK_MODE; /* "Alt Gr" key */
   729 #endif
   730 
   731 	/* Map the miscellaneous keys */
   732 	for ( i=0; i<SDL_TABLESIZE(MISC_keymap); ++i )
   733 		MISC_keymap[i] = SDLK_UNKNOWN;
   734 
   735 	/* These X keysyms have 0xFF as the high byte */
   736 	MISC_keymap[XK_BackSpace&0xFF] = SDLK_BACKSPACE;
   737 	MISC_keymap[XK_Tab&0xFF] = SDLK_TAB;
   738 	MISC_keymap[XK_Clear&0xFF] = SDLK_CLEAR;
   739 	MISC_keymap[XK_Return&0xFF] = SDLK_RETURN;
   740 	MISC_keymap[XK_Pause&0xFF] = SDLK_PAUSE;
   741 	MISC_keymap[XK_Escape&0xFF] = SDLK_ESCAPE;
   742 	MISC_keymap[XK_Delete&0xFF] = SDLK_DELETE;
   743 
   744 	MISC_keymap[XK_KP_0&0xFF] = SDLK_KP0;		/* Keypad 0-9 */
   745 	MISC_keymap[XK_KP_1&0xFF] = SDLK_KP1;
   746 	MISC_keymap[XK_KP_2&0xFF] = SDLK_KP2;
   747 	MISC_keymap[XK_KP_3&0xFF] = SDLK_KP3;
   748 	MISC_keymap[XK_KP_4&0xFF] = SDLK_KP4;
   749 	MISC_keymap[XK_KP_5&0xFF] = SDLK_KP5;
   750 	MISC_keymap[XK_KP_6&0xFF] = SDLK_KP6;
   751 	MISC_keymap[XK_KP_7&0xFF] = SDLK_KP7;
   752 	MISC_keymap[XK_KP_8&0xFF] = SDLK_KP8;
   753 	MISC_keymap[XK_KP_9&0xFF] = SDLK_KP9;
   754 	MISC_keymap[XK_KP_Insert&0xFF] = SDLK_KP0;
   755 	MISC_keymap[XK_KP_End&0xFF] = SDLK_KP1;	
   756 	MISC_keymap[XK_KP_Down&0xFF] = SDLK_KP2;
   757 	MISC_keymap[XK_KP_Page_Down&0xFF] = SDLK_KP3;
   758 	MISC_keymap[XK_KP_Left&0xFF] = SDLK_KP4;
   759 	MISC_keymap[XK_KP_Begin&0xFF] = SDLK_KP5;
   760 	MISC_keymap[XK_KP_Right&0xFF] = SDLK_KP6;
   761 	MISC_keymap[XK_KP_Home&0xFF] = SDLK_KP7;
   762 	MISC_keymap[XK_KP_Up&0xFF] = SDLK_KP8;
   763 	MISC_keymap[XK_KP_Page_Up&0xFF] = SDLK_KP9;
   764 	MISC_keymap[XK_KP_Delete&0xFF] = SDLK_KP_PERIOD;
   765 	MISC_keymap[XK_KP_Decimal&0xFF] = SDLK_KP_PERIOD;
   766 	MISC_keymap[XK_KP_Divide&0xFF] = SDLK_KP_DIVIDE;
   767 	MISC_keymap[XK_KP_Multiply&0xFF] = SDLK_KP_MULTIPLY;
   768 	MISC_keymap[XK_KP_Subtract&0xFF] = SDLK_KP_MINUS;
   769 	MISC_keymap[XK_KP_Add&0xFF] = SDLK_KP_PLUS;
   770 	MISC_keymap[XK_KP_Enter&0xFF] = SDLK_KP_ENTER;
   771 	MISC_keymap[XK_KP_Equal&0xFF] = SDLK_KP_EQUALS;
   772 
   773 	MISC_keymap[XK_Up&0xFF] = SDLK_UP;
   774 	MISC_keymap[XK_Down&0xFF] = SDLK_DOWN;
   775 	MISC_keymap[XK_Right&0xFF] = SDLK_RIGHT;
   776 	MISC_keymap[XK_Left&0xFF] = SDLK_LEFT;
   777 	MISC_keymap[XK_Insert&0xFF] = SDLK_INSERT;
   778 	MISC_keymap[XK_Home&0xFF] = SDLK_HOME;
   779 	MISC_keymap[XK_End&0xFF] = SDLK_END;
   780 	MISC_keymap[XK_Page_Up&0xFF] = SDLK_PAGEUP;
   781 	MISC_keymap[XK_Page_Down&0xFF] = SDLK_PAGEDOWN;
   782 
   783 	MISC_keymap[XK_F1&0xFF] = SDLK_F1;
   784 	MISC_keymap[XK_F2&0xFF] = SDLK_F2;
   785 	MISC_keymap[XK_F3&0xFF] = SDLK_F3;
   786 	MISC_keymap[XK_F4&0xFF] = SDLK_F4;
   787 	MISC_keymap[XK_F5&0xFF] = SDLK_F5;
   788 	MISC_keymap[XK_F6&0xFF] = SDLK_F6;
   789 	MISC_keymap[XK_F7&0xFF] = SDLK_F7;
   790 	MISC_keymap[XK_F8&0xFF] = SDLK_F8;
   791 	MISC_keymap[XK_F9&0xFF] = SDLK_F9;
   792 	MISC_keymap[XK_F10&0xFF] = SDLK_F10;
   793 	MISC_keymap[XK_F11&0xFF] = SDLK_F11;
   794 	MISC_keymap[XK_F12&0xFF] = SDLK_F12;
   795 	MISC_keymap[XK_F13&0xFF] = SDLK_F13;
   796 	MISC_keymap[XK_F14&0xFF] = SDLK_F14;
   797 	MISC_keymap[XK_F15&0xFF] = SDLK_F15;
   798 
   799 	MISC_keymap[XK_Num_Lock&0xFF] = SDLK_NUMLOCK;
   800 	MISC_keymap[XK_Caps_Lock&0xFF] = SDLK_CAPSLOCK;
   801 	MISC_keymap[XK_Scroll_Lock&0xFF] = SDLK_SCROLLOCK;
   802 	MISC_keymap[XK_Shift_R&0xFF] = SDLK_RSHIFT;
   803 	MISC_keymap[XK_Shift_L&0xFF] = SDLK_LSHIFT;
   804 	MISC_keymap[XK_Control_R&0xFF] = SDLK_RCTRL;
   805 	MISC_keymap[XK_Control_L&0xFF] = SDLK_LCTRL;
   806 	MISC_keymap[XK_Alt_R&0xFF] = SDLK_RALT;
   807 	MISC_keymap[XK_Alt_L&0xFF] = SDLK_LALT;
   808 	MISC_keymap[XK_Meta_R&0xFF] = SDLK_RMETA;
   809 	MISC_keymap[XK_Meta_L&0xFF] = SDLK_LMETA;
   810 	MISC_keymap[XK_Super_L&0xFF] = SDLK_LSUPER; /* Left "Windows" */
   811 	MISC_keymap[XK_Super_R&0xFF] = SDLK_RSUPER; /* Right "Windows */
   812 	MISC_keymap[XK_Mode_switch&0xFF] = SDLK_MODE; /* "Alt Gr" key */
   813 	MISC_keymap[XK_Multi_key&0xFF] = SDLK_COMPOSE; /* Multi-key compose */
   814 
   815 	MISC_keymap[XK_Help&0xFF] = SDLK_HELP;
   816 	MISC_keymap[XK_Print&0xFF] = SDLK_PRINT;
   817 	MISC_keymap[XK_Sys_Req&0xFF] = SDLK_SYSREQ;
   818 	MISC_keymap[XK_Break&0xFF] = SDLK_BREAK;
   819 	MISC_keymap[XK_Menu&0xFF] = SDLK_MENU;
   820 	MISC_keymap[XK_Hyper_R&0xFF] = SDLK_MENU;   /* Windows "Menu" key */
   821 }
   822 
   823 /* Get the translated SDL virtual keysym */
   824 SDLKey X11_TranslateKeycode(Display *display, KeyCode kc)
   825 {
   826 	KeySym xsym;
   827 	SDLKey key;
   828 
   829 	xsym = pXKeycodeToKeysym(display, kc, 0);
   830 #ifdef DEBUG_KEYS
   831 	fprintf(stderr, "Translating key code %d -> 0x%.4x\n", kc, xsym);
   832 #endif
   833 	key = SDLK_UNKNOWN;
   834 	if ( xsym ) {
   835 		switch (xsym>>8) {
   836 		    case 0x1005FF:
   837 #ifdef SunXK_F36
   838 			if ( xsym == SunXK_F36 )
   839 				key = SDLK_F11;
   840 #endif
   841 #ifdef SunXK_F37
   842 			if ( xsym == SunXK_F37 )
   843 				key = SDLK_F12;
   844 #endif
   845 			break;
   846 		    case 0x00:	/* Latin 1 */
   847 			key = (SDLKey)(xsym & 0xFF);
   848 			break;
   849 		    case 0x01:	/* Latin 2 */
   850 		    case 0x02:	/* Latin 3 */
   851 		    case 0x03:	/* Latin 4 */
   852 		    case 0x04:	/* Katakana */
   853 		    case 0x05:	/* Arabic */
   854 		    case 0x06:	/* Cyrillic */
   855 		    case 0x07:	/* Greek */
   856 		    case 0x08:	/* Technical */
   857 		    case 0x0A:	/* Publishing */
   858 		    case 0x0C:	/* Hebrew */
   859 		    case 0x0D:	/* Thai */
   860 			/* These are wrong, but it's better than nothing */
   861 			key = (SDLKey)(xsym & 0xFF);
   862 			break;
   863 		    case 0xFE:
   864 			key = ODD_keymap[xsym&0xFF];
   865 			break;
   866 		    case 0xFF:
   867 			key = MISC_keymap[xsym&0xFF];
   868 			break;
   869 		    default:
   870 			/*
   871 			fprintf(stderr, "X11: Unhandled xsym, sym = 0x%04x\n",
   872 					(unsigned int)xsym);
   873 			*/
   874 			break;
   875 		}
   876 	} else {
   877 		/* X11 doesn't know how to translate the key! */
   878 		switch (kc) {
   879 		    /* Caution:
   880 		       These keycodes are from the Microsoft Keyboard
   881 		     */
   882 		    case 115:
   883 			key = SDLK_LSUPER;
   884 			break;
   885 		    case 116:
   886 			key = SDLK_RSUPER;
   887 			break;
   888 		    case 117:
   889 			key = SDLK_MENU;
   890 			break;
   891 		    default:
   892 			/*
   893 			 * no point in an error message; happens for
   894 			 * several keys when we get a keymap notify
   895 			 */
   896 			break;
   897 		}
   898 	}
   899 	return key;
   900 }
   901 
   902 /* X11 modifier masks for various keys */
   903 static unsigned meta_l_mask, meta_r_mask, alt_l_mask, alt_r_mask;
   904 static unsigned num_mask, mode_switch_mask;
   905 
   906 static void get_modifier_masks(Display *display)
   907 {
   908 	static unsigned got_masks;
   909 	int i, j;
   910 	XModifierKeymap *xmods;
   911 	unsigned n;
   912 
   913 	if(got_masks)
   914 		return;
   915 
   916 	xmods = pXGetModifierMapping(display);
   917 	n = xmods->max_keypermod;
   918 	for(i = 3; i < 8; i++) {
   919 		for(j = 0; j < n; j++) {
   920 			KeyCode kc = xmods->modifiermap[i * n + j];
   921 			KeySym ks = pXKeycodeToKeysym(display, kc, 0);
   922 			unsigned mask = 1 << i;
   923 			switch(ks) {
   924 			case XK_Num_Lock:
   925 				num_mask = mask; break;
   926 			case XK_Alt_L:
   927 				alt_l_mask = mask; break;
   928 			case XK_Alt_R:
   929 				alt_r_mask = mask; break;
   930 			case XK_Meta_L:
   931 				meta_l_mask = mask; break;
   932 			case XK_Meta_R:
   933 				meta_r_mask = mask; break;
   934 			case XK_Mode_switch:
   935 				mode_switch_mask = mask; break;
   936 			}
   937 		}
   938 	}
   939 	pXFreeModifiermap(xmods);
   940 	got_masks = 1;
   941 }
   942 
   943 
   944 /*
   945  * This function is semi-official; it is not officially exported and should
   946  * not be considered part of the SDL API, but may be used by client code
   947  * that *really* needs it (including legacy code).
   948  * It is slow, though, and should be avoided if possible.
   949  *
   950  * Note that it isn't completely accurate either; in particular, multi-key
   951  * sequences (dead accents, compose key sequences) will not work since the
   952  * state has been irrevocably lost.
   953  */
   954 Uint16 X11_KeyToUnicode(SDLKey keysym, SDLMod modifiers)
   955 {
   956 	struct SDL_VideoDevice *this = current_video;
   957 	char keybuf[32];
   958 	int i;
   959 	KeySym xsym = 0;
   960 	XKeyEvent xkey;
   961 	Uint16 unicode;
   962 
   963 	if ( !this || !SDL_Display ) {
   964 		return 0;
   965 	}
   966 
   967 	SDL_memset(&xkey, 0, sizeof(xkey));
   968 	xkey.display = SDL_Display;
   969 
   970 	xsym = keysym;		/* last resort if not found */
   971 	for (i = 0; i < 256; ++i) {
   972 		if ( MISC_keymap[i] == keysym ) {
   973 			xsym = 0xFF00 | i;
   974 			break;
   975 		} else if ( ODD_keymap[i] == keysym ) {
   976 			xsym = 0xFE00 | i;
   977 			break;
   978 		}
   979 	}
   980 
   981 	xkey.keycode = pXKeysymToKeycode(xkey.display, xsym);
   982 
   983 	get_modifier_masks(SDL_Display);
   984 	if(modifiers & KMOD_SHIFT)
   985 		xkey.state |= ShiftMask;
   986 	if(modifiers & KMOD_CAPS)
   987 		xkey.state |= LockMask;
   988 	if(modifiers & KMOD_CTRL)
   989 		xkey.state |= ControlMask;
   990 	if(modifiers & KMOD_MODE)
   991 		xkey.state |= mode_switch_mask;
   992 	if(modifiers & KMOD_LALT)
   993 		xkey.state |= alt_l_mask;
   994 	if(modifiers & KMOD_RALT)
   995 		xkey.state |= alt_r_mask;
   996 	if(modifiers & KMOD_LMETA)
   997 		xkey.state |= meta_l_mask;
   998 	if(modifiers & KMOD_RMETA)
   999 		xkey.state |= meta_r_mask;
  1000 	if(modifiers & KMOD_NUM)
  1001 		xkey.state |= num_mask;
  1002 
  1003 	unicode = 0;
  1004 	if ( pXLookupString(&xkey, keybuf, sizeof(keybuf), NULL, NULL) )
  1005 		unicode = (unsigned char)keybuf[0];
  1006 	return(unicode);
  1007 }
  1008 
  1009 
  1010 /*
  1011  * Called when focus is regained, to read the keyboard state and generate
  1012  * synthetic keypress/release events.
  1013  * key_vec is a bit vector of keycodes (256 bits)
  1014  */
  1015 void X11_SetKeyboardState(Display *display, const char *key_vec)
  1016 {
  1017 	char keys_return[32];
  1018 	int i;
  1019 	Uint8 *kstate = SDL_GetKeyState(NULL);
  1020 	SDLMod modstate;
  1021 	Window junk_window;
  1022 	int x, y;
  1023 	unsigned int mask;
  1024 
  1025 	/* The first time the window is mapped, we initialize key state */
  1026 	if ( ! key_vec ) {
  1027 		pXQueryKeymap(display, keys_return);
  1028 		key_vec = keys_return;
  1029 	}
  1030 
  1031 	/* Get the keyboard modifier state */
  1032 	modstate = 0;
  1033 	get_modifier_masks(display);
  1034 	if ( pXQueryPointer(display, DefaultRootWindow(display),
  1035 		&junk_window, &junk_window, &x, &y, &x, &y, &mask) ) {
  1036 		if ( mask & LockMask ) {
  1037 			modstate |= KMOD_CAPS;
  1038 		}
  1039 		if ( mask & mode_switch_mask ) {
  1040 			modstate |= KMOD_MODE;
  1041 		}
  1042 		if ( mask & num_mask ) {
  1043 			modstate |= KMOD_NUM;
  1044 		}
  1045 	}
  1046 
  1047 	/* Zero the new keyboard state and generate it */
  1048 	SDL_memset(kstate, 0, SDLK_LAST);
  1049 	/*
  1050 	 * An obvious optimisation is to check entire longwords at a time in
  1051 	 * both loops, but we can't be sure the arrays are aligned so it's not
  1052 	 * worth the extra complexity
  1053 	 */
  1054 	for ( i = 0; i < 32; i++ ) {
  1055 		int j;
  1056 		if ( !key_vec[i] )
  1057 			continue;
  1058 		for ( j = 0; j < 8; j++ ) {
  1059 			if ( key_vec[i] & (1 << j) ) {
  1060 				SDLKey key;
  1061 				KeyCode kc = (i << 3 | j);
  1062 				key = X11_TranslateKeycode(display, kc);
  1063 				if ( key == SDLK_UNKNOWN ) {
  1064 					continue;
  1065 				}
  1066 				kstate[key] = SDL_PRESSED;
  1067 				switch (key) {
  1068 				    case SDLK_LSHIFT:
  1069 					modstate |= KMOD_LSHIFT;
  1070 					break;
  1071 				    case SDLK_RSHIFT:
  1072 					modstate |= KMOD_RSHIFT;
  1073 					break;
  1074 				    case SDLK_LCTRL:
  1075 					modstate |= KMOD_LCTRL;
  1076 					break;
  1077 				    case SDLK_RCTRL:
  1078 					modstate |= KMOD_RCTRL;
  1079 					break;
  1080 				    case SDLK_LALT:
  1081 					modstate |= KMOD_LALT;
  1082 					break;
  1083 				    case SDLK_RALT:
  1084 					modstate |= KMOD_RALT;
  1085 					break;
  1086 				    case SDLK_LMETA:
  1087 					modstate |= KMOD_LMETA;
  1088 					break;
  1089 				    case SDLK_RMETA:
  1090 					modstate |= KMOD_RMETA;
  1091 					break;
  1092 				    default:
  1093 					break;
  1094 				}
  1095 			}
  1096 		}
  1097 	}
  1098 
  1099 	/* Hack - set toggle key state */
  1100 	if ( modstate & KMOD_CAPS ) {
  1101 		kstate[SDLK_CAPSLOCK] = SDL_PRESSED;
  1102 	} else {
  1103 		kstate[SDLK_CAPSLOCK] = SDL_RELEASED;
  1104 	}
  1105 	if ( modstate & KMOD_NUM ) {
  1106 		kstate[SDLK_NUMLOCK] = SDL_PRESSED;
  1107 	} else {
  1108 		kstate[SDLK_NUMLOCK] = SDL_RELEASED;
  1109 	}
  1110 
  1111 	/* Set the final modifier state */
  1112 	SDL_SetModState(modstate);
  1113 }
  1114 
  1115 void X11_InitOSKeymap(_THIS)
  1116 {
  1117 	X11_InitKeymap();
  1118 }
  1119