From 3d4caf53f8a62f04ea2ea658b3b49376f2487d9c Mon Sep 17 00:00:00 2001 From: Tim Hentenaar Date: Mon, 4 Jun 2018 21:50:36 +0200 Subject: [PATCH 1/2] SDL2: Fix SDL_TEXTINPUT handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous code was only examining the first character of the string from the SDL_TEXTINPUT event, although SDL_TEXTINPUT can return multiple characters at a time. For example, if I enter "玉米超人“ with my chinese IME, in wide mode, only the first character will be evaluated. Depending on the IME, it may be possible in non-wide mode to also receive multiple characters at a time. Thus, when we get a SDL_TEXTINPUT event, we should process each character before polling for the next event. --- sdl2/pdckbd.c | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/sdl2/pdckbd.c b/sdl2/pdckbd.c index bbaf2df8..27a3eada 100644 --- a/sdl2/pdckbd.c +++ b/sdl2/pdckbd.c @@ -111,7 +111,16 @@ void PDC_set_keyboard_binary(bool on) bool PDC_check_key(void) { Uint32 current = SDL_GetTicks(); - int haveevent = SDL_PollEvent(&event); + int haveevent; + + /** + * SDL_TEXTINPUT can return multiple chars from the IME + * which we should handle before polling for additional + * events. + */ + if (event.type == SDL_TEXTINPUT && event.text.text[0]) + haveevent = 1; + else haveevent = SDL_PollEvent(&event); /* if we have an event, or 30 ms have passed without a screen update, or the timer has wrapped, update now */ @@ -124,7 +133,7 @@ bool PDC_check_key(void) } #ifdef PDC_WIDE -static int _utf8_to_unicode(char *chstr) +static int _utf8_to_unicode(char *chstr, size_t *b) { int i, bytes, unicode; unsigned char byte = chstr[0]; @@ -157,6 +166,7 @@ static int _utf8_to_unicode(char *chstr) for (i = 1; i < bytes; i++) unicode = (unicode << 6) + (chstr[i] & 0x3f); + *b = bytes; return unicode; } #endif @@ -166,6 +176,10 @@ static int _process_key_event(void) int i, key = 0; unsigned long old_modifiers = pdc_key_modifiers; +#ifdef PDC_WIDE + size_t bytes; +#endif + pdc_key_modifiers = 0L; SP->key_code = FALSE; @@ -198,9 +212,20 @@ static int _process_key_event(void) { pdc_key_modifiers = old_modifiers; #ifdef PDC_WIDE - return _utf8_to_unicode(event.text.text); + if ((key = _utf8_to_unicode(event.text.text, &bytes)) == -1) + { + event.text.text[0] = '\0'; + } + else + { + memmove(event.text.text, event.text.text+bytes, + strlen(event.text.text)-bytes+1); + } + return key; #else key = (unsigned char)event.text.text[0]; + memmove(event.text.text, event.text.text+1, + strlen(event.text.text)); return key > 0x7f ? -1 : key; #endif } From 38f21172436f2bd73c862a97431f03d99e6986af Mon Sep 17 00:00:00 2001 From: Tim Hentenaar Date: Tue, 5 Jun 2018 12:43:06 +0200 Subject: [PATCH 2/2] SDL2: Fix handling of keys with modifiers --- sdl2/pdckbd.c | 137 ++++++++++++++++++++++++++++---------------------- 1 file changed, 78 insertions(+), 59 deletions(-) diff --git a/sdl2/pdckbd.c b/sdl2/pdckbd.c index 27a3eada..d5395766 100644 --- a/sdl2/pdckbd.c +++ b/sdl2/pdckbd.c @@ -171,23 +171,72 @@ static int _utf8_to_unicode(char *chstr, size_t *b) } #endif +/* Handle ALT and CTRL sequences */ +static int _handle_alt_keys(int key) +{ + if (key > 0x7f) + return key; + + if (pdc_key_modifiers & PDC_KEY_MODIFIER_CONTROL) + { + if (key >= 'A' && key <= 'Z') key -= 64; + if (key >= 'a' && key <= 'z') key -= 96; + } + else if (pdc_key_modifiers & PDC_KEY_MODIFIER_ALT) + { + if (key >= 'A' && key <= 'Z') + { + key += ALT_A - 'A'; + SP->key_code = TRUE; + } else if (key >= 'a' && key <= 'z') + { + key += ALT_A - 'a'; + SP->key_code = TRUE; + } else if (key >= '0' && key <= '9') + { + key += ALT_0 - '0'; + SP->key_code = TRUE; + } + } + + return key; +} + static int _process_key_event(void) { int i, key = 0; - unsigned long old_modifiers = pdc_key_modifiers; #ifdef PDC_WIDE size_t bytes; #endif - pdc_key_modifiers = 0L; SP->key_code = FALSE; if (event.type == SDL_KEYUP) { - if (SP->return_key_modifiers && event.key.keysym.sym == oldkey) + switch (event.key.keysym.sym) { - switch (oldkey) + case SDLK_LCTRL: + case SDLK_RCTRL: + pdc_key_modifiers &= ~PDC_KEY_MODIFIER_CONTROL; + break; + case SDLK_LALT: + case SDLK_RALT: + pdc_key_modifiers &= ~PDC_KEY_MODIFIER_ALT; + break; + case SDLK_LSHIFT: + case SDLK_RSHIFT: + pdc_key_modifiers &= ~PDC_KEY_MODIFIER_SHIFT; + break; + } + + if (!(SDL_GetModState() & KMOD_NUM)) + pdc_key_modifiers &= ~PDC_KEY_MODIFIER_NUMLOCK; + + if (SP->return_key_modifiers) + { + SP->key_code = TRUE; + switch (event.key.keysym.sym) { case SDLK_RSHIFT: return KEY_SHIFT_R; @@ -206,11 +255,11 @@ static int _process_key_event(void) } } + SP->key_code = FALSE; return -1; } else if (event.type == SDL_TEXTINPUT) { - pdc_key_modifiers = old_modifiers; #ifdef PDC_WIDE if ((key = _utf8_to_unicode(event.text.text, &bytes)) == -1) { @@ -221,30 +270,36 @@ static int _process_key_event(void) memmove(event.text.text, event.text.text+bytes, strlen(event.text.text)-bytes+1); } - return key; + return _handle_alt_keys(key); #else key = (unsigned char)event.text.text[0]; memmove(event.text.text, event.text.text+1, strlen(event.text.text)); - return key > 0x7f ? -1 : key; + return key > 0x7f ? -1 : _handle_alt_keys(key); #endif } - oldkey = event.key.keysym.sym; + if (SDL_GetModState() & KMOD_NUM) + pdc_key_modifiers |= PDC_KEY_MODIFIER_NUMLOCK; - if (SP->save_key_modifiers) + switch (event.key.keysym.sym) { - if (event.key.keysym.mod & KMOD_NUM) - pdc_key_modifiers |= PDC_KEY_MODIFIER_NUMLOCK; - - if (event.key.keysym.mod & KMOD_SHIFT) - pdc_key_modifiers |= PDC_KEY_MODIFIER_SHIFT; - - if (event.key.keysym.mod & KMOD_CTRL) + case SDLK_LCTRL: + case SDLK_RCTRL: pdc_key_modifiers |= PDC_KEY_MODIFIER_CONTROL; - - if (event.key.keysym.mod & KMOD_ALT) + break; + case SDLK_LALT: + case SDLK_RALT: pdc_key_modifiers |= PDC_KEY_MODIFIER_ALT; + break; + case SDLK_LSHIFT: + case SDLK_RSHIFT: + pdc_key_modifiers |= PDC_KEY_MODIFIER_SHIFT; + break; + case SDLK_RETURN: + return 0x0d; + default: + key = event.key.keysym.sym; } for (i = 0; key_table[i].keycode; i++) @@ -271,50 +326,14 @@ static int _process_key_event(void) } SP->key_code = (key > 0x100); - break; + return key; } } - if (!key) - { - key = (int) event.key.keysym.sym; - if (key >= 'a' && key <= 'z') - if (event.key.keysym.mod & KMOD_SHIFT) - key = toupper(key); - - if (key > 0x7f) - key = 0; - } - - /* Handle ALT letters and numbers */ - - if (event.key.keysym.mod & KMOD_ALT) - { - if (key >= 'A' && key <= 'Z') - { - key += ALT_A - 'A'; - SP->key_code = TRUE; - } - - if (key >= 'a' && key <= 'z') - { - key += ALT_A - 'a'; - SP->key_code = TRUE; - } - - if (key >= '0' && key <= '9') - { - key += ALT_0 - '0'; - SP->key_code = TRUE; - } - } - - /* Textual input is handled by the SDL_TEXTINPUT event */ - if (' ' <= key && key <= '~') { - return -1; - } - - return key ? key : -1; + /* SDL with TextInput ignores keys with CTRL */ + if (key && pdc_key_modifiers & PDC_KEY_MODIFIER_CONTROL) + return _handle_alt_keys(key); + return -1; } static int _process_mouse_event(void)