src/video/x11/SDL_x11events.c
changeset 1327 d12a63a8d95a
parent 1312 c9b51268668f
child 1328 27ddb06a0bca
     1.1 --- a/src/video/x11/SDL_x11events.c	Fri Feb 03 07:43:42 2006 +0000
     1.2 +++ b/src/video/x11/SDL_x11events.c	Sat Feb 04 08:35:11 2006 +0000
     1.3 @@ -57,8 +57,128 @@
     1.4  /* The translation tables from an X11 keysym to a SDL keysym */
     1.5  static SDLKey ODD_keymap[256];
     1.6  static SDLKey MISC_keymap[256];
     1.7 -SDL_keysym *X11_TranslateKey(Display *display, XIC ic, XKeyEvent *xkey, KeyCode kc,
     1.8 -			     SDL_keysym *keysym);
     1.9 +SDLKey X11_TranslateKeycode(Display *display, KeyCode kc);
    1.10 +
    1.11 +
    1.12 +#ifdef X_HAVE_UTF8_STRING
    1.13 +Uint32 Utf8ToUcs4(const Uint8 *utf8)
    1.14 +{
    1.15 +	Uint32 c;
    1.16 +	int i = 1;
    1.17 +	int noOctets = 0;
    1.18 +	int firstOctetMask = 0;
    1.19 +	unsigned char firstOctet = utf8[0];
    1.20 +	if (firstOctet < 0x80) {
    1.21 +		/*
    1.22 +		  Characters in the range:
    1.23 +		    00000000 to 01111111 (ASCII Range)
    1.24 +		  are stored in one octet:
    1.25 +		    0xxxxxxx (The same as its ASCII representation)
    1.26 +		  The least 6 significant bits of the first octet is the most 6 significant nonzero bits
    1.27 +		  of the UCS4 representation.
    1.28 +		*/
    1.29 +		noOctets = 1;
    1.30 +		firstOctetMask = 0x7F;  /* 0(1111111) - The most significant bit is ignored */
    1.31 +	} else if ((firstOctet & 0xE0) /* get the most 3 significant bits by AND'ing with 11100000 */
    1.32 +	              == 0xC0 ) {  /* see if those 3 bits are 110. If so, the char is in this range */
    1.33 +		/*
    1.34 +		  Characters in the range:
    1.35 +		    00000000 10000000 to 00000111 11111111
    1.36 +		  are stored in two octets:
    1.37 +		    110xxxxx 10xxxxxx
    1.38 +		  The least 5 significant bits of the first octet is the most 5 significant nonzero bits
    1.39 +		  of the UCS4 representation.
    1.40 +		*/
    1.41 +		noOctets = 2;
    1.42 +		firstOctetMask = 0x1F;  /* 000(11111) - The most 3 significant bits are ignored */
    1.43 +	} else if ((firstOctet & 0xF0) /* get the most 4 significant bits by AND'ing with 11110000 */
    1.44 +	              == 0xE0) {  /* see if those 4 bits are 1110. If so, the char is in this range */
    1.45 +		/*
    1.46 +		  Characters in the range:
    1.47 +		    00001000 00000000 to 11111111 11111111
    1.48 +		  are stored in three octets:
    1.49 +		    1110xxxx 10xxxxxx 10xxxxxx
    1.50 +		  The least 4 significant bits of the first octet is the most 4 significant nonzero bits
    1.51 +		  of the UCS4 representation.
    1.52 +		*/
    1.53 +		noOctets = 3;
    1.54 +		firstOctetMask = 0x0F; /* 0000(1111) - The most 4 significant bits are ignored */
    1.55 +	} else if ((firstOctet & 0xF8) /* get the most 5 significant bits by AND'ing with 11111000 */
    1.56 +	              == 0xF0) {  /* see if those 5 bits are 11110. If so, the char is in this range */
    1.57 +		/*
    1.58 +		  Characters in the range:
    1.59 +		    00000001 00000000 00000000 to 00011111 11111111 11111111
    1.60 +		  are stored in four octets:
    1.61 +		    11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
    1.62 +		  The least 3 significant bits of the first octet is the most 3 significant nonzero bits
    1.63 +		  of the UCS4 representation.
    1.64 +		*/
    1.65 +		noOctets = 4;
    1.66 +		firstOctetMask = 0x07; /* 11110(111) - The most 5 significant bits are ignored */
    1.67 +	} else if ((firstOctet & 0xFC) /* get the most 6 significant bits by AND'ing with 11111100 */
    1.68 +	              == 0xF8) { /* see if those 6 bits are 111110. If so, the char is in this range */
    1.69 +		/*
    1.70 +		  Characters in the range:
    1.71 +		    00000000 00100000 00000000 00000000 to
    1.72 +		    00000011 11111111 11111111 11111111
    1.73 +		  are stored in five octets:
    1.74 +		    111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
    1.75 +		  The least 2 significant bits of the first octet is the most 2 significant nonzero bits
    1.76 +		  of the UCS4 representation.
    1.77 +		*/
    1.78 +		noOctets = 5;
    1.79 +		firstOctetMask = 0x03; /* 111110(11) - The most 6 significant bits are ignored */
    1.80 +	} else if ((firstOctet & 0xFE) /* get the most 7 significant bits by AND'ing with 11111110 */
    1.81 +	              == 0xFC) { /* see if those 7 bits are 1111110. If so, the char is in this range */
    1.82 +		/*
    1.83 +		  Characters in the range:
    1.84 +		    00000100 00000000 00000000 00000000 to
    1.85 +		    01111111 11111111 11111111 11111111
    1.86 +		  are stored in six octets:
    1.87 +		    1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
    1.88 +		  The least significant bit of the first octet is the most significant nonzero bit
    1.89 +		  of the UCS4 representation.
    1.90 +		*/
    1.91 +		noOctets = 6;
    1.92 +		firstOctetMask = 0x01; /* 1111110(1) - The most 7 significant bits are ignored */
    1.93 +	} else
    1.94 +		return 0;  /* The given chunk is not a valid UTF-8 encoded Unicode character */
    1.95 +	
    1.96 +	/*
    1.97 +	  The least noOctets significant bits of the first octet is the most 2 significant nonzero bits
    1.98 +	  of the UCS4 representation.
    1.99 +	  The first 6 bits of the UCS4 representation is the least 8-noOctets-1 significant bits of
   1.100 +	  firstOctet if the character is not ASCII. If so, it's the least 7 significant bits of firstOctet.
   1.101 +	  This done by AND'ing firstOctet with its mask to trim the bits used for identifying the
   1.102 +	  number of continuing octets (if any) and leave only the free bits (the x's)
   1.103 +	  Sample:
   1.104 +	  1-octet:    0xxxxxxx  &  01111111 = 0xxxxxxx
   1.105 +	  2-octets:  110xxxxx  &  00011111 = 000xxxxx
   1.106 +	*/
   1.107 +	c = firstOctet & firstOctetMask;
   1.108 +	
   1.109 +	/* Now, start filling c.ucs4 with the bits from the continuing octets from utf8. */
   1.110 +	for (i = 1; i < noOctets; i++) {
   1.111 +		/* A valid continuing octet is of the form 10xxxxxx */
   1.112 +		if ((utf8[i] & 0xC0) /* get the most 2 significant bits by AND'ing with 11000000 */
   1.113 +		    != 0x80) /* see if those 2 bits are 10. If not, the is a malformed sequence. */
   1.114 +			/*The given chunk is a partial sequence at the end of a string that could
   1.115 +			   begin a valid character */
   1.116 +			return 0;
   1.117 +		
   1.118 +		/* Make room for the next 6-bits */
   1.119 +		c <<= 6;
   1.120 +		
   1.121 +		/*
   1.122 +		  Take only the least 6 significance bits of the current octet (utf8[i]) and fill the created room
   1.123 +		  of c.ucs4 with them.
   1.124 +		  This done by AND'ing utf8[i] with 00111111 and the OR'ing the result with c.ucs4.
   1.125 +		*/
   1.126 +		c |= utf8[i] & 0x3F;
   1.127 +	}
   1.128 +	return c;
   1.129 +}
   1.130 +#endif
   1.131  
   1.132  /* Check to see if this is a repeated key.
   1.133     (idea shamelessly lifted from GII -- thanks guys! :)
   1.134 @@ -212,6 +332,10 @@
   1.135  #endif
   1.136  		posted = SDL_PrivateAppActive(1, SDL_APPINPUTFOCUS);
   1.137  
   1.138 +		if ( SDL_IC != NULL ) {
   1.139 +			pXSetICFocus(SDL_IC);
   1.140 +		}
   1.141 +
   1.142  		/* Queue entry into fullscreen mode */
   1.143  		switch_waiting = 0x01 | SDL_FULLSCREEN;
   1.144  		switch_time = SDL_GetTicks() + 1500;
   1.145 @@ -225,6 +349,10 @@
   1.146  #endif
   1.147  		posted = SDL_PrivateAppActive(0, SDL_APPINPUTFOCUS);
   1.148  
   1.149 +		if ( SDL_IC != NULL ) {
   1.150 +			pXUnsetICFocus(SDL_IC);
   1.151 +		}
   1.152 +
   1.153  		/* Queue leaving fullscreen mode */
   1.154  		switch_waiting = 0x01;
   1.155  		switch_time = SDL_GetTicks() + 200;
   1.156 @@ -236,7 +364,7 @@
   1.157  #ifdef DEBUG_XEVENTS
   1.158  printf("KeymapNotify!\n");
   1.159  #endif
   1.160 -		X11_SetKeyboardState(SDL_Display, SDL_IC,  xevent.xkeymap.key_vector);
   1.161 +		X11_SetKeyboardState(SDL_Display,  xevent.xkeymap.key_vector);
   1.162  	    }
   1.163  	    break;
   1.164  
   1.165 @@ -282,32 +410,94 @@
   1.166  
   1.167  	    /* Key press? */
   1.168  	    case KeyPress: {
   1.169 +		static SDL_keysym saved_keysym;
   1.170  		SDL_keysym keysym;
   1.171 +		KeyCode keycode = xevent.xkey.keycode;
   1.172  
   1.173  #ifdef DEBUG_XEVENTS
   1.174  printf("KeyPress (X11 keycode = 0x%X)\n", xevent.xkey.keycode);
   1.175  #endif
   1.176 -		posted = SDL_PrivateKeyboard(SDL_PRESSED,
   1.177 -				X11_TranslateKey(SDL_Display, SDL_IC, &xevent.xkey,
   1.178 -						 xevent.xkey.keycode,
   1.179 -						 &keysym));
   1.180 +		/* Get the translated SDL virtual keysym */
   1.181 +		if ( keycode ) {
   1.182 +			keysym.scancode = keycode;
   1.183 +			keysym.sym = X11_TranslateKeycode(SDL_Display, keycode);
   1.184 +			keysym.mod = KMOD_NONE;
   1.185 +			keysym.unicode = 0;
   1.186 +		} else {
   1.187 +			keysym = saved_keysym;
   1.188 +		}
   1.189 +
   1.190 +		/* If we're not doing translation, we're done! */
   1.191 +		if ( !SDL_TranslateUNICODE ) {
   1.192 +			posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym);
   1.193 +			break;
   1.194 +		}
   1.195 +
   1.196 +		if ( pXFilterEvent(&xevent, None) ) {
   1.197 +			if ( xevent.xkey.keycode ) {
   1.198 +				posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym);
   1.199 +			} else {
   1.200 +				/* Save event to be associated with IM text
   1.201 +				   In 1.3 we'll have a text event instead.. */
   1.202 +				saved_keysym = keysym;
   1.203 +			}
   1.204 +			break;
   1.205 +		}
   1.206 +
   1.207 +		/* Look up the translated value for the key event */
   1.208 +#ifdef X_HAVE_UTF8_STRING
   1.209 +		if ( SDL_IC != NULL ) {
   1.210 +			static Status state;
   1.211 +			/* A UTF-8 character can be at most 6 bytes */
   1.212 +			char keybuf[6];
   1.213 +			if ( pXutf8LookupString(SDL_IC, &xevent.xkey,
   1.214 +			                        keybuf, sizeof(keybuf),
   1.215 +			                        NULL, &state) ) {
   1.216 +				keysym.unicode = Utf8ToUcs4((Uint8*)keybuf);
   1.217 +			}
   1.218 +		}
   1.219 +		else
   1.220 +#endif
   1.221 +		{
   1.222 +			static XComposeStatus state;
   1.223 +			char keybuf[32];
   1.224 +
   1.225 +			if ( pXLookupString(&xevent.xkey,
   1.226 +			                    keybuf, sizeof(keybuf),
   1.227 +			                    NULL, &state) ) {
   1.228 +				/*
   1.229 +				* FIXME: XLookupString() may yield more than one
   1.230 +				* character, so we need a mechanism to allow for
   1.231 +				* this (perhaps null keypress events with a
   1.232 +				* unicode value)
   1.233 +				*/
   1.234 +				keysym.unicode = (Uint8)keybuf[0];
   1.235 +			}
   1.236 +		}
   1.237 +		posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym);
   1.238  	    }
   1.239  	    break;
   1.240  
   1.241  	    /* Key release? */
   1.242  	    case KeyRelease: {
   1.243  		SDL_keysym keysym;
   1.244 +		KeyCode keycode = xevent.xkey.keycode;
   1.245  
   1.246  #ifdef DEBUG_XEVENTS
   1.247  printf("KeyRelease (X11 keycode = 0x%X)\n", xevent.xkey.keycode);
   1.248  #endif
   1.249  		/* Check to see if this is a repeated key */
   1.250 -		if ( ! X11_KeyRepeat(SDL_Display, &xevent) ) {
   1.251 -			posted = SDL_PrivateKeyboard(SDL_RELEASED, 
   1.252 -				X11_TranslateKey(SDL_Display, SDL_IC,  &xevent.xkey,
   1.253 -						 xevent.xkey.keycode,
   1.254 -						 &keysym));
   1.255 +		if ( X11_KeyRepeat(SDL_Display, &xevent) ) {
   1.256 +			break;
   1.257  		}
   1.258 +
   1.259 +		/* Get the translated SDL virtual keysym */
   1.260 +		keysym.scancode = keycode;
   1.261 +		keysym.sym = X11_TranslateKeycode(SDL_Display, keycode);
   1.262 +		keysym.mod = KMOD_NONE;
   1.263 +		keysym.unicode = 0;
   1.264 +
   1.265 +		posted = SDL_PrivateKeyboard(SDL_RELEASED, &keysym);
   1.266  	    }
   1.267  	    break;
   1.268  
   1.269 @@ -507,6 +697,26 @@
   1.270  	for ( i=0; i<SDL_TABLESIZE(ODD_keymap); ++i )
   1.271  		ODD_keymap[i] = SDLK_UNKNOWN;
   1.272  
   1.273 + 	/* Some of these might be mappable to an existing SDLK_ code */
   1.274 + 	ODD_keymap[XK_dead_grave&0xFF] = SDLK_COMPOSE;
   1.275 + 	ODD_keymap[XK_dead_acute&0xFF] = SDLK_COMPOSE;
   1.276 + 	ODD_keymap[XK_dead_tilde&0xFF] = SDLK_COMPOSE;
   1.277 + 	ODD_keymap[XK_dead_macron&0xFF] = SDLK_COMPOSE;
   1.278 + 	ODD_keymap[XK_dead_breve&0xFF] = SDLK_COMPOSE;
   1.279 + 	ODD_keymap[XK_dead_abovedot&0xFF] = SDLK_COMPOSE;
   1.280 + 	ODD_keymap[XK_dead_diaeresis&0xFF] = SDLK_COMPOSE;
   1.281 + 	ODD_keymap[XK_dead_abovering&0xFF] = SDLK_COMPOSE;
   1.282 + 	ODD_keymap[XK_dead_doubleacute&0xFF] = SDLK_COMPOSE;
   1.283 + 	ODD_keymap[XK_dead_caron&0xFF] = SDLK_COMPOSE;
   1.284 + 	ODD_keymap[XK_dead_cedilla&0xFF] = SDLK_COMPOSE;
   1.285 + 	ODD_keymap[XK_dead_ogonek&0xFF] = SDLK_COMPOSE;
   1.286 + 	ODD_keymap[XK_dead_iota&0xFF] = SDLK_COMPOSE;
   1.287 + 	ODD_keymap[XK_dead_voiced_sound&0xFF] = SDLK_COMPOSE;
   1.288 + 	ODD_keymap[XK_dead_semivoiced_sound&0xFF] = SDLK_COMPOSE;
   1.289 + 	ODD_keymap[XK_dead_belowdot&0xFF] = SDLK_COMPOSE;
   1.290 + 	ODD_keymap[XK_dead_hook&0xFF] = SDLK_COMPOSE;
   1.291 + 	ODD_keymap[XK_dead_horn&0xFF] = SDLK_COMPOSE;
   1.292 +
   1.293  #ifdef XK_dead_circumflex
   1.294  	/* These X keysyms have 0xFE as the high byte */
   1.295  	ODD_keymap[XK_dead_circumflex&0xFF] = SDLK_CARET;
   1.296 @@ -607,253 +817,83 @@
   1.297  	MISC_keymap[XK_Hyper_R&0xFF] = SDLK_MENU;   /* Windows "Menu" key */
   1.298  }
   1.299  
   1.300 -#ifdef X_HAVE_UTF8_STRING
   1.301 -Uint32 Utf8ToUcs4(const unsigned char *utf8)
   1.302 -{
   1.303 -	Uint32 c;
   1.304 -	int i = 1;
   1.305 -	int noOctets = 0;
   1.306 -	int firstOctetMask = 0;
   1.307 -	unsigned char firstOctet = utf8[0];
   1.308 -	if (firstOctet < 0x80) {
   1.309 -		/*
   1.310 -		  Characters in the range:
   1.311 -		    00000000 to 01111111 (ASCII Range)
   1.312 -		  are stored in one octet:
   1.313 -		    0xxxxxxx (The same as its ASCII representation)
   1.314 -		  The least 6 significant bits of the first octet is the most 6 significant nonzero bits
   1.315 -		  of the UCS4 representation.
   1.316 -		*/
   1.317 -		noOctets = 1;
   1.318 -		firstOctetMask = 0x7F;  /* 0(1111111) - The most significant bit is ignored */
   1.319 -	} else if ((firstOctet & 0xE0) /* get the most 3 significant bits by AND'ing with 11100000 */
   1.320 -	              == 0xC0 ) {  /* see if those 3 bits are 110. If so, the char is in this range */
   1.321 -		/*
   1.322 -		  Characters in the range:
   1.323 -		    00000000 10000000 to 00000111 11111111
   1.324 -		  are stored in two octets:
   1.325 -		    110xxxxx 10xxxxxx
   1.326 -		  The least 5 significant bits of the first octet is the most 5 significant nonzero bits
   1.327 -		  of the UCS4 representation.
   1.328 -		*/
   1.329 -		noOctets = 2;
   1.330 -		firstOctetMask = 0x1F;  /* 000(11111) - The most 3 significant bits are ignored */
   1.331 -	} else if ((firstOctet & 0xF0) /* get the most 4 significant bits by AND'ing with 11110000 */
   1.332 -	              == 0xE0) {  /* see if those 4 bits are 1110. If so, the char is in this range */
   1.333 -		/*
   1.334 -		  Characters in the range:
   1.335 -		    00001000 00000000 to 11111111 11111111
   1.336 -		  are stored in three octets:
   1.337 -		    1110xxxx 10xxxxxx 10xxxxxx
   1.338 -		  The least 4 significant bits of the first octet is the most 4 significant nonzero bits
   1.339 -		  of the UCS4 representation.
   1.340 -		*/
   1.341 -		noOctets = 3;
   1.342 -		firstOctetMask = 0x0F; /* 0000(1111) - The most 4 significant bits are ignored */
   1.343 -	} else if ((firstOctet & 0xF8) /* get the most 5 significant bits by AND'ing with 11111000 */
   1.344 -	              == 0xF0) {  /* see if those 5 bits are 11110. If so, the char is in this range */
   1.345 -		/*
   1.346 -		  Characters in the range:
   1.347 -		    00000001 00000000 00000000 to 00011111 11111111 11111111
   1.348 -		  are stored in four octets:
   1.349 -		    11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
   1.350 -		  The least 3 significant bits of the first octet is the most 3 significant nonzero bits
   1.351 -		  of the UCS4 representation.
   1.352 -		*/
   1.353 -		noOctets = 4;
   1.354 -		firstOctetMask = 0x07; /* 11110(111) - The most 5 significant bits are ignored */
   1.355 -	} else if ((firstOctet & 0xFC) /* get the most 6 significant bits by AND'ing with 11111100 */
   1.356 -	              == 0xF8) { /* see if those 6 bits are 111110. If so, the char is in this range */
   1.357 -		/*
   1.358 -		  Characters in the range:
   1.359 -		    00000000 00100000 00000000 00000000 to
   1.360 -		    00000011 11111111 11111111 11111111
   1.361 -		  are stored in five octets:
   1.362 -		    111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
   1.363 -		  The least 2 significant bits of the first octet is the most 2 significant nonzero bits
   1.364 -		  of the UCS4 representation.
   1.365 -		*/
   1.366 -		noOctets = 5;
   1.367 -		firstOctetMask = 0x03; /* 111110(11) - The most 6 significant bits are ignored */
   1.368 -	} else if ((firstOctet & 0xFE) /* get the most 7 significant bits by AND'ing with 11111110 */
   1.369 -	              == 0xFC) { /* see if those 7 bits are 1111110. If so, the char is in this range */
   1.370 -		/*
   1.371 -		  Characters in the range:
   1.372 -		    00000100 00000000 00000000 00000000 to
   1.373 -		    01111111 11111111 11111111 11111111
   1.374 -		  are stored in six octets:
   1.375 -		    1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
   1.376 -		  The least significant bit of the first octet is the most significant nonzero bit
   1.377 -		  of the UCS4 representation.
   1.378 -		*/
   1.379 -		noOctets = 6;
   1.380 -		firstOctetMask = 0x01; /* 1111110(1) - The most 7 significant bits are ignored */
   1.381 -	} else
   1.382 -		return 0;  /* The given chunk is not a valid UTF-8 encoded Unicode character */
   1.383 -	
   1.384 -	/*
   1.385 -	  The least noOctets significant bits of the first octet is the most 2 significant nonzero bits
   1.386 -	  of the UCS4 representation.
   1.387 -	  The first 6 bits of the UCS4 representation is the least 8-noOctets-1 significant bits of
   1.388 -	  firstOctet if the character is not ASCII. If so, it's the least 7 significant bits of firstOctet.
   1.389 -	  This done by AND'ing firstOctet with its mask to trim the bits used for identifying the
   1.390 -	  number of continuing octets (if any) and leave only the free bits (the x's)
   1.391 -	  Sample:
   1.392 -	  1-octet:    0xxxxxxx  &  01111111 = 0xxxxxxx
   1.393 -	  2-octets:  110xxxxx  &  00011111 = 000xxxxx
   1.394 -	*/
   1.395 -	c = firstOctet & firstOctetMask;
   1.396 -	
   1.397 -	/* Now, start filling c.ucs4 with the bits from the continuing octets from utf8. */
   1.398 -	for (i = 1; i < noOctets; i++) {
   1.399 -		/* A valid continuing octet is of the form 10xxxxxx */
   1.400 -		if ((utf8[i] & 0xC0) /* get the most 2 significant bits by AND'ing with 11000000 */
   1.401 -		    != 0x80) /* see if those 2 bits are 10. If not, the is a malformed sequence. */
   1.402 -			/*The given chunk is a partial sequence at the end of a string that could
   1.403 -			   begin a valid character */
   1.404 -			return 0;
   1.405 -		
   1.406 -		/* Make room for the next 6-bits */
   1.407 -		c <<= 6;
   1.408 -		
   1.409 -		/*
   1.410 -		  Take only the least 6 significance bits of the current octet (utf8[i]) and fill the created room
   1.411 -		  of c.ucs4 with them.
   1.412 -		  This done by AND'ing utf8[i] with 00111111 and the OR'ing the result with c.ucs4.
   1.413 -		*/
   1.414 -		c |= utf8[i] & 0x3F;
   1.415 -	}
   1.416 -	return c;
   1.417 -}
   1.418 -#endif
   1.419 -
   1.420 -
   1.421 -SDL_keysym *X11_TranslateKey(Display *display, XIC ic, XKeyEvent *xkey, KeyCode kc,
   1.422 -			     SDL_keysym *keysym)
   1.423 +/* Get the translated SDL virtual keysym */
   1.424 +SDLKey X11_TranslateKeycode(Display *display, KeyCode kc)
   1.425  {
   1.426  	KeySym xsym;
   1.427 +	SDLKey key;
   1.428  
   1.429 -	/* Get the raw keyboard scancode */
   1.430 -	keysym->scancode = kc;
   1.431  	xsym = pXKeycodeToKeysym(display, kc, 0);
   1.432  #ifdef DEBUG_KEYS
   1.433 -	fprintf(stderr, "Translating key 0x%.4x (%d)\n", xsym, kc);
   1.434 +	fprintf(stderr, "Translating key code %d -> 0x%.4x\n", kc, xsym);
   1.435  #endif
   1.436 -	/* Get the translated SDL virtual keysym */
   1.437 -	keysym->sym = SDLK_UNKNOWN;
   1.438 +	key = SDLK_UNKNOWN;
   1.439  	if ( xsym ) {
   1.440  		switch (xsym>>8) {
   1.441 -			case 0x1005FF:
   1.442 +		    case 0x1005FF:
   1.443  #ifdef SunXK_F36
   1.444 -				if ( xsym == SunXK_F36 )
   1.445 -					keysym->sym = SDLK_F11;
   1.446 +			if ( xsym == SunXK_F36 )
   1.447 +				key = SDLK_F11;
   1.448  #endif
   1.449  #ifdef SunXK_F37
   1.450 -				if ( xsym == SunXK_F37 )
   1.451 -					keysym->sym = SDLK_F12;
   1.452 +			if ( xsym == SunXK_F37 )
   1.453 +				key = SDLK_F12;
   1.454  #endif
   1.455 -				break;
   1.456 -			case 0x00:	/* Latin 1 */
   1.457 -			case 0x01:	/* Latin 2 */
   1.458 -			case 0x02:	/* Latin 3 */
   1.459 -			case 0x03:	/* Latin 4 */
   1.460 -			case 0x04:	/* Katakana */
   1.461 -			case 0x05:	/* Arabic */
   1.462 -			case 0x06:	/* Cyrillic */
   1.463 -			case 0x07:	/* Greek */
   1.464 -			case 0x08:	/* Technical */
   1.465 -			case 0x0A:	/* Publishing */
   1.466 -			case 0x0C:	/* Hebrew */
   1.467 -			case 0x0D:	/* Thai */
   1.468 -				keysym->sym = (SDLKey)(xsym&0xFF);
   1.469 -				/* Map capital letter syms to lowercase */
   1.470 -				if ((keysym->sym >= 'A')&&(keysym->sym <= 'Z'))
   1.471 -					keysym->sym += ('a'-'A');
   1.472 -				break;
   1.473 -			case 0xFE:
   1.474 -				keysym->sym = ODD_keymap[xsym&0xFF];
   1.475 -				break;
   1.476 -			case 0xFF:
   1.477 -				keysym->sym = MISC_keymap[xsym&0xFF];
   1.478 -				break;
   1.479 -			default:
   1.480 -				fprintf(stderr,
   1.481 -					"X11: Unknown xsym, sym = 0x%04x\n",
   1.482 +			break;
   1.483 +		    case 0x00:	/* Latin 1 */
   1.484 +			key = (SDLKey)(xsym & 0xFF);
   1.485 +			break;
   1.486 +		    case 0x01:	/* Latin 2 */
   1.487 +		    case 0x02:	/* Latin 3 */
   1.488 +		    case 0x03:	/* Latin 4 */
   1.489 +		    case 0x04:	/* Katakana */
   1.490 +		    case 0x05:	/* Arabic */
   1.491 +		    case 0x06:	/* Cyrillic */
   1.492 +		    case 0x07:	/* Greek */
   1.493 +		    case 0x08:	/* Technical */
   1.494 +		    case 0x0A:	/* Publishing */
   1.495 +		    case 0x0C:	/* Hebrew */
   1.496 +		    case 0x0D:	/* Thai */
   1.497 +			/* These are wrong, but it's better than nothing */
   1.498 +			key = (SDLKey)(xsym & 0xFF);
   1.499 +			break;
   1.500 +		    case 0xFE:
   1.501 +			key = ODD_keymap[xsym&0xFF];
   1.502 +			break;
   1.503 +		    case 0xFF:
   1.504 +			key = MISC_keymap[xsym&0xFF];
   1.505 +			break;
   1.506 +		    default:
   1.507 +			/*
   1.508 +			fprintf(stderr, "X11: Unhandled xsym, sym = 0x%04x\n",
   1.509  					(unsigned int)xsym);
   1.510 -				break;
   1.511 +			*/
   1.512 +			break;
   1.513  		}
   1.514  	} else {
   1.515  		/* X11 doesn't know how to translate the key! */
   1.516  		switch (kc) {
   1.517 -			/* Caution:
   1.518 -			   These keycodes are from the Microsoft Keyboard
   1.519 +		    /* Caution:
   1.520 +		       These keycodes are from the Microsoft Keyboard
   1.521 +		     */
   1.522 +		    case 115:
   1.523 +			key = SDLK_LSUPER;
   1.524 +			break;
   1.525 +		    case 116:
   1.526 +			key = SDLK_RSUPER;
   1.527 +			break;
   1.528 +		    case 117:
   1.529 +			key = SDLK_MENU;
   1.530 +			break;
   1.531 +		    default:
   1.532 +			/*
   1.533 +			 * no point in an error message; happens for
   1.534 +			 * several keys when we get a keymap notify
   1.535  			 */
   1.536 -			case 115:
   1.537 -				keysym->sym = SDLK_LSUPER;
   1.538 -				break;
   1.539 -			case 116:
   1.540 -				keysym->sym = SDLK_RSUPER;
   1.541 -				break;
   1.542 -			case 117:
   1.543 -				keysym->sym = SDLK_MENU;
   1.544 -				break;
   1.545 -			default:
   1.546 -				/*
   1.547 -				 * no point in an error message; happens for
   1.548 -				 * several keys when we get a keymap notify
   1.549 -				 */
   1.550 -				break;
   1.551 +			break;
   1.552  		}
   1.553  	}
   1.554 -	keysym->mod = KMOD_NONE;
   1.555 -
   1.556 -	/* If UNICODE is on, get the UNICODE value for the key */
   1.557 -	keysym->unicode = 0;
   1.558 -	if ( SDL_TranslateUNICODE && xkey ) {
   1.559 -		static XComposeStatus state;
   1.560 -
   1.561 -
   1.562 -#define BROKEN_XFREE86_INTERNATIONAL_KBD
   1.563 -/* This appears to be a magical flag that is used with AltGr on
   1.564 -   international keyboards to signal alternate key translations.
   1.565 -   The flag doesn't show up when in fullscreen mode (?)
   1.566 -   FIXME:  Check to see if this code is safe for other servers.
   1.567 -*/
   1.568 -#ifdef BROKEN_XFREE86_INTERNATIONAL_KBD
   1.569 -		/* Work around what appears to be a bug in XFree86 */
   1.570 -		if ( SDL_GetModState() & KMOD_MODE ) {
   1.571 -			xkey->state |= (1<<13);
   1.572 -		}
   1.573 -#endif
   1.574 -		/* Look up the translated value for the key event */
   1.575 -
   1.576 -		/* if there is no connection with the IM server, use the regular method */
   1.577 -		if (ic == NULL || xkey->type != KeyPress) {
   1.578 -			unsigned char keybuf[32];
   1.579 -
   1.580 -			if ( pXLookupString(xkey, (char *)keybuf, sizeof(keybuf),
   1.581 -								NULL, &state) ) {
   1.582 -				/*
   1.583 -				* FIXME,: XLookupString() may yield more than one
   1.584 -				* character, so we need a mechanism to allow for
   1.585 -				* this (perhaps generate null keypress events with
   1.586 -				* a unicode value)
   1.587 -				*/
   1.588 -				keysym->unicode = keybuf[0];
   1.589 -			}
   1.590 -		} else {  /* else, use the IM protocol */
   1.591 -			#ifdef X_HAVE_UTF8_STRING
   1.592 -			/* A UTF-8 character can be at most 6 bytes */
   1.593 -			unsigned char keybuf[6];
   1.594 -			pXSetICFocus(ic);
   1.595 -			if ( pXutf8LookupString(ic, (XKeyPressedEvent *)xkey, (char *)keybuf, sizeof(keybuf),
   1.596 -			                                    NULL, (Status *)&state) )
   1.597 -				keysym->unicode = Utf8ToUcs4(keybuf);
   1.598 -			pXUnsetICFocus(ic);
   1.599 -			#endif
   1.600 -		}
   1.601 -	}
   1.602 -	return(keysym);
   1.603 +	return key;
   1.604  }
   1.605  
   1.606  /* X11 modifier masks for various keys */
   1.607 @@ -969,12 +1009,10 @@
   1.608   * synthetic keypress/release events.
   1.609   * key_vec is a bit vector of keycodes (256 bits)
   1.610   */
   1.611 -void X11_SetKeyboardState(Display *display, XIC ic, const char *key_vec)
   1.612 +void X11_SetKeyboardState(Display *display, const char *key_vec)
   1.613  {
   1.614  	char keys_return[32];
   1.615  	int i;
   1.616 -	KeyCode xcode[SDLK_LAST];
   1.617 -	Uint8 new_kstate[SDLK_LAST];
   1.618  	Uint8 *kstate = SDL_GetKeyState(NULL);
   1.619  	SDLMod modstate;
   1.620  	Window junk_window;
   1.621 @@ -1004,62 +1042,55 @@
   1.622  	}
   1.623  
   1.624  	/* Zero the new keyboard state and generate it */
   1.625 -	memset(new_kstate, SDL_RELEASED, sizeof(new_kstate));
   1.626 +	memset(kstate, 0, SDLK_LAST);
   1.627  	/*
   1.628  	 * An obvious optimisation is to check entire longwords at a time in
   1.629  	 * both loops, but we can't be sure the arrays are aligned so it's not
   1.630  	 * worth the extra complexity
   1.631  	 */
   1.632 -	for(i = 0; i < 32; i++) {
   1.633 +	for ( i = 0; i < 32; i++ ) {
   1.634  		int j;
   1.635 -		if(!key_vec[i])
   1.636 +		if ( !key_vec[i] )
   1.637  			continue;
   1.638 -		for(j = 0; j < 8; j++) {
   1.639 -			if(key_vec[i] & (1 << j)) {
   1.640 -				SDL_keysym sk;
   1.641 -				KeyCode kc = i << 3 | j;
   1.642 -				X11_TranslateKey(display, ic, NULL, kc, &sk);
   1.643 -				new_kstate[sk.sym] = SDL_PRESSED;
   1.644 -				xcode[sk.sym] = kc;
   1.645 -			}
   1.646 -		}
   1.647 -	}
   1.648 -	for(i = SDLK_FIRST+1; i < SDLK_LAST; i++) {
   1.649 -		int state = new_kstate[i];
   1.650 -
   1.651 -		if ( state == SDL_PRESSED ) {
   1.652 -			switch (i) {
   1.653 -				case SDLK_LSHIFT:
   1.654 +		for ( j = 0; j < 8; j++ ) {
   1.655 +			if ( key_vec[i] & (1 << j) ) {
   1.656 +				SDLKey key;
   1.657 +				KeyCode kc = (i << 3 | j);
   1.658 +				key = X11_TranslateKeycode(display, kc);
   1.659 +				if ( key == SDLK_UNKNOWN ) {
   1.660 +					continue;
   1.661 +				}
   1.662 +				kstate[key] = SDL_PRESSED;
   1.663 +				switch (key) {
   1.664 +				    case SDLK_LSHIFT:
   1.665  					modstate |= KMOD_LSHIFT;
   1.666  					break;
   1.667 -				case SDLK_RSHIFT:
   1.668 +				    case SDLK_RSHIFT:
   1.669  					modstate |= KMOD_RSHIFT;
   1.670  					break;
   1.671 -				case SDLK_LCTRL:
   1.672 +				    case SDLK_LCTRL:
   1.673  					modstate |= KMOD_LCTRL;
   1.674  					break;
   1.675 -				case SDLK_RCTRL:
   1.676 +				    case SDLK_RCTRL:
   1.677  					modstate |= KMOD_RCTRL;
   1.678  					break;
   1.679 -				case SDLK_LALT:
   1.680 +				    case SDLK_LALT:
   1.681  					modstate |= KMOD_LALT;
   1.682  					break;
   1.683 -				case SDLK_RALT:
   1.684 +				    case SDLK_RALT:
   1.685  					modstate |= KMOD_RALT;
   1.686  					break;
   1.687 -				case SDLK_LMETA:
   1.688 +				    case SDLK_LMETA:
   1.689  					modstate |= KMOD_LMETA;
   1.690  					break;
   1.691 -				case SDLK_RMETA:
   1.692 +				    case SDLK_RMETA:
   1.693  					modstate |= KMOD_RMETA;
   1.694  					break;
   1.695 -				default:
   1.696 +				    default:
   1.697  					break;
   1.698 +				}
   1.699  			}
   1.700  		}
   1.701 -		if ( kstate[i] != state ) {
   1.702 -			kstate[i] = state;
   1.703 -		}
   1.704  	}
   1.705  
   1.706  	/* Hack - set toggle key state */