comparison src/video/x11/SDL_x11events.c @ 1178:9867f3d86e44

Real Unicode support for X11. Based on updated version of this patch: http://lists.arabeyes.org/archives/developer/2004/June/msg00160.html --ryan.
author Ryan C. Gordon <icculus@icculus.org>
date Mon, 21 Nov 2005 00:16:34 +0000
parents 045f186426e1
children abb4267e7028
comparison
equal deleted inserted replaced
1177:e967ab22e6fd 1178:9867f3d86e44
60 /*#define DEBUG_XEVENTS*/ 60 /*#define DEBUG_XEVENTS*/
61 61
62 /* The translation tables from an X11 keysym to a SDL keysym */ 62 /* The translation tables from an X11 keysym to a SDL keysym */
63 static SDLKey ODD_keymap[256]; 63 static SDLKey ODD_keymap[256];
64 static SDLKey MISC_keymap[256]; 64 static SDLKey MISC_keymap[256];
65 SDL_keysym *X11_TranslateKey(Display *display, XKeyEvent *xkey, KeyCode kc, 65 SDL_keysym *X11_TranslateKey(Display *display, XIC ic, XKeyEvent *xkey, KeyCode kc,
66 SDL_keysym *keysym); 66 SDL_keysym *keysym);
67 67
68 /* Check to see if this is a repeated key. 68 /* Check to see if this is a repeated key.
69 (idea shamelessly lifted from GII -- thanks guys! :) 69 (idea shamelessly lifted from GII -- thanks guys! :)
70 */ 70 */
239 /* Generated upon EnterWindow and FocusIn */ 239 /* Generated upon EnterWindow and FocusIn */
240 case KeymapNotify: { 240 case KeymapNotify: {
241 #ifdef DEBUG_XEVENTS 241 #ifdef DEBUG_XEVENTS
242 printf("KeymapNotify!\n"); 242 printf("KeymapNotify!\n");
243 #endif 243 #endif
244 X11_SetKeyboardState(SDL_Display, xevent.xkeymap.key_vector); 244 X11_SetKeyboardState(SDL_Display, SDL_IC, xevent.xkeymap.key_vector);
245 } 245 }
246 break; 246 break;
247 247
248 /* Mouse motion? */ 248 /* Mouse motion? */
249 case MotionNotify: { 249 case MotionNotify: {
291 291
292 #ifdef DEBUG_XEVENTS 292 #ifdef DEBUG_XEVENTS
293 printf("KeyPress (X11 keycode = 0x%X)\n", xevent.xkey.keycode); 293 printf("KeyPress (X11 keycode = 0x%X)\n", xevent.xkey.keycode);
294 #endif 294 #endif
295 posted = SDL_PrivateKeyboard(SDL_PRESSED, 295 posted = SDL_PrivateKeyboard(SDL_PRESSED,
296 X11_TranslateKey(SDL_Display, &xevent.xkey, 296 X11_TranslateKey(SDL_Display, SDL_IC, &xevent.xkey,
297 xevent.xkey.keycode, 297 xevent.xkey.keycode,
298 &keysym)); 298 &keysym));
299 } 299 }
300 break; 300 break;
301 301
307 printf("KeyRelease (X11 keycode = 0x%X)\n", xevent.xkey.keycode); 307 printf("KeyRelease (X11 keycode = 0x%X)\n", xevent.xkey.keycode);
308 #endif 308 #endif
309 /* Check to see if this is a repeated key */ 309 /* Check to see if this is a repeated key */
310 if ( ! X11_KeyRepeat(SDL_Display, &xevent) ) { 310 if ( ! X11_KeyRepeat(SDL_Display, &xevent) ) {
311 posted = SDL_PrivateKeyboard(SDL_RELEASED, 311 posted = SDL_PrivateKeyboard(SDL_RELEASED,
312 X11_TranslateKey(SDL_Display, &xevent.xkey, 312 X11_TranslateKey(SDL_Display, SDL_IC, &xevent.xkey,
313 xevent.xkey.keycode, 313 xevent.xkey.keycode,
314 &keysym)); 314 &keysym));
315 } 315 }
316 } 316 }
317 break; 317 break;
610 MISC_keymap[XK_Break&0xFF] = SDLK_BREAK; 610 MISC_keymap[XK_Break&0xFF] = SDLK_BREAK;
611 MISC_keymap[XK_Menu&0xFF] = SDLK_MENU; 611 MISC_keymap[XK_Menu&0xFF] = SDLK_MENU;
612 MISC_keymap[XK_Hyper_R&0xFF] = SDLK_MENU; /* Windows "Menu" key */ 612 MISC_keymap[XK_Hyper_R&0xFF] = SDLK_MENU; /* Windows "Menu" key */
613 } 613 }
614 614
615 SDL_keysym *X11_TranslateKey(Display *display, XKeyEvent *xkey, KeyCode kc, 615 #ifdef X_HAVE_UTF8_STRING
616 Uint32 Utf8ToUcs4(const char * utf8)
617 {
618 Uint32 c;
619 int i = 1;
620 int noOctets = 0;
621 int firstOctetMask = 0;
622 unsigned char firstOctet = utf8[0];
623 if (firstOctet < 0x80) {
624 /*
625 Characters in the range:
626 00000000 to 01111111 (ASCII Range)
627 are stored in one octet:
628 0xxxxxxx (The same as its ASCII representation)
629 The least 6 significant bits of the first octet is the most 6 significant nonzero bits
630 of the UCS4 representation.
631 */
632 noOctets = 1;
633 firstOctetMask = 0x7F; /* 0(1111111) - The most significant bit is ignored */
634 } else if ((firstOctet & 0xE0) /* get the most 3 significant bits by AND'ing with 11100000 */
635 == 0xC0 ) { /* see if those 3 bits are 110. If so, the char is in this range */
636 /*
637 Characters in the range:
638 00000000 10000000 to 00000111 11111111
639 are stored in two octets:
640 110xxxxx 10xxxxxx
641 The least 5 significant bits of the first octet is the most 5 significant nonzero bits
642 of the UCS4 representation.
643 */
644 noOctets = 2;
645 firstOctetMask = 0x1F; /* 000(11111) - The most 3 significant bits are ignored */
646 } else if ((firstOctet & 0xF0) /* get the most 4 significant bits by AND'ing with 11110000 */
647 == 0xE0) { /* see if those 4 bits are 1110. If so, the char is in this range */
648 /*
649 Characters in the range:
650 00001000 00000000 to 11111111 11111111
651 are stored in three octets:
652 1110xxxx 10xxxxxx 10xxxxxx
653 The least 4 significant bits of the first octet is the most 4 significant nonzero bits
654 of the UCS4 representation.
655 */
656 noOctets = 3;
657 firstOctetMask = 0x0F; /* 0000(1111) - The most 4 significant bits are ignored */
658 } else if ((firstOctet & 0xF8) /* get the most 5 significant bits by AND'ing with 11111000 */
659 == 0xF0) { /* see if those 5 bits are 11110. If so, the char is in this range */
660 /*
661 Characters in the range:
662 00000001 00000000 00000000 to 00011111 11111111 11111111
663 are stored in four octets:
664 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
665 The least 3 significant bits of the first octet is the most 3 significant nonzero bits
666 of the UCS4 representation.
667 */
668 noOctets = 4;
669 firstOctetMask = 0x07; /* 11110(111) - The most 5 significant bits are ignored */
670 } else if ((firstOctet & 0xFC) /* get the most 6 significant bits by AND'ing with 11111100 */
671 == 0xF8) { /* see if those 6 bits are 111110. If so, the char is in this range */
672 /*
673 Characters in the range:
674 00000000 00100000 00000000 00000000 to
675 00000011 11111111 11111111 11111111
676 are stored in five octets:
677 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
678 The least 2 significant bits of the first octet is the most 2 significant nonzero bits
679 of the UCS4 representation.
680 */
681 noOctets = 5;
682 firstOctetMask = 0x03; /* 111110(11) - The most 6 significant bits are ignored */
683 } else if ((firstOctet & 0xFE) /* get the most 7 significant bits by AND'ing with 11111110 */
684 == 0xFC) { /* see if those 7 bits are 1111110. If so, the char is in this range */
685 /*
686 Characters in the range:
687 00000100 00000000 00000000 00000000 to
688 01111111 11111111 11111111 11111111
689 are stored in six octets:
690 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
691 The least significant bit of the first octet is the most significant nonzero bit
692 of the UCS4 representation.
693 */
694 noOctets = 6;
695 firstOctetMask = 0x01; /* 1111110(1) - The most 7 significant bits are ignored */
696 } else
697 return 0; /* The given chunk is not a valid UTF-8 encoded Unicode character */
698
699 /*
700 The least noOctets significant bits of the first octet is the most 2 significant nonzero bits
701 of the UCS4 representation.
702 The first 6 bits of the UCS4 representation is the least 8-noOctets-1 significant bits of
703 firstOctet if the character is not ASCII. If so, it's the least 7 significant bits of firstOctet.
704 This done by AND'ing firstOctet with its mask to trim the bits used for identifying the
705 number of continuing octets (if any) and leave only the free bits (the x's)
706 Sample:
707 1-octet: 0xxxxxxx & 01111111 = 0xxxxxxx
708 2-octets: 110xxxxx & 00011111 = 000xxxxx
709 */
710 c = firstOctet & firstOctetMask;
711
712 /* Now, start filling c.ucs4 with the bits from the continuing octets from utf8. */
713 for (i = 1; i < noOctets; i++) {
714 /* A valid continuing octet is of the form 10xxxxxx */
715 if ((utf8[i] & 0xC0) /* get the most 2 significant bits by AND'ing with 11000000 */
716 != 0x80) /* see if those 2 bits are 10. If not, the is a malformed sequence. */
717 /*The given chunk is a partial sequence at the end of a string that could
718 begin a valid character */
719 return 0;
720
721 /* Make room for the next 6-bits */
722 c <<= 6;
723
724 /*
725 Take only the least 6 significance bits of the current octet (utf8[i]) and fill the created room
726 of c.ucs4 with them.
727 This done by AND'ing utf8[i] with 00111111 and the OR'ing the result with c.ucs4.
728 */
729 c |= utf8[i] & 0x3F;
730 }
731 return c;
732 }
733 #endif
734
735
736 SDL_keysym *X11_TranslateKey(Display *display, XIC ic, XKeyEvent *xkey, KeyCode kc,
616 SDL_keysym *keysym) 737 SDL_keysym *keysym)
617 { 738 {
618 KeySym xsym; 739 KeySym xsym;
619 740
620 /* Get the raw keyboard scancode */ 741 /* Get the raw keyboard scancode */
693 814
694 /* If UNICODE is on, get the UNICODE value for the key */ 815 /* If UNICODE is on, get the UNICODE value for the key */
695 keysym->unicode = 0; 816 keysym->unicode = 0;
696 if ( SDL_TranslateUNICODE && xkey ) { 817 if ( SDL_TranslateUNICODE && xkey ) {
697 static XComposeStatus state; 818 static XComposeStatus state;
698 /* Until we handle the IM protocol, use XLookupString() */ 819
699 unsigned char keybuf[32];
700 820
701 #define BROKEN_XFREE86_INTERNATIONAL_KBD 821 #define BROKEN_XFREE86_INTERNATIONAL_KBD
702 /* This appears to be a magical flag that is used with AltGr on 822 /* This appears to be a magical flag that is used with AltGr on
703 international keyboards to signal alternate key translations. 823 international keyboards to signal alternate key translations.
704 The flag doesn't show up when in fullscreen mode (?) 824 The flag doesn't show up when in fullscreen mode (?)
709 if ( SDL_GetModState() & KMOD_MODE ) { 829 if ( SDL_GetModState() & KMOD_MODE ) {
710 xkey->state |= (1<<13); 830 xkey->state |= (1<<13);
711 } 831 }
712 #endif 832 #endif
713 /* Look up the translated value for the key event */ 833 /* Look up the translated value for the key event */
714 if ( pXLookupString(xkey, (char *)keybuf, sizeof(keybuf), 834
715 NULL, &state) ) { 835 /* if there is no connection with the IM server, use the regular method */
716 /* 836 if (ic == NULL) {
717 * FIXME,: XLookupString() may yield more than one 837 unsigned char keybuf[32];
718 * character, so we need a mechanism to allow for 838
719 * this (perhaps generate null keypress events with 839 if ( pXLookupString(xkey, (char *)keybuf, sizeof(keybuf),
720 * a unicode value) 840 NULL, &state) ) {
721 */ 841 /*
722 keysym->unicode = keybuf[0]; 842 * FIXME,: XLookupString() may yield more than one
843 * character, so we need a mechanism to allow for
844 * this (perhaps generate null keypress events with
845 * a unicode value)
846 */
847 keysym->unicode = keybuf[0];
848 }
849 } else { /* else, use the IM protocol */
850 #ifdef X_HAVE_UTF8_STRING
851 /* A UTF-8 character can be at most 6 bytes */
852 unsigned char keybuf[6];
853 pXSetICFocus(ic);
854 if ( pXutf8LookupString(ic, (XKeyPressedEvent *)xkey, (char *)keybuf, sizeof(keybuf),
855 NULL, (Status *)&state) )
856 keysym->unicode = Utf8ToUcs4(keybuf);
857 pXUnsetICFocus(ic);
858 #endif
723 } 859 }
724 } 860 }
725 return(keysym); 861 return(keysym);
726 } 862 }
727 863
830 if ( pXLookupString(&xkey, keybuf, sizeof(keybuf), NULL, NULL) ) 966 if ( pXLookupString(&xkey, keybuf, sizeof(keybuf), NULL, NULL) )
831 unicode = (unsigned char)keybuf[0]; 967 unicode = (unsigned char)keybuf[0];
832 return(unicode); 968 return(unicode);
833 } 969 }
834 970
971
835 /* 972 /*
836 * Called when focus is regained, to read the keyboard state and generate 973 * Called when focus is regained, to read the keyboard state and generate
837 * synthetic keypress/release events. 974 * synthetic keypress/release events.
838 * key_vec is a bit vector of keycodes (256 bits) 975 * key_vec is a bit vector of keycodes (256 bits)
839 */ 976 */
840 void X11_SetKeyboardState(Display *display, const char *key_vec) 977 void X11_SetKeyboardState(Display *display, XIC ic, const char *key_vec)
841 { 978 {
842 char keys_return[32]; 979 char keys_return[32];
843 int i; 980 int i;
844 KeyCode xcode[SDLK_LAST]; 981 KeyCode xcode[SDLK_LAST];
845 Uint8 new_kstate[SDLK_LAST]; 982 Uint8 new_kstate[SDLK_LAST];
884 continue; 1021 continue;
885 for(j = 0; j < 8; j++) { 1022 for(j = 0; j < 8; j++) {
886 if(key_vec[i] & (1 << j)) { 1023 if(key_vec[i] & (1 << j)) {
887 SDL_keysym sk; 1024 SDL_keysym sk;
888 KeyCode kc = i << 3 | j; 1025 KeyCode kc = i << 3 | j;
889 X11_TranslateKey(display, NULL, kc, &sk); 1026 X11_TranslateKey(display, ic, NULL, kc, &sk);
890 new_kstate[sk.sym] = SDL_PRESSED; 1027 new_kstate[sk.sym] = SDL_PRESSED;
891 xcode[sk.sym] = kc; 1028 xcode[sk.sym] = kc;
892 } 1029 }
893 } 1030 }
894 } 1031 }