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