diff src/video/x11/SDL_x11events.c @ 1327:d12a63a8d95a

Resolved bug #130 Use XFilterEvent() to handle dead-key composition under X11 Cleaned up the code in preparation for 1.3 API changes
author Sam Lantinga <slouken@libsdl.org>
date Sat, 04 Feb 2006 08:35:11 +0000
parents c9b51268668f
children 27ddb06a0bca
line wrap: on
line diff
--- a/src/video/x11/SDL_x11events.c	Fri Feb 03 07:43:42 2006 +0000
+++ b/src/video/x11/SDL_x11events.c	Sat Feb 04 08:35:11 2006 +0000
@@ -57,8 +57,128 @@
 /* The translation tables from an X11 keysym to a SDL keysym */
 static SDLKey ODD_keymap[256];
 static SDLKey MISC_keymap[256];
-SDL_keysym *X11_TranslateKey(Display *display, XIC ic, XKeyEvent *xkey, KeyCode kc,
-			     SDL_keysym *keysym);
+SDLKey X11_TranslateKeycode(Display *display, KeyCode kc);
+
+
+#ifdef X_HAVE_UTF8_STRING
+Uint32 Utf8ToUcs4(const Uint8 *utf8)
+{
+	Uint32 c;
+	int i = 1;
+	int noOctets = 0;
+	int firstOctetMask = 0;
+	unsigned char firstOctet = utf8[0];
+	if (firstOctet < 0x80) {
+		/*
+		  Characters in the range:
+		    00000000 to 01111111 (ASCII Range)
+		  are stored in one octet:
+		    0xxxxxxx (The same as its ASCII representation)
+		  The least 6 significant bits of the first octet is the most 6 significant nonzero bits
+		  of the UCS4 representation.
+		*/
+		noOctets = 1;
+		firstOctetMask = 0x7F;  /* 0(1111111) - The most significant bit is ignored */
+	} else if ((firstOctet & 0xE0) /* get the most 3 significant bits by AND'ing with 11100000 */
+	              == 0xC0 ) {  /* see if those 3 bits are 110. If so, the char is in this range */
+		/*
+		  Characters in the range:
+		    00000000 10000000 to 00000111 11111111
+		  are stored in two octets:
+		    110xxxxx 10xxxxxx
+		  The least 5 significant bits of the first octet is the most 5 significant nonzero bits
+		  of the UCS4 representation.
+		*/
+		noOctets = 2;
+		firstOctetMask = 0x1F;  /* 000(11111) - The most 3 significant bits are ignored */
+	} else if ((firstOctet & 0xF0) /* get the most 4 significant bits by AND'ing with 11110000 */
+	              == 0xE0) {  /* see if those 4 bits are 1110. If so, the char is in this range */
+		/*
+		  Characters in the range:
+		    00001000 00000000 to 11111111 11111111
+		  are stored in three octets:
+		    1110xxxx 10xxxxxx 10xxxxxx
+		  The least 4 significant bits of the first octet is the most 4 significant nonzero bits
+		  of the UCS4 representation.
+		*/
+		noOctets = 3;
+		firstOctetMask = 0x0F; /* 0000(1111) - The most 4 significant bits are ignored */
+	} else if ((firstOctet & 0xF8) /* get the most 5 significant bits by AND'ing with 11111000 */
+	              == 0xF0) {  /* see if those 5 bits are 11110. If so, the char is in this range */
+		/*
+		  Characters in the range:
+		    00000001 00000000 00000000 to 00011111 11111111 11111111
+		  are stored in four octets:
+		    11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+		  The least 3 significant bits of the first octet is the most 3 significant nonzero bits
+		  of the UCS4 representation.
+		*/
+		noOctets = 4;
+		firstOctetMask = 0x07; /* 11110(111) - The most 5 significant bits are ignored */
+	} else if ((firstOctet & 0xFC) /* get the most 6 significant bits by AND'ing with 11111100 */
+	              == 0xF8) { /* see if those 6 bits are 111110. If so, the char is in this range */
+		/*
+		  Characters in the range:
+		    00000000 00100000 00000000 00000000 to
+		    00000011 11111111 11111111 11111111
+		  are stored in five octets:
+		    111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
+		  The least 2 significant bits of the first octet is the most 2 significant nonzero bits
+		  of the UCS4 representation.
+		*/
+		noOctets = 5;
+		firstOctetMask = 0x03; /* 111110(11) - The most 6 significant bits are ignored */
+	} else if ((firstOctet & 0xFE) /* get the most 7 significant bits by AND'ing with 11111110 */
+	              == 0xFC) { /* see if those 7 bits are 1111110. If so, the char is in this range */
+		/*
+		  Characters in the range:
+		    00000100 00000000 00000000 00000000 to
+		    01111111 11111111 11111111 11111111
+		  are stored in six octets:
+		    1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
+		  The least significant bit of the first octet is the most significant nonzero bit
+		  of the UCS4 representation.
+		*/
+		noOctets = 6;
+		firstOctetMask = 0x01; /* 1111110(1) - The most 7 significant bits are ignored */
+	} else
+		return 0;  /* The given chunk is not a valid UTF-8 encoded Unicode character */
+	
+	/*
+	  The least noOctets significant bits of the first octet is the most 2 significant nonzero bits
+	  of the UCS4 representation.
+	  The first 6 bits of the UCS4 representation is the least 8-noOctets-1 significant bits of
+	  firstOctet if the character is not ASCII. If so, it's the least 7 significant bits of firstOctet.
+	  This done by AND'ing firstOctet with its mask to trim the bits used for identifying the
+	  number of continuing octets (if any) and leave only the free bits (the x's)
+	  Sample:
+	  1-octet:    0xxxxxxx  &  01111111 = 0xxxxxxx
+	  2-octets:  110xxxxx  &  00011111 = 000xxxxx
+	*/
+	c = firstOctet & firstOctetMask;
+	
+	/* Now, start filling c.ucs4 with the bits from the continuing octets from utf8. */
+	for (i = 1; i < noOctets; i++) {
+		/* A valid continuing octet is of the form 10xxxxxx */
+		if ((utf8[i] & 0xC0) /* get the most 2 significant bits by AND'ing with 11000000 */
+		    != 0x80) /* see if those 2 bits are 10. If not, the is a malformed sequence. */
+			/*The given chunk is a partial sequence at the end of a string that could
+			   begin a valid character */
+			return 0;
+		
+		/* Make room for the next 6-bits */
+		c <<= 6;
+		
+		/*
+		  Take only the least 6 significance bits of the current octet (utf8[i]) and fill the created room
+		  of c.ucs4 with them.
+		  This done by AND'ing utf8[i] with 00111111 and the OR'ing the result with c.ucs4.
+		*/
+		c |= utf8[i] & 0x3F;
+	}
+	return c;
+}
+#endif
 
 /* Check to see if this is a repeated key.
    (idea shamelessly lifted from GII -- thanks guys! :)
@@ -212,6 +332,10 @@
 #endif
 		posted = SDL_PrivateAppActive(1, SDL_APPINPUTFOCUS);
 
+		if ( SDL_IC != NULL ) {
+			pXSetICFocus(SDL_IC);
+		}
+
 		/* Queue entry into fullscreen mode */
 		switch_waiting = 0x01 | SDL_FULLSCREEN;
 		switch_time = SDL_GetTicks() + 1500;
@@ -225,6 +349,10 @@
 #endif
 		posted = SDL_PrivateAppActive(0, SDL_APPINPUTFOCUS);
 
+		if ( SDL_IC != NULL ) {
+			pXUnsetICFocus(SDL_IC);
+		}
+
 		/* Queue leaving fullscreen mode */
 		switch_waiting = 0x01;
 		switch_time = SDL_GetTicks() + 200;
@@ -236,7 +364,7 @@
 #ifdef DEBUG_XEVENTS
 printf("KeymapNotify!\n");
 #endif
-		X11_SetKeyboardState(SDL_Display, SDL_IC,  xevent.xkeymap.key_vector);
+		X11_SetKeyboardState(SDL_Display,  xevent.xkeymap.key_vector);
 	    }
 	    break;
 
@@ -282,32 +410,94 @@
 
 	    /* Key press? */
 	    case KeyPress: {
+		static SDL_keysym saved_keysym;
 		SDL_keysym keysym;
+		KeyCode keycode = xevent.xkey.keycode;
 
 #ifdef DEBUG_XEVENTS
 printf("KeyPress (X11 keycode = 0x%X)\n", xevent.xkey.keycode);
 #endif
-		posted = SDL_PrivateKeyboard(SDL_PRESSED,
-				X11_TranslateKey(SDL_Display, SDL_IC, &xevent.xkey,
-						 xevent.xkey.keycode,
-						 &keysym));
+		/* Get the translated SDL virtual keysym */
+		if ( keycode ) {
+			keysym.scancode = keycode;
+			keysym.sym = X11_TranslateKeycode(SDL_Display, keycode);
+			keysym.mod = KMOD_NONE;
+			keysym.unicode = 0;
+		} else {
+			keysym = saved_keysym;
+		}
+
+		/* If we're not doing translation, we're done! */
+		if ( !SDL_TranslateUNICODE ) {
+			posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym);
+			break;
+		}
+
+		if ( pXFilterEvent(&xevent, None) ) {
+			if ( xevent.xkey.keycode ) {
+				posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym);
+			} else {
+				/* Save event to be associated with IM text
+				   In 1.3 we'll have a text event instead.. */
+				saved_keysym = keysym;
+			}
+			break;
+		}
+
+		/* Look up the translated value for the key event */
+#ifdef X_HAVE_UTF8_STRING
+		if ( SDL_IC != NULL ) {
+			static Status state;
+			/* A UTF-8 character can be at most 6 bytes */
+			char keybuf[6];
+			if ( pXutf8LookupString(SDL_IC, &xevent.xkey,
+			                        keybuf, sizeof(keybuf),
+			                        NULL, &state) ) {
+				keysym.unicode = Utf8ToUcs4((Uint8*)keybuf);
+			}
+		}
+		else
+#endif
+		{
+			static XComposeStatus state;
+			char keybuf[32];
+
+			if ( pXLookupString(&xevent.xkey,
+			                    keybuf, sizeof(keybuf),
+			                    NULL, &state) ) {
+				/*
+				* FIXME: XLookupString() may yield more than one
+				* character, so we need a mechanism to allow for
+				* this (perhaps null keypress events with a
+				* unicode value)
+				*/
+				keysym.unicode = (Uint8)keybuf[0];
+			}
+		}
+		posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym);
 	    }
 	    break;
 
 	    /* Key release? */
 	    case KeyRelease: {
 		SDL_keysym keysym;
+		KeyCode keycode = xevent.xkey.keycode;
 
 #ifdef DEBUG_XEVENTS
 printf("KeyRelease (X11 keycode = 0x%X)\n", xevent.xkey.keycode);
 #endif
 		/* Check to see if this is a repeated key */
-		if ( ! X11_KeyRepeat(SDL_Display, &xevent) ) {
-			posted = SDL_PrivateKeyboard(SDL_RELEASED, 
-				X11_TranslateKey(SDL_Display, SDL_IC,  &xevent.xkey,
-						 xevent.xkey.keycode,
-						 &keysym));
+		if ( X11_KeyRepeat(SDL_Display, &xevent) ) {
+			break;
 		}
+
+		/* Get the translated SDL virtual keysym */
+		keysym.scancode = keycode;
+		keysym.sym = X11_TranslateKeycode(SDL_Display, keycode);
+		keysym.mod = KMOD_NONE;
+		keysym.unicode = 0;
+
+		posted = SDL_PrivateKeyboard(SDL_RELEASED, &keysym);
 	    }
 	    break;
 
@@ -507,6 +697,26 @@
 	for ( i=0; i<SDL_TABLESIZE(ODD_keymap); ++i )
 		ODD_keymap[i] = SDLK_UNKNOWN;
 
+ 	/* Some of these might be mappable to an existing SDLK_ code */
+ 	ODD_keymap[XK_dead_grave&0xFF] = SDLK_COMPOSE;
+ 	ODD_keymap[XK_dead_acute&0xFF] = SDLK_COMPOSE;
+ 	ODD_keymap[XK_dead_tilde&0xFF] = SDLK_COMPOSE;
+ 	ODD_keymap[XK_dead_macron&0xFF] = SDLK_COMPOSE;
+ 	ODD_keymap[XK_dead_breve&0xFF] = SDLK_COMPOSE;
+ 	ODD_keymap[XK_dead_abovedot&0xFF] = SDLK_COMPOSE;
+ 	ODD_keymap[XK_dead_diaeresis&0xFF] = SDLK_COMPOSE;
+ 	ODD_keymap[XK_dead_abovering&0xFF] = SDLK_COMPOSE;
+ 	ODD_keymap[XK_dead_doubleacute&0xFF] = SDLK_COMPOSE;
+ 	ODD_keymap[XK_dead_caron&0xFF] = SDLK_COMPOSE;
+ 	ODD_keymap[XK_dead_cedilla&0xFF] = SDLK_COMPOSE;
+ 	ODD_keymap[XK_dead_ogonek&0xFF] = SDLK_COMPOSE;
+ 	ODD_keymap[XK_dead_iota&0xFF] = SDLK_COMPOSE;
+ 	ODD_keymap[XK_dead_voiced_sound&0xFF] = SDLK_COMPOSE;
+ 	ODD_keymap[XK_dead_semivoiced_sound&0xFF] = SDLK_COMPOSE;
+ 	ODD_keymap[XK_dead_belowdot&0xFF] = SDLK_COMPOSE;
+ 	ODD_keymap[XK_dead_hook&0xFF] = SDLK_COMPOSE;
+ 	ODD_keymap[XK_dead_horn&0xFF] = SDLK_COMPOSE;
+
 #ifdef XK_dead_circumflex
 	/* These X keysyms have 0xFE as the high byte */
 	ODD_keymap[XK_dead_circumflex&0xFF] = SDLK_CARET;
@@ -607,253 +817,83 @@
 	MISC_keymap[XK_Hyper_R&0xFF] = SDLK_MENU;   /* Windows "Menu" key */
 }
 
-#ifdef X_HAVE_UTF8_STRING
-Uint32 Utf8ToUcs4(const unsigned char *utf8)
-{
-	Uint32 c;
-	int i = 1;
-	int noOctets = 0;
-	int firstOctetMask = 0;
-	unsigned char firstOctet = utf8[0];
-	if (firstOctet < 0x80) {
-		/*
-		  Characters in the range:
-		    00000000 to 01111111 (ASCII Range)
-		  are stored in one octet:
-		    0xxxxxxx (The same as its ASCII representation)
-		  The least 6 significant bits of the first octet is the most 6 significant nonzero bits
-		  of the UCS4 representation.
-		*/
-		noOctets = 1;
-		firstOctetMask = 0x7F;  /* 0(1111111) - The most significant bit is ignored */
-	} else if ((firstOctet & 0xE0) /* get the most 3 significant bits by AND'ing with 11100000 */
-	              == 0xC0 ) {  /* see if those 3 bits are 110. If so, the char is in this range */
-		/*
-		  Characters in the range:
-		    00000000 10000000 to 00000111 11111111
-		  are stored in two octets:
-		    110xxxxx 10xxxxxx
-		  The least 5 significant bits of the first octet is the most 5 significant nonzero bits
-		  of the UCS4 representation.
-		*/
-		noOctets = 2;
-		firstOctetMask = 0x1F;  /* 000(11111) - The most 3 significant bits are ignored */
-	} else if ((firstOctet & 0xF0) /* get the most 4 significant bits by AND'ing with 11110000 */
-	              == 0xE0) {  /* see if those 4 bits are 1110. If so, the char is in this range */
-		/*
-		  Characters in the range:
-		    00001000 00000000 to 11111111 11111111
-		  are stored in three octets:
-		    1110xxxx 10xxxxxx 10xxxxxx
-		  The least 4 significant bits of the first octet is the most 4 significant nonzero bits
-		  of the UCS4 representation.
-		*/
-		noOctets = 3;
-		firstOctetMask = 0x0F; /* 0000(1111) - The most 4 significant bits are ignored */
-	} else if ((firstOctet & 0xF8) /* get the most 5 significant bits by AND'ing with 11111000 */
-	              == 0xF0) {  /* see if those 5 bits are 11110. If so, the char is in this range */
-		/*
-		  Characters in the range:
-		    00000001 00000000 00000000 to 00011111 11111111 11111111
-		  are stored in four octets:
-		    11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
-		  The least 3 significant bits of the first octet is the most 3 significant nonzero bits
-		  of the UCS4 representation.
-		*/
-		noOctets = 4;
-		firstOctetMask = 0x07; /* 11110(111) - The most 5 significant bits are ignored */
-	} else if ((firstOctet & 0xFC) /* get the most 6 significant bits by AND'ing with 11111100 */
-	              == 0xF8) { /* see if those 6 bits are 111110. If so, the char is in this range */
-		/*
-		  Characters in the range:
-		    00000000 00100000 00000000 00000000 to
-		    00000011 11111111 11111111 11111111
-		  are stored in five octets:
-		    111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
-		  The least 2 significant bits of the first octet is the most 2 significant nonzero bits
-		  of the UCS4 representation.
-		*/
-		noOctets = 5;
-		firstOctetMask = 0x03; /* 111110(11) - The most 6 significant bits are ignored */
-	} else if ((firstOctet & 0xFE) /* get the most 7 significant bits by AND'ing with 11111110 */
-	              == 0xFC) { /* see if those 7 bits are 1111110. If so, the char is in this range */
-		/*
-		  Characters in the range:
-		    00000100 00000000 00000000 00000000 to
-		    01111111 11111111 11111111 11111111
-		  are stored in six octets:
-		    1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
-		  The least significant bit of the first octet is the most significant nonzero bit
-		  of the UCS4 representation.
-		*/
-		noOctets = 6;
-		firstOctetMask = 0x01; /* 1111110(1) - The most 7 significant bits are ignored */
-	} else
-		return 0;  /* The given chunk is not a valid UTF-8 encoded Unicode character */
-	
-	/*
-	  The least noOctets significant bits of the first octet is the most 2 significant nonzero bits
-	  of the UCS4 representation.
-	  The first 6 bits of the UCS4 representation is the least 8-noOctets-1 significant bits of
-	  firstOctet if the character is not ASCII. If so, it's the least 7 significant bits of firstOctet.
-	  This done by AND'ing firstOctet with its mask to trim the bits used for identifying the
-	  number of continuing octets (if any) and leave only the free bits (the x's)
-	  Sample:
-	  1-octet:    0xxxxxxx  &  01111111 = 0xxxxxxx
-	  2-octets:  110xxxxx  &  00011111 = 000xxxxx
-	*/
-	c = firstOctet & firstOctetMask;
-	
-	/* Now, start filling c.ucs4 with the bits from the continuing octets from utf8. */
-	for (i = 1; i < noOctets; i++) {
-		/* A valid continuing octet is of the form 10xxxxxx */
-		if ((utf8[i] & 0xC0) /* get the most 2 significant bits by AND'ing with 11000000 */
-		    != 0x80) /* see if those 2 bits are 10. If not, the is a malformed sequence. */
-			/*The given chunk is a partial sequence at the end of a string that could
-			   begin a valid character */
-			return 0;
-		
-		/* Make room for the next 6-bits */
-		c <<= 6;
-		
-		/*
-		  Take only the least 6 significance bits of the current octet (utf8[i]) and fill the created room
-		  of c.ucs4 with them.
-		  This done by AND'ing utf8[i] with 00111111 and the OR'ing the result with c.ucs4.
-		*/
-		c |= utf8[i] & 0x3F;
-	}
-	return c;
-}
-#endif
-
-
-SDL_keysym *X11_TranslateKey(Display *display, XIC ic, XKeyEvent *xkey, KeyCode kc,
-			     SDL_keysym *keysym)
+/* Get the translated SDL virtual keysym */
+SDLKey X11_TranslateKeycode(Display *display, KeyCode kc)
 {
 	KeySym xsym;
+	SDLKey key;
 
-	/* Get the raw keyboard scancode */
-	keysym->scancode = kc;
 	xsym = pXKeycodeToKeysym(display, kc, 0);
 #ifdef DEBUG_KEYS
-	fprintf(stderr, "Translating key 0x%.4x (%d)\n", xsym, kc);
+	fprintf(stderr, "Translating key code %d -> 0x%.4x\n", kc, xsym);
 #endif
-	/* Get the translated SDL virtual keysym */
-	keysym->sym = SDLK_UNKNOWN;
+	key = SDLK_UNKNOWN;
 	if ( xsym ) {
 		switch (xsym>>8) {
-			case 0x1005FF:
+		    case 0x1005FF:
 #ifdef SunXK_F36
-				if ( xsym == SunXK_F36 )
-					keysym->sym = SDLK_F11;
+			if ( xsym == SunXK_F36 )
+				key = SDLK_F11;
 #endif
 #ifdef SunXK_F37
-				if ( xsym == SunXK_F37 )
-					keysym->sym = SDLK_F12;
+			if ( xsym == SunXK_F37 )
+				key = SDLK_F12;
 #endif
-				break;
-			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)(xsym&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[xsym&0xFF];
-				break;
-			case 0xFF:
-				keysym->sym = MISC_keymap[xsym&0xFF];
-				break;
-			default:
-				fprintf(stderr,
-					"X11: Unknown xsym, sym = 0x%04x\n",
+			break;
+		    case 0x00:	/* Latin 1 */
+			key = (SDLKey)(xsym & 0xFF);
+			break;
+		    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 */
+			/* These are wrong, but it's better than nothing */
+			key = (SDLKey)(xsym & 0xFF);
+			break;
+		    case 0xFE:
+			key = ODD_keymap[xsym&0xFF];
+			break;
+		    case 0xFF:
+			key = MISC_keymap[xsym&0xFF];
+			break;
+		    default:
+			/*
+			fprintf(stderr, "X11: Unhandled xsym, sym = 0x%04x\n",
 					(unsigned int)xsym);
-				break;
+			*/
+			break;
 		}
 	} else {
 		/* X11 doesn't know how to translate the key! */
 		switch (kc) {
-			/* Caution:
-			   These keycodes are from the Microsoft Keyboard
+		    /* Caution:
+		       These keycodes are from the Microsoft Keyboard
+		     */
+		    case 115:
+			key = SDLK_LSUPER;
+			break;
+		    case 116:
+			key = SDLK_RSUPER;
+			break;
+		    case 117:
+			key = SDLK_MENU;
+			break;
+		    default:
+			/*
+			 * no point in an error message; happens for
+			 * several keys when we get a keymap notify
 			 */
-			case 115:
-				keysym->sym = SDLK_LSUPER;
-				break;
-			case 116:
-				keysym->sym = SDLK_RSUPER;
-				break;
-			case 117:
-				keysym->sym = SDLK_MENU;
-				break;
-			default:
-				/*
-				 * no point in an error message; happens for
-				 * several keys when we get a keymap notify
-				 */
-				break;
+			break;
 		}
 	}
-	keysym->mod = KMOD_NONE;
-
-	/* If UNICODE is on, get the UNICODE value for the key */
-	keysym->unicode = 0;
-	if ( SDL_TranslateUNICODE && xkey ) {
-		static XComposeStatus state;
-
-
-#define BROKEN_XFREE86_INTERNATIONAL_KBD
-/* This appears to be a magical flag that is used with AltGr on
-   international keyboards to signal alternate key translations.
-   The flag doesn't show up when in fullscreen mode (?)
-   FIXME:  Check to see if this code is safe for other servers.
-*/
-#ifdef BROKEN_XFREE86_INTERNATIONAL_KBD
-		/* Work around what appears to be a bug in XFree86 */
-		if ( SDL_GetModState() & KMOD_MODE ) {
-			xkey->state |= (1<<13);
-		}
-#endif
-		/* Look up the translated value for the key event */
-
-		/* if there is no connection with the IM server, use the regular method */
-		if (ic == NULL || xkey->type != KeyPress) {
-			unsigned char keybuf[32];
-
-			if ( pXLookupString(xkey, (char *)keybuf, sizeof(keybuf),
-								NULL, &state) ) {
-				/*
-				* FIXME,: XLookupString() may yield more than one
-				* character, so we need a mechanism to allow for
-				* this (perhaps generate null keypress events with
-				* a unicode value)
-				*/
-				keysym->unicode = keybuf[0];
-			}
-		} else {  /* else, use the IM protocol */
-			#ifdef X_HAVE_UTF8_STRING
-			/* A UTF-8 character can be at most 6 bytes */
-			unsigned char keybuf[6];
-			pXSetICFocus(ic);
-			if ( pXutf8LookupString(ic, (XKeyPressedEvent *)xkey, (char *)keybuf, sizeof(keybuf),
-			                                    NULL, (Status *)&state) )
-				keysym->unicode = Utf8ToUcs4(keybuf);
-			pXUnsetICFocus(ic);
-			#endif
-		}
-	}
-	return(keysym);
+	return key;
 }
 
 /* X11 modifier masks for various keys */
@@ -969,12 +1009,10 @@
  * synthetic keypress/release events.
  * key_vec is a bit vector of keycodes (256 bits)
  */
-void X11_SetKeyboardState(Display *display, XIC ic, const char *key_vec)
+void X11_SetKeyboardState(Display *display, const char *key_vec)
 {
 	char keys_return[32];
 	int i;
-	KeyCode xcode[SDLK_LAST];
-	Uint8 new_kstate[SDLK_LAST];
 	Uint8 *kstate = SDL_GetKeyState(NULL);
 	SDLMod modstate;
 	Window junk_window;
@@ -1004,62 +1042,55 @@
 	}
 
 	/* Zero the new keyboard state and generate it */
-	memset(new_kstate, SDL_RELEASED, sizeof(new_kstate));
+	memset(kstate, 0, SDLK_LAST);
 	/*
 	 * An obvious optimisation is to check entire longwords at a time in
 	 * both loops, but we can't be sure the arrays are aligned so it's not
 	 * worth the extra complexity
 	 */
-	for(i = 0; i < 32; i++) {
+	for ( i = 0; i < 32; i++ ) {
 		int j;
-		if(!key_vec[i])
+		if ( !key_vec[i] )
 			continue;
-		for(j = 0; j < 8; j++) {
-			if(key_vec[i] & (1 << j)) {
-				SDL_keysym sk;
-				KeyCode kc = i << 3 | j;
-				X11_TranslateKey(display, ic, NULL, kc, &sk);
-				new_kstate[sk.sym] = SDL_PRESSED;
-				xcode[sk.sym] = kc;
-			}
-		}
-	}
-	for(i = SDLK_FIRST+1; i < SDLK_LAST; i++) {
-		int state = new_kstate[i];
-
-		if ( state == SDL_PRESSED ) {
-			switch (i) {
-				case SDLK_LSHIFT:
+		for ( j = 0; j < 8; j++ ) {
+			if ( key_vec[i] & (1 << j) ) {
+				SDLKey key;
+				KeyCode kc = (i << 3 | j);
+				key = X11_TranslateKeycode(display, kc);
+				if ( key == SDLK_UNKNOWN ) {
+					continue;
+				}
+				kstate[key] = SDL_PRESSED;
+				switch (key) {
+				    case SDLK_LSHIFT:
 					modstate |= KMOD_LSHIFT;
 					break;
-				case SDLK_RSHIFT:
+				    case SDLK_RSHIFT:
 					modstate |= KMOD_RSHIFT;
 					break;
-				case SDLK_LCTRL:
+				    case SDLK_LCTRL:
 					modstate |= KMOD_LCTRL;
 					break;
-				case SDLK_RCTRL:
+				    case SDLK_RCTRL:
 					modstate |= KMOD_RCTRL;
 					break;
-				case SDLK_LALT:
+				    case SDLK_LALT:
 					modstate |= KMOD_LALT;
 					break;
-				case SDLK_RALT:
+				    case SDLK_RALT:
 					modstate |= KMOD_RALT;
 					break;
-				case SDLK_LMETA:
+				    case SDLK_LMETA:
 					modstate |= KMOD_LMETA;
 					break;
-				case SDLK_RMETA:
+				    case SDLK_RMETA:
 					modstate |= KMOD_RMETA;
 					break;
-				default:
+				    default:
 					break;
+				}
 			}
 		}
-		if ( kstate[i] != state ) {
-			kstate[i] = state;
-		}
 	}
 
 	/* Hack - set toggle key state */