Resolved bug #130
authorSam Lantinga <slouken@libsdl.org>
Sat, 04 Feb 2006 08:35:11 +0000
changeset 1327d12a63a8d95a
parent 1326 9439c2f1da89
child 1328 27ddb06a0bca
Resolved bug #130
Use XFilterEvent() to handle dead-key composition under X11
Cleaned up the code in preparation for 1.3 API changes
src/events/SDL_keyboard.c
src/video/dga/SDL_dgaevents.c
src/video/x11/SDL_x11events.c
src/video/x11/SDL_x11events_c.h
src/video/x11/SDL_x11sym.h
src/video/x11/SDL_x11video.c
src/video/x11/SDL_x11video.h
     1.1 --- a/src/events/SDL_keyboard.c	Fri Feb 03 07:43:42 2006 +0000
     1.2 +++ b/src/events/SDL_keyboard.c	Sat Feb 04 08:35:11 2006 +0000
     1.3 @@ -397,6 +397,8 @@
     1.4  	if ( state == SDL_PRESSED ) {
     1.5  		keysym->mod = (SDLMod)modstate;
     1.6  		switch (keysym->sym) {
     1.7 +			case SDLK_UNKNOWN:
     1.8 +				break;
     1.9  			case SDLK_NUMLOCK:
    1.10  				modstate ^= KMOD_NUM;
    1.11  				if ( ! (modstate&KMOD_NUM) )
    1.12 @@ -442,6 +444,8 @@
    1.13  		}
    1.14  	} else {
    1.15  		switch (keysym->sym) {
    1.16 +			case SDLK_UNKNOWN:
    1.17 +				break;
    1.18  			case SDLK_NUMLOCK:
    1.19  			case SDLK_CAPSLOCK:
    1.20  				/* Only send keydown events */
    1.21 @@ -499,18 +503,20 @@
    1.22  			return(0);
    1.23  	}
    1.24  
    1.25 -	/* Drop events that don't change state */
    1.26 -	if ( SDL_KeyState[keysym->sym] == state ) {
    1.27 +	if ( keysym->sym != SDLK_UNKNOWN ) {
    1.28 +		/* Drop events that don't change state */
    1.29 +		if ( SDL_KeyState[keysym->sym] == state ) {
    1.30  #if 0
    1.31  printf("Keyboard event didn't change state - dropped!\n");
    1.32  #endif
    1.33 -		return(0);
    1.34 +			return(0);
    1.35 +		}
    1.36 +
    1.37 +		/* Update internal keyboard state */
    1.38 +		SDL_ModState = (SDLMod)modstate;
    1.39 +		SDL_KeyState[keysym->sym] = state;
    1.40  	}
    1.41  
    1.42 -	/* Update internal keyboard state */
    1.43 -	SDL_ModState = (SDLMod)modstate;
    1.44 -	SDL_KeyState[keysym->sym] = state;
    1.45 -
    1.46  	/* Post the event, if desired */
    1.47  	posted = 0;
    1.48  	if ( SDL_ProcessEvents[event.type] == SDL_ENABLE ) {
     2.1 --- a/src/video/dga/SDL_dgaevents.c	Fri Feb 03 07:43:42 2006 +0000
     2.2 +++ b/src/video/dga/SDL_dgaevents.c	Sat Feb 04 08:35:11 2006 +0000
     2.3 @@ -37,8 +37,7 @@
     2.4  /* Heheh we're using X11 event code */
     2.5  extern int X11_Pending(Display *display);
     2.6  extern void X11_InitKeymap(void);
     2.7 -extern SDL_keysym *X11_TranslateKey(Display *display, XIC ic, XKeyEvent *xkey,
     2.8 -				    KeyCode kc, SDL_keysym *keysym);
     2.9 +extern SDLKey X11_TranslateKeycode(Display *display, KeyCode kc);
    2.10  
    2.11  static int DGA_DispatchEvent(_THIS)
    2.12  {
    2.13 @@ -74,20 +73,64 @@
    2.14  	    }
    2.15  	    break;
    2.16  
    2.17 -	    /* Key press or release? */
    2.18 -	    case KeyPress:
    2.19 -	    case KeyRelease: {
    2.20 +	    /* Key press? */
    2.21 +	    case KeyPress: {
    2.22  		SDL_keysym keysym;
    2.23 +		KeyCode keycode;
    2.24  		XKeyEvent xkey;
    2.25  
    2.26  		SDL_NAME(XDGAKeyEventToXKeyEvent)(&xevent.xkey, &xkey);
    2.27 -		posted = SDL_PrivateKeyboard((xevent.type == KeyPress), 
    2.28 -					X11_TranslateKey(DGA_Display, NULL/*no XIC*/,
    2.29 -							 &xkey, xkey.keycode,
    2.30 -							 &keysym));
    2.31 +		keycode = xkey.keycode;
    2.32 +#ifdef DEBUG_XEVENTS
    2.33 +printf("KeyPress (X11 keycode = 0x%X)\n", xkey.keycode);
    2.34 +#endif
    2.35 +		/* Get the translated SDL virtual keysym */
    2.36 +		keysym.scancode = keycode;
    2.37 +		keysym.sym = X11_TranslateKeycode(DGA_Display, keycode);
    2.38 +		keysym.mod = KMOD_NONE;
    2.39 +		keysym.unicode = 0;
    2.40 +
    2.41 +		/* Look up the translated value for the key event */
    2.42 +		if ( SDL_TranslateUNICODE ) {
    2.43 +			static XComposeStatus state;
    2.44 +			char keybuf[32];
    2.45 +
    2.46 +			if ( pXLookupString(&xkey, keybuf, sizeof(keybuf), NULL, &state) ) {
    2.47 +				/*
    2.48 +				* FIXME: XLookupString() may yield more than one
    2.49 +				* character, so we need a mechanism to allow for
    2.50 +				* this (perhaps null keypress events with a
    2.51 +				* unicode value)
    2.52 +				*/
    2.53 +				keysym.unicode = (Uint8)keybuf[0];
    2.54 +			}
    2.55 +		}
    2.56 +		posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym);
    2.57  	    }
    2.58  	    break;
    2.59  
    2.60 +	    /* Key release? */
    2.61 +	    case KeyRelease: {
    2.62 +		SDL_keysym keysym;
    2.63 +		KeyCode keycode;
    2.64 +		XKeyEvent xkey;
    2.65 +
    2.66 +		SDL_NAME(XDGAKeyEventToXKeyEvent)(&xevent.xkey, &xkey);
    2.67 +		keycode = xkey.keycode;
    2.68 +#ifdef DEBUG_XEVENTS
    2.69 +printf("KeyRelease (X11 keycode = 0x%X)\n", xkey.keycode);
    2.70 +#endif
    2.71 +		/* Get the translated SDL virtual keysym */
    2.72 +		keysym.scancode = keycode;
    2.73 +		keysym.sym = X11_TranslateKeycode(DGA_Display, keycode);
    2.74 +		keysym.mod = KMOD_NONE;
    2.75 +		keysym.unicode = 0;
    2.76 +		posted = SDL_PrivateKeyboard(SDL_RELEASED, &keysym);
    2.77 +	    }
    2.78 +	    break;
    2.79 +
    2.80 +	    break;
    2.81 +
    2.82  	}
    2.83  	return(posted);
    2.84  }
     3.1 --- a/src/video/x11/SDL_x11events.c	Fri Feb 03 07:43:42 2006 +0000
     3.2 +++ b/src/video/x11/SDL_x11events.c	Sat Feb 04 08:35:11 2006 +0000
     3.3 @@ -57,8 +57,128 @@
     3.4  /* The translation tables from an X11 keysym to a SDL keysym */
     3.5  static SDLKey ODD_keymap[256];
     3.6  static SDLKey MISC_keymap[256];
     3.7 -SDL_keysym *X11_TranslateKey(Display *display, XIC ic, XKeyEvent *xkey, KeyCode kc,
     3.8 -			     SDL_keysym *keysym);
     3.9 +SDLKey X11_TranslateKeycode(Display *display, KeyCode kc);
    3.10 +
    3.11 +
    3.12 +#ifdef X_HAVE_UTF8_STRING
    3.13 +Uint32 Utf8ToUcs4(const Uint8 *utf8)
    3.14 +{
    3.15 +	Uint32 c;
    3.16 +	int i = 1;
    3.17 +	int noOctets = 0;
    3.18 +	int firstOctetMask = 0;
    3.19 +	unsigned char firstOctet = utf8[0];
    3.20 +	if (firstOctet < 0x80) {
    3.21 +		/*
    3.22 +		  Characters in the range:
    3.23 +		    00000000 to 01111111 (ASCII Range)
    3.24 +		  are stored in one octet:
    3.25 +		    0xxxxxxx (The same as its ASCII representation)
    3.26 +		  The least 6 significant bits of the first octet is the most 6 significant nonzero bits
    3.27 +		  of the UCS4 representation.
    3.28 +		*/
    3.29 +		noOctets = 1;
    3.30 +		firstOctetMask = 0x7F;  /* 0(1111111) - The most significant bit is ignored */
    3.31 +	} else if ((firstOctet & 0xE0) /* get the most 3 significant bits by AND'ing with 11100000 */
    3.32 +	              == 0xC0 ) {  /* see if those 3 bits are 110. If so, the char is in this range */
    3.33 +		/*
    3.34 +		  Characters in the range:
    3.35 +		    00000000 10000000 to 00000111 11111111
    3.36 +		  are stored in two octets:
    3.37 +		    110xxxxx 10xxxxxx
    3.38 +		  The least 5 significant bits of the first octet is the most 5 significant nonzero bits
    3.39 +		  of the UCS4 representation.
    3.40 +		*/
    3.41 +		noOctets = 2;
    3.42 +		firstOctetMask = 0x1F;  /* 000(11111) - The most 3 significant bits are ignored */
    3.43 +	} else if ((firstOctet & 0xF0) /* get the most 4 significant bits by AND'ing with 11110000 */
    3.44 +	              == 0xE0) {  /* see if those 4 bits are 1110. If so, the char is in this range */
    3.45 +		/*
    3.46 +		  Characters in the range:
    3.47 +		    00001000 00000000 to 11111111 11111111
    3.48 +		  are stored in three octets:
    3.49 +		    1110xxxx 10xxxxxx 10xxxxxx
    3.50 +		  The least 4 significant bits of the first octet is the most 4 significant nonzero bits
    3.51 +		  of the UCS4 representation.
    3.52 +		*/
    3.53 +		noOctets = 3;
    3.54 +		firstOctetMask = 0x0F; /* 0000(1111) - The most 4 significant bits are ignored */
    3.55 +	} else if ((firstOctet & 0xF8) /* get the most 5 significant bits by AND'ing with 11111000 */
    3.56 +	              == 0xF0) {  /* see if those 5 bits are 11110. If so, the char is in this range */
    3.57 +		/*
    3.58 +		  Characters in the range:
    3.59 +		    00000001 00000000 00000000 to 00011111 11111111 11111111
    3.60 +		  are stored in four octets:
    3.61 +		    11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
    3.62 +		  The least 3 significant bits of the first octet is the most 3 significant nonzero bits
    3.63 +		  of the UCS4 representation.
    3.64 +		*/
    3.65 +		noOctets = 4;
    3.66 +		firstOctetMask = 0x07; /* 11110(111) - The most 5 significant bits are ignored */
    3.67 +	} else if ((firstOctet & 0xFC) /* get the most 6 significant bits by AND'ing with 11111100 */
    3.68 +	              == 0xF8) { /* see if those 6 bits are 111110. If so, the char is in this range */
    3.69 +		/*
    3.70 +		  Characters in the range:
    3.71 +		    00000000 00100000 00000000 00000000 to
    3.72 +		    00000011 11111111 11111111 11111111
    3.73 +		  are stored in five octets:
    3.74 +		    111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
    3.75 +		  The least 2 significant bits of the first octet is the most 2 significant nonzero bits
    3.76 +		  of the UCS4 representation.
    3.77 +		*/
    3.78 +		noOctets = 5;
    3.79 +		firstOctetMask = 0x03; /* 111110(11) - The most 6 significant bits are ignored */
    3.80 +	} else if ((firstOctet & 0xFE) /* get the most 7 significant bits by AND'ing with 11111110 */
    3.81 +	              == 0xFC) { /* see if those 7 bits are 1111110. If so, the char is in this range */
    3.82 +		/*
    3.83 +		  Characters in the range:
    3.84 +		    00000100 00000000 00000000 00000000 to
    3.85 +		    01111111 11111111 11111111 11111111
    3.86 +		  are stored in six octets:
    3.87 +		    1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
    3.88 +		  The least significant bit of the first octet is the most significant nonzero bit
    3.89 +		  of the UCS4 representation.
    3.90 +		*/
    3.91 +		noOctets = 6;
    3.92 +		firstOctetMask = 0x01; /* 1111110(1) - The most 7 significant bits are ignored */
    3.93 +	} else
    3.94 +		return 0;  /* The given chunk is not a valid UTF-8 encoded Unicode character */
    3.95 +	
    3.96 +	/*
    3.97 +	  The least noOctets significant bits of the first octet is the most 2 significant nonzero bits
    3.98 +	  of the UCS4 representation.
    3.99 +	  The first 6 bits of the UCS4 representation is the least 8-noOctets-1 significant bits of
   3.100 +	  firstOctet if the character is not ASCII. If so, it's the least 7 significant bits of firstOctet.
   3.101 +	  This done by AND'ing firstOctet with its mask to trim the bits used for identifying the
   3.102 +	  number of continuing octets (if any) and leave only the free bits (the x's)
   3.103 +	  Sample:
   3.104 +	  1-octet:    0xxxxxxx  &  01111111 = 0xxxxxxx
   3.105 +	  2-octets:  110xxxxx  &  00011111 = 000xxxxx
   3.106 +	*/
   3.107 +	c = firstOctet & firstOctetMask;
   3.108 +	
   3.109 +	/* Now, start filling c.ucs4 with the bits from the continuing octets from utf8. */
   3.110 +	for (i = 1; i < noOctets; i++) {
   3.111 +		/* A valid continuing octet is of the form 10xxxxxx */
   3.112 +		if ((utf8[i] & 0xC0) /* get the most 2 significant bits by AND'ing with 11000000 */
   3.113 +		    != 0x80) /* see if those 2 bits are 10. If not, the is a malformed sequence. */
   3.114 +			/*The given chunk is a partial sequence at the end of a string that could
   3.115 +			   begin a valid character */
   3.116 +			return 0;
   3.117 +		
   3.118 +		/* Make room for the next 6-bits */
   3.119 +		c <<= 6;
   3.120 +		
   3.121 +		/*
   3.122 +		  Take only the least 6 significance bits of the current octet (utf8[i]) and fill the created room
   3.123 +		  of c.ucs4 with them.
   3.124 +		  This done by AND'ing utf8[i] with 00111111 and the OR'ing the result with c.ucs4.
   3.125 +		*/
   3.126 +		c |= utf8[i] & 0x3F;
   3.127 +	}
   3.128 +	return c;
   3.129 +}
   3.130 +#endif
   3.131  
   3.132  /* Check to see if this is a repeated key.
   3.133     (idea shamelessly lifted from GII -- thanks guys! :)
   3.134 @@ -212,6 +332,10 @@
   3.135  #endif
   3.136  		posted = SDL_PrivateAppActive(1, SDL_APPINPUTFOCUS);
   3.137  
   3.138 +		if ( SDL_IC != NULL ) {
   3.139 +			pXSetICFocus(SDL_IC);
   3.140 +		}
   3.141 +
   3.142  		/* Queue entry into fullscreen mode */
   3.143  		switch_waiting = 0x01 | SDL_FULLSCREEN;
   3.144  		switch_time = SDL_GetTicks() + 1500;
   3.145 @@ -225,6 +349,10 @@
   3.146  #endif
   3.147  		posted = SDL_PrivateAppActive(0, SDL_APPINPUTFOCUS);
   3.148  
   3.149 +		if ( SDL_IC != NULL ) {
   3.150 +			pXUnsetICFocus(SDL_IC);
   3.151 +		}
   3.152 +
   3.153  		/* Queue leaving fullscreen mode */
   3.154  		switch_waiting = 0x01;
   3.155  		switch_time = SDL_GetTicks() + 200;
   3.156 @@ -236,7 +364,7 @@
   3.157  #ifdef DEBUG_XEVENTS
   3.158  printf("KeymapNotify!\n");
   3.159  #endif
   3.160 -		X11_SetKeyboardState(SDL_Display, SDL_IC,  xevent.xkeymap.key_vector);
   3.161 +		X11_SetKeyboardState(SDL_Display,  xevent.xkeymap.key_vector);
   3.162  	    }
   3.163  	    break;
   3.164  
   3.165 @@ -282,32 +410,94 @@
   3.166  
   3.167  	    /* Key press? */
   3.168  	    case KeyPress: {
   3.169 +		static SDL_keysym saved_keysym;
   3.170  		SDL_keysym keysym;
   3.171 +		KeyCode keycode = xevent.xkey.keycode;
   3.172  
   3.173  #ifdef DEBUG_XEVENTS
   3.174  printf("KeyPress (X11 keycode = 0x%X)\n", xevent.xkey.keycode);
   3.175  #endif
   3.176 -		posted = SDL_PrivateKeyboard(SDL_PRESSED,
   3.177 -				X11_TranslateKey(SDL_Display, SDL_IC, &xevent.xkey,
   3.178 -						 xevent.xkey.keycode,
   3.179 -						 &keysym));
   3.180 +		/* Get the translated SDL virtual keysym */
   3.181 +		if ( keycode ) {
   3.182 +			keysym.scancode = keycode;
   3.183 +			keysym.sym = X11_TranslateKeycode(SDL_Display, keycode);
   3.184 +			keysym.mod = KMOD_NONE;
   3.185 +			keysym.unicode = 0;
   3.186 +		} else {
   3.187 +			keysym = saved_keysym;
   3.188 +		}
   3.189 +
   3.190 +		/* If we're not doing translation, we're done! */
   3.191 +		if ( !SDL_TranslateUNICODE ) {
   3.192 +			posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym);
   3.193 +			break;
   3.194 +		}
   3.195 +
   3.196 +		if ( pXFilterEvent(&xevent, None) ) {
   3.197 +			if ( xevent.xkey.keycode ) {
   3.198 +				posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym);
   3.199 +			} else {
   3.200 +				/* Save event to be associated with IM text
   3.201 +				   In 1.3 we'll have a text event instead.. */
   3.202 +				saved_keysym = keysym;
   3.203 +			}
   3.204 +			break;
   3.205 +		}
   3.206 +
   3.207 +		/* Look up the translated value for the key event */
   3.208 +#ifdef X_HAVE_UTF8_STRING
   3.209 +		if ( SDL_IC != NULL ) {
   3.210 +			static Status state;
   3.211 +			/* A UTF-8 character can be at most 6 bytes */
   3.212 +			char keybuf[6];
   3.213 +			if ( pXutf8LookupString(SDL_IC, &xevent.xkey,
   3.214 +			                        keybuf, sizeof(keybuf),
   3.215 +			                        NULL, &state) ) {
   3.216 +				keysym.unicode = Utf8ToUcs4((Uint8*)keybuf);
   3.217 +			}
   3.218 +		}
   3.219 +		else
   3.220 +#endif
   3.221 +		{
   3.222 +			static XComposeStatus state;
   3.223 +			char keybuf[32];
   3.224 +
   3.225 +			if ( pXLookupString(&xevent.xkey,
   3.226 +			                    keybuf, sizeof(keybuf),
   3.227 +			                    NULL, &state) ) {
   3.228 +				/*
   3.229 +				* FIXME: XLookupString() may yield more than one
   3.230 +				* character, so we need a mechanism to allow for
   3.231 +				* this (perhaps null keypress events with a
   3.232 +				* unicode value)
   3.233 +				*/
   3.234 +				keysym.unicode = (Uint8)keybuf[0];
   3.235 +			}
   3.236 +		}
   3.237 +		posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym);
   3.238  	    }
   3.239  	    break;
   3.240  
   3.241  	    /* Key release? */
   3.242  	    case KeyRelease: {
   3.243  		SDL_keysym keysym;
   3.244 +		KeyCode keycode = xevent.xkey.keycode;
   3.245  
   3.246  #ifdef DEBUG_XEVENTS
   3.247  printf("KeyRelease (X11 keycode = 0x%X)\n", xevent.xkey.keycode);
   3.248  #endif
   3.249  		/* Check to see if this is a repeated key */
   3.250 -		if ( ! X11_KeyRepeat(SDL_Display, &xevent) ) {
   3.251 -			posted = SDL_PrivateKeyboard(SDL_RELEASED, 
   3.252 -				X11_TranslateKey(SDL_Display, SDL_IC,  &xevent.xkey,
   3.253 -						 xevent.xkey.keycode,
   3.254 -						 &keysym));
   3.255 +		if ( X11_KeyRepeat(SDL_Display, &xevent) ) {
   3.256 +			break;
   3.257  		}
   3.258 +
   3.259 +		/* Get the translated SDL virtual keysym */
   3.260 +		keysym.scancode = keycode;
   3.261 +		keysym.sym = X11_TranslateKeycode(SDL_Display, keycode);
   3.262 +		keysym.mod = KMOD_NONE;
   3.263 +		keysym.unicode = 0;
   3.264 +
   3.265 +		posted = SDL_PrivateKeyboard(SDL_RELEASED, &keysym);
   3.266  	    }
   3.267  	    break;
   3.268  
   3.269 @@ -507,6 +697,26 @@
   3.270  	for ( i=0; i<SDL_TABLESIZE(ODD_keymap); ++i )
   3.271  		ODD_keymap[i] = SDLK_UNKNOWN;
   3.272  
   3.273 + 	/* Some of these might be mappable to an existing SDLK_ code */
   3.274 + 	ODD_keymap[XK_dead_grave&0xFF] = SDLK_COMPOSE;
   3.275 + 	ODD_keymap[XK_dead_acute&0xFF] = SDLK_COMPOSE;
   3.276 + 	ODD_keymap[XK_dead_tilde&0xFF] = SDLK_COMPOSE;
   3.277 + 	ODD_keymap[XK_dead_macron&0xFF] = SDLK_COMPOSE;
   3.278 + 	ODD_keymap[XK_dead_breve&0xFF] = SDLK_COMPOSE;
   3.279 + 	ODD_keymap[XK_dead_abovedot&0xFF] = SDLK_COMPOSE;
   3.280 + 	ODD_keymap[XK_dead_diaeresis&0xFF] = SDLK_COMPOSE;
   3.281 + 	ODD_keymap[XK_dead_abovering&0xFF] = SDLK_COMPOSE;
   3.282 + 	ODD_keymap[XK_dead_doubleacute&0xFF] = SDLK_COMPOSE;
   3.283 + 	ODD_keymap[XK_dead_caron&0xFF] = SDLK_COMPOSE;
   3.284 + 	ODD_keymap[XK_dead_cedilla&0xFF] = SDLK_COMPOSE;
   3.285 + 	ODD_keymap[XK_dead_ogonek&0xFF] = SDLK_COMPOSE;
   3.286 + 	ODD_keymap[XK_dead_iota&0xFF] = SDLK_COMPOSE;
   3.287 + 	ODD_keymap[XK_dead_voiced_sound&0xFF] = SDLK_COMPOSE;
   3.288 + 	ODD_keymap[XK_dead_semivoiced_sound&0xFF] = SDLK_COMPOSE;
   3.289 + 	ODD_keymap[XK_dead_belowdot&0xFF] = SDLK_COMPOSE;
   3.290 + 	ODD_keymap[XK_dead_hook&0xFF] = SDLK_COMPOSE;
   3.291 + 	ODD_keymap[XK_dead_horn&0xFF] = SDLK_COMPOSE;
   3.292 +
   3.293  #ifdef XK_dead_circumflex
   3.294  	/* These X keysyms have 0xFE as the high byte */
   3.295  	ODD_keymap[XK_dead_circumflex&0xFF] = SDLK_CARET;
   3.296 @@ -607,253 +817,83 @@
   3.297  	MISC_keymap[XK_Hyper_R&0xFF] = SDLK_MENU;   /* Windows "Menu" key */
   3.298  }
   3.299  
   3.300 -#ifdef X_HAVE_UTF8_STRING
   3.301 -Uint32 Utf8ToUcs4(const unsigned char *utf8)
   3.302 -{
   3.303 -	Uint32 c;
   3.304 -	int i = 1;
   3.305 -	int noOctets = 0;
   3.306 -	int firstOctetMask = 0;
   3.307 -	unsigned char firstOctet = utf8[0];
   3.308 -	if (firstOctet < 0x80) {
   3.309 -		/*
   3.310 -		  Characters in the range:
   3.311 -		    00000000 to 01111111 (ASCII Range)
   3.312 -		  are stored in one octet:
   3.313 -		    0xxxxxxx (The same as its ASCII representation)
   3.314 -		  The least 6 significant bits of the first octet is the most 6 significant nonzero bits
   3.315 -		  of the UCS4 representation.
   3.316 -		*/
   3.317 -		noOctets = 1;
   3.318 -		firstOctetMask = 0x7F;  /* 0(1111111) - The most significant bit is ignored */
   3.319 -	} else if ((firstOctet & 0xE0) /* get the most 3 significant bits by AND'ing with 11100000 */
   3.320 -	              == 0xC0 ) {  /* see if those 3 bits are 110. If so, the char is in this range */
   3.321 -		/*
   3.322 -		  Characters in the range:
   3.323 -		    00000000 10000000 to 00000111 11111111
   3.324 -		  are stored in two octets:
   3.325 -		    110xxxxx 10xxxxxx
   3.326 -		  The least 5 significant bits of the first octet is the most 5 significant nonzero bits
   3.327 -		  of the UCS4 representation.
   3.328 -		*/
   3.329 -		noOctets = 2;
   3.330 -		firstOctetMask = 0x1F;  /* 000(11111) - The most 3 significant bits are ignored */
   3.331 -	} else if ((firstOctet & 0xF0) /* get the most 4 significant bits by AND'ing with 11110000 */
   3.332 -	              == 0xE0) {  /* see if those 4 bits are 1110. If so, the char is in this range */
   3.333 -		/*
   3.334 -		  Characters in the range:
   3.335 -		    00001000 00000000 to 11111111 11111111
   3.336 -		  are stored in three octets:
   3.337 -		    1110xxxx 10xxxxxx 10xxxxxx
   3.338 -		  The least 4 significant bits of the first octet is the most 4 significant nonzero bits
   3.339 -		  of the UCS4 representation.
   3.340 -		*/
   3.341 -		noOctets = 3;
   3.342 -		firstOctetMask = 0x0F; /* 0000(1111) - The most 4 significant bits are ignored */
   3.343 -	} else if ((firstOctet & 0xF8) /* get the most 5 significant bits by AND'ing with 11111000 */
   3.344 -	              == 0xF0) {  /* see if those 5 bits are 11110. If so, the char is in this range */
   3.345 -		/*
   3.346 -		  Characters in the range:
   3.347 -		    00000001 00000000 00000000 to 00011111 11111111 11111111
   3.348 -		  are stored in four octets:
   3.349 -		    11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
   3.350 -		  The least 3 significant bits of the first octet is the most 3 significant nonzero bits
   3.351 -		  of the UCS4 representation.
   3.352 -		*/
   3.353 -		noOctets = 4;
   3.354 -		firstOctetMask = 0x07; /* 11110(111) - The most 5 significant bits are ignored */
   3.355 -	} else if ((firstOctet & 0xFC) /* get the most 6 significant bits by AND'ing with 11111100 */
   3.356 -	              == 0xF8) { /* see if those 6 bits are 111110. If so, the char is in this range */
   3.357 -		/*
   3.358 -		  Characters in the range:
   3.359 -		    00000000 00100000 00000000 00000000 to
   3.360 -		    00000011 11111111 11111111 11111111
   3.361 -		  are stored in five octets:
   3.362 -		    111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
   3.363 -		  The least 2 significant bits of the first octet is the most 2 significant nonzero bits
   3.364 -		  of the UCS4 representation.
   3.365 -		*/
   3.366 -		noOctets = 5;
   3.367 -		firstOctetMask = 0x03; /* 111110(11) - The most 6 significant bits are ignored */
   3.368 -	} else if ((firstOctet & 0xFE) /* get the most 7 significant bits by AND'ing with 11111110 */
   3.369 -	              == 0xFC) { /* see if those 7 bits are 1111110. If so, the char is in this range */
   3.370 -		/*
   3.371 -		  Characters in the range:
   3.372 -		    00000100 00000000 00000000 00000000 to
   3.373 -		    01111111 11111111 11111111 11111111
   3.374 -		  are stored in six octets:
   3.375 -		    1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
   3.376 -		  The least significant bit of the first octet is the most significant nonzero bit
   3.377 -		  of the UCS4 representation.
   3.378 -		*/
   3.379 -		noOctets = 6;
   3.380 -		firstOctetMask = 0x01; /* 1111110(1) - The most 7 significant bits are ignored */
   3.381 -	} else
   3.382 -		return 0;  /* The given chunk is not a valid UTF-8 encoded Unicode character */
   3.383 -	
   3.384 -	/*
   3.385 -	  The least noOctets significant bits of the first octet is the most 2 significant nonzero bits
   3.386 -	  of the UCS4 representation.
   3.387 -	  The first 6 bits of the UCS4 representation is the least 8-noOctets-1 significant bits of
   3.388 -	  firstOctet if the character is not ASCII. If so, it's the least 7 significant bits of firstOctet.
   3.389 -	  This done by AND'ing firstOctet with its mask to trim the bits used for identifying the
   3.390 -	  number of continuing octets (if any) and leave only the free bits (the x's)
   3.391 -	  Sample:
   3.392 -	  1-octet:    0xxxxxxx  &  01111111 = 0xxxxxxx
   3.393 -	  2-octets:  110xxxxx  &  00011111 = 000xxxxx
   3.394 -	*/
   3.395 -	c = firstOctet & firstOctetMask;
   3.396 -	
   3.397 -	/* Now, start filling c.ucs4 with the bits from the continuing octets from utf8. */
   3.398 -	for (i = 1; i < noOctets; i++) {
   3.399 -		/* A valid continuing octet is of the form 10xxxxxx */
   3.400 -		if ((utf8[i] & 0xC0) /* get the most 2 significant bits by AND'ing with 11000000 */
   3.401 -		    != 0x80) /* see if those 2 bits are 10. If not, the is a malformed sequence. */
   3.402 -			/*The given chunk is a partial sequence at the end of a string that could
   3.403 -			   begin a valid character */
   3.404 -			return 0;
   3.405 -		
   3.406 -		/* Make room for the next 6-bits */
   3.407 -		c <<= 6;
   3.408 -		
   3.409 -		/*
   3.410 -		  Take only the least 6 significance bits of the current octet (utf8[i]) and fill the created room
   3.411 -		  of c.ucs4 with them.
   3.412 -		  This done by AND'ing utf8[i] with 00111111 and the OR'ing the result with c.ucs4.
   3.413 -		*/
   3.414 -		c |= utf8[i] & 0x3F;
   3.415 -	}
   3.416 -	return c;
   3.417 -}
   3.418 -#endif
   3.419 -
   3.420 -
   3.421 -SDL_keysym *X11_TranslateKey(Display *display, XIC ic, XKeyEvent *xkey, KeyCode kc,
   3.422 -			     SDL_keysym *keysym)
   3.423 +/* Get the translated SDL virtual keysym */
   3.424 +SDLKey X11_TranslateKeycode(Display *display, KeyCode kc)
   3.425  {
   3.426  	KeySym xsym;
   3.427 +	SDLKey key;
   3.428  
   3.429 -	/* Get the raw keyboard scancode */
   3.430 -	keysym->scancode = kc;
   3.431  	xsym = pXKeycodeToKeysym(display, kc, 0);
   3.432  #ifdef DEBUG_KEYS
   3.433 -	fprintf(stderr, "Translating key 0x%.4x (%d)\n", xsym, kc);
   3.434 +	fprintf(stderr, "Translating key code %d -> 0x%.4x\n", kc, xsym);
   3.435  #endif
   3.436 -	/* Get the translated SDL virtual keysym */
   3.437 -	keysym->sym = SDLK_UNKNOWN;
   3.438 +	key = SDLK_UNKNOWN;
   3.439  	if ( xsym ) {
   3.440  		switch (xsym>>8) {
   3.441 -			case 0x1005FF:
   3.442 +		    case 0x1005FF:
   3.443  #ifdef SunXK_F36
   3.444 -				if ( xsym == SunXK_F36 )
   3.445 -					keysym->sym = SDLK_F11;
   3.446 +			if ( xsym == SunXK_F36 )
   3.447 +				key = SDLK_F11;
   3.448  #endif
   3.449  #ifdef SunXK_F37
   3.450 -				if ( xsym == SunXK_F37 )
   3.451 -					keysym->sym = SDLK_F12;
   3.452 +			if ( xsym == SunXK_F37 )
   3.453 +				key = SDLK_F12;
   3.454  #endif
   3.455 -				break;
   3.456 -			case 0x00:	/* Latin 1 */
   3.457 -			case 0x01:	/* Latin 2 */
   3.458 -			case 0x02:	/* Latin 3 */
   3.459 -			case 0x03:	/* Latin 4 */
   3.460 -			case 0x04:	/* Katakana */
   3.461 -			case 0x05:	/* Arabic */
   3.462 -			case 0x06:	/* Cyrillic */
   3.463 -			case 0x07:	/* Greek */
   3.464 -			case 0x08:	/* Technical */
   3.465 -			case 0x0A:	/* Publishing */
   3.466 -			case 0x0C:	/* Hebrew */
   3.467 -			case 0x0D:	/* Thai */
   3.468 -				keysym->sym = (SDLKey)(xsym&0xFF);
   3.469 -				/* Map capital letter syms to lowercase */
   3.470 -				if ((keysym->sym >= 'A')&&(keysym->sym <= 'Z'))
   3.471 -					keysym->sym += ('a'-'A');
   3.472 -				break;
   3.473 -			case 0xFE:
   3.474 -				keysym->sym = ODD_keymap[xsym&0xFF];
   3.475 -				break;
   3.476 -			case 0xFF:
   3.477 -				keysym->sym = MISC_keymap[xsym&0xFF];
   3.478 -				break;
   3.479 -			default:
   3.480 -				fprintf(stderr,
   3.481 -					"X11: Unknown xsym, sym = 0x%04x\n",
   3.482 +			break;
   3.483 +		    case 0x00:	/* Latin 1 */
   3.484 +			key = (SDLKey)(xsym & 0xFF);
   3.485 +			break;
   3.486 +		    case 0x01:	/* Latin 2 */
   3.487 +		    case 0x02:	/* Latin 3 */
   3.488 +		    case 0x03:	/* Latin 4 */
   3.489 +		    case 0x04:	/* Katakana */
   3.490 +		    case 0x05:	/* Arabic */
   3.491 +		    case 0x06:	/* Cyrillic */
   3.492 +		    case 0x07:	/* Greek */
   3.493 +		    case 0x08:	/* Technical */
   3.494 +		    case 0x0A:	/* Publishing */
   3.495 +		    case 0x0C:	/* Hebrew */
   3.496 +		    case 0x0D:	/* Thai */
   3.497 +			/* These are wrong, but it's better than nothing */
   3.498 +			key = (SDLKey)(xsym & 0xFF);
   3.499 +			break;
   3.500 +		    case 0xFE:
   3.501 +			key = ODD_keymap[xsym&0xFF];
   3.502 +			break;
   3.503 +		    case 0xFF:
   3.504 +			key = MISC_keymap[xsym&0xFF];
   3.505 +			break;
   3.506 +		    default:
   3.507 +			/*
   3.508 +			fprintf(stderr, "X11: Unhandled xsym, sym = 0x%04x\n",
   3.509  					(unsigned int)xsym);
   3.510 -				break;
   3.511 +			*/
   3.512 +			break;
   3.513  		}
   3.514  	} else {
   3.515  		/* X11 doesn't know how to translate the key! */
   3.516  		switch (kc) {
   3.517 -			/* Caution:
   3.518 -			   These keycodes are from the Microsoft Keyboard
   3.519 +		    /* Caution:
   3.520 +		       These keycodes are from the Microsoft Keyboard
   3.521 +		     */
   3.522 +		    case 115:
   3.523 +			key = SDLK_LSUPER;
   3.524 +			break;
   3.525 +		    case 116:
   3.526 +			key = SDLK_RSUPER;
   3.527 +			break;
   3.528 +		    case 117:
   3.529 +			key = SDLK_MENU;
   3.530 +			break;
   3.531 +		    default:
   3.532 +			/*
   3.533 +			 * no point in an error message; happens for
   3.534 +			 * several keys when we get a keymap notify
   3.535  			 */
   3.536 -			case 115:
   3.537 -				keysym->sym = SDLK_LSUPER;
   3.538 -				break;
   3.539 -			case 116:
   3.540 -				keysym->sym = SDLK_RSUPER;
   3.541 -				break;
   3.542 -			case 117:
   3.543 -				keysym->sym = SDLK_MENU;
   3.544 -				break;
   3.545 -			default:
   3.546 -				/*
   3.547 -				 * no point in an error message; happens for
   3.548 -				 * several keys when we get a keymap notify
   3.549 -				 */
   3.550 -				break;
   3.551 +			break;
   3.552  		}
   3.553  	}
   3.554 -	keysym->mod = KMOD_NONE;
   3.555 -
   3.556 -	/* If UNICODE is on, get the UNICODE value for the key */
   3.557 -	keysym->unicode = 0;
   3.558 -	if ( SDL_TranslateUNICODE && xkey ) {
   3.559 -		static XComposeStatus state;
   3.560 -
   3.561 -
   3.562 -#define BROKEN_XFREE86_INTERNATIONAL_KBD
   3.563 -/* This appears to be a magical flag that is used with AltGr on
   3.564 -   international keyboards to signal alternate key translations.
   3.565 -   The flag doesn't show up when in fullscreen mode (?)
   3.566 -   FIXME:  Check to see if this code is safe for other servers.
   3.567 -*/
   3.568 -#ifdef BROKEN_XFREE86_INTERNATIONAL_KBD
   3.569 -		/* Work around what appears to be a bug in XFree86 */
   3.570 -		if ( SDL_GetModState() & KMOD_MODE ) {
   3.571 -			xkey->state |= (1<<13);
   3.572 -		}
   3.573 -#endif
   3.574 -		/* Look up the translated value for the key event */
   3.575 -
   3.576 -		/* if there is no connection with the IM server, use the regular method */
   3.577 -		if (ic == NULL || xkey->type != KeyPress) {
   3.578 -			unsigned char keybuf[32];
   3.579 -
   3.580 -			if ( pXLookupString(xkey, (char *)keybuf, sizeof(keybuf),
   3.581 -								NULL, &state) ) {
   3.582 -				/*
   3.583 -				* FIXME,: XLookupString() may yield more than one
   3.584 -				* character, so we need a mechanism to allow for
   3.585 -				* this (perhaps generate null keypress events with
   3.586 -				* a unicode value)
   3.587 -				*/
   3.588 -				keysym->unicode = keybuf[0];
   3.589 -			}
   3.590 -		} else {  /* else, use the IM protocol */
   3.591 -			#ifdef X_HAVE_UTF8_STRING
   3.592 -			/* A UTF-8 character can be at most 6 bytes */
   3.593 -			unsigned char keybuf[6];
   3.594 -			pXSetICFocus(ic);
   3.595 -			if ( pXutf8LookupString(ic, (XKeyPressedEvent *)xkey, (char *)keybuf, sizeof(keybuf),
   3.596 -			                                    NULL, (Status *)&state) )
   3.597 -				keysym->unicode = Utf8ToUcs4(keybuf);
   3.598 -			pXUnsetICFocus(ic);
   3.599 -			#endif
   3.600 -		}
   3.601 -	}
   3.602 -	return(keysym);
   3.603 +	return key;
   3.604  }
   3.605  
   3.606  /* X11 modifier masks for various keys */
   3.607 @@ -969,12 +1009,10 @@
   3.608   * synthetic keypress/release events.
   3.609   * key_vec is a bit vector of keycodes (256 bits)
   3.610   */
   3.611 -void X11_SetKeyboardState(Display *display, XIC ic, const char *key_vec)
   3.612 +void X11_SetKeyboardState(Display *display, const char *key_vec)
   3.613  {
   3.614  	char keys_return[32];
   3.615  	int i;
   3.616 -	KeyCode xcode[SDLK_LAST];
   3.617 -	Uint8 new_kstate[SDLK_LAST];
   3.618  	Uint8 *kstate = SDL_GetKeyState(NULL);
   3.619  	SDLMod modstate;
   3.620  	Window junk_window;
   3.621 @@ -1004,62 +1042,55 @@
   3.622  	}
   3.623  
   3.624  	/* Zero the new keyboard state and generate it */
   3.625 -	memset(new_kstate, SDL_RELEASED, sizeof(new_kstate));
   3.626 +	memset(kstate, 0, SDLK_LAST);
   3.627  	/*
   3.628  	 * An obvious optimisation is to check entire longwords at a time in
   3.629  	 * both loops, but we can't be sure the arrays are aligned so it's not
   3.630  	 * worth the extra complexity
   3.631  	 */
   3.632 -	for(i = 0; i < 32; i++) {
   3.633 +	for ( i = 0; i < 32; i++ ) {
   3.634  		int j;
   3.635 -		if(!key_vec[i])
   3.636 +		if ( !key_vec[i] )
   3.637  			continue;
   3.638 -		for(j = 0; j < 8; j++) {
   3.639 -			if(key_vec[i] & (1 << j)) {
   3.640 -				SDL_keysym sk;
   3.641 -				KeyCode kc = i << 3 | j;
   3.642 -				X11_TranslateKey(display, ic, NULL, kc, &sk);
   3.643 -				new_kstate[sk.sym] = SDL_PRESSED;
   3.644 -				xcode[sk.sym] = kc;
   3.645 -			}
   3.646 -		}
   3.647 -	}
   3.648 -	for(i = SDLK_FIRST+1; i < SDLK_LAST; i++) {
   3.649 -		int state = new_kstate[i];
   3.650 -
   3.651 -		if ( state == SDL_PRESSED ) {
   3.652 -			switch (i) {
   3.653 -				case SDLK_LSHIFT:
   3.654 +		for ( j = 0; j < 8; j++ ) {
   3.655 +			if ( key_vec[i] & (1 << j) ) {
   3.656 +				SDLKey key;
   3.657 +				KeyCode kc = (i << 3 | j);
   3.658 +				key = X11_TranslateKeycode(display, kc);
   3.659 +				if ( key == SDLK_UNKNOWN ) {
   3.660 +					continue;
   3.661 +				}
   3.662 +				kstate[key] = SDL_PRESSED;
   3.663 +				switch (key) {
   3.664 +				    case SDLK_LSHIFT:
   3.665  					modstate |= KMOD_LSHIFT;
   3.666  					break;
   3.667 -				case SDLK_RSHIFT:
   3.668 +				    case SDLK_RSHIFT:
   3.669  					modstate |= KMOD_RSHIFT;
   3.670  					break;
   3.671 -				case SDLK_LCTRL:
   3.672 +				    case SDLK_LCTRL:
   3.673  					modstate |= KMOD_LCTRL;
   3.674  					break;
   3.675 -				case SDLK_RCTRL:
   3.676 +				    case SDLK_RCTRL:
   3.677  					modstate |= KMOD_RCTRL;
   3.678  					break;
   3.679 -				case SDLK_LALT:
   3.680 +				    case SDLK_LALT:
   3.681  					modstate |= KMOD_LALT;
   3.682  					break;
   3.683 -				case SDLK_RALT:
   3.684 +				    case SDLK_RALT:
   3.685  					modstate |= KMOD_RALT;
   3.686  					break;
   3.687 -				case SDLK_LMETA:
   3.688 +				    case SDLK_LMETA:
   3.689  					modstate |= KMOD_LMETA;
   3.690  					break;
   3.691 -				case SDLK_RMETA:
   3.692 +				    case SDLK_RMETA:
   3.693  					modstate |= KMOD_RMETA;
   3.694  					break;
   3.695 -				default:
   3.696 +				    default:
   3.697  					break;
   3.698 +				}
   3.699  			}
   3.700  		}
   3.701 -		if ( kstate[i] != state ) {
   3.702 -			kstate[i] = state;
   3.703 -		}
   3.704  	}
   3.705  
   3.706  	/* Hack - set toggle key state */
     4.1 --- a/src/video/x11/SDL_x11events_c.h	Fri Feb 03 07:43:42 2006 +0000
     4.2 +++ b/src/video/x11/SDL_x11events_c.h	Sat Feb 04 08:35:11 2006 +0000
     4.3 @@ -25,5 +25,5 @@
     4.4  /* Functions to be exported */
     4.5  extern void X11_InitOSKeymap(_THIS);
     4.6  extern void X11_PumpEvents(_THIS);
     4.7 -extern void X11_SetKeyboardState(Display *display, XIC ic, const char *key_vec);
     4.8 +extern void X11_SetKeyboardState(Display *display, const char *key_vec);
     4.9  
     5.1 --- a/src/video/x11/SDL_x11sym.h	Fri Feb 03 07:43:42 2006 +0000
     5.2 +++ b/src/video/x11/SDL_x11sym.h	Sat Feb 04 08:35:11 2006 +0000
     5.3 @@ -43,6 +43,7 @@
     5.4  SDL_X11_SYM(1,int,XDestroyWindow,(Display*,Window))
     5.5  SDL_X11_SYM(1,char*,XDisplayName,(_Xconst char*))
     5.6  SDL_X11_SYM(1,int,XEventsQueued,(Display*,int))
     5.7 +SDL_X11_SYM(1,Bool,XFilterEvent,(XEvent *event, Window w))
     5.8  SDL_X11_SYM(1,int,XFlush,(Display*))
     5.9  SDL_X11_SYM(1,int,XFree,(void*))
    5.10  SDL_X11_SYM(1,int,XFreeColormap,(Display*,Colormap))
     6.1 --- a/src/video/x11/SDL_x11video.c	Fri Feb 03 07:43:42 2006 +0000
     6.2 +++ b/src/video/x11/SDL_x11video.c	Sat Feb 04 08:35:11 2006 +0000
     6.3 @@ -953,7 +953,7 @@
     6.4  	}
     6.5  
     6.6  	/* Update the internal keyboard state */
     6.7 -	X11_SetKeyboardState(SDL_Display, SDL_IC, NULL);
     6.8 +	X11_SetKeyboardState(SDL_Display, NULL);
     6.9  
    6.10  	/* When the window is first mapped, ignore non-modifier keys */
    6.11  	{
     7.1 --- a/src/video/x11/SDL_x11video.h	Fri Feb 03 07:43:42 2006 +0000
     7.2 +++ b/src/video/x11/SDL_x11video.h	Sat Feb 04 08:35:11 2006 +0000
     7.3 @@ -151,8 +151,8 @@
     7.4  #define SDL_Window		(this->hidden->SDL_Window)
     7.5  #define WM_DELETE_WINDOW	(this->hidden->WM_DELETE_WINDOW)
     7.6  #define SDL_BlankCursor		(this->hidden->BlankCursor)
     7.7 -#define SDL_IM		(this->hidden->X11_IM)
     7.8 -#define SDL_IC		(this->hidden->X11_IC)
     7.9 +#define SDL_IM			(this->hidden->X11_IM)
    7.10 +#define SDL_IC			(this->hidden->X11_IC)
    7.11  #define SDL_windowid		(this->hidden->SDL_windowid)
    7.12  #define using_dga		(this->hidden->using_dga)
    7.13  #define use_mitshm		(this->hidden->use_mitshm)