Mercurial > sdl-ios-xcode
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 */