From 4f87bc99736df0cc3736fec9a12426952ffa0385 Mon Sep 17 00:00:00 2001 From: Robin Gustafsson Date: Sat, 19 Nov 2016 01:30:38 +0100 Subject: [PATCH] Implement proper text input through the SDL2 TextInput API Input using SDL_KEYDOWN was limited to characters with a dedicated US-layout keyboard key (e.g. shift-2 produced 2 instead of @). Textual input is now handled through the SDL_TEXTINPUT event, giving the proper character for the current keyboard layout. This includes Unicode input support for WIDE builds. --- sdl2/pdckbd.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++ sdl2/pdcscrn.c | 7 +++++++ 2 files changed, 62 insertions(+) diff --git a/sdl2/pdckbd.c b/sdl2/pdckbd.c index 3af2fa50..61b68f91 100644 --- a/sdl2/pdckbd.c +++ b/sdl2/pdckbd.c @@ -123,9 +123,48 @@ bool PDC_check_key(void) return haveevent; } +#ifdef PDC_WIDE +static int _utf8_to_unicode(char *chstr) +{ + int i, bytes, unicode; + unsigned char byte = chstr[0]; + + if (byte > 0xf0) + { + bytes = 4; + unicode = byte & 0x7; + } + else if (byte > 0xe0) + { + bytes = 3; + unicode = byte & 0xf; + } + else if (byte > 0xc0) + { + bytes = 2; + unicode = byte & 0x1f; + } + else if (byte > 0x80) { + /* starts with a continuation byte; invalid character */ + return -1; + } + else + { + bytes = 1; + unicode = byte; + } + + for (i = 1; i < bytes; i++) + unicode = (unicode << 6) + (chstr[i] & 0x3f); + + return unicode; +} +#endif + static int _process_key_event(void) { int i, key = 0; + unsigned long old_modifiers = pdc_key_modifiers; pdc_key_modifiers = 0L; SP->key_code = FALSE; @@ -155,6 +194,16 @@ static int _process_key_event(void) return -1; } + else if (event.type == SDL_TEXTINPUT) + { + pdc_key_modifiers = old_modifiers; +#ifdef PDC_WIDE + return _utf8_to_unicode(event.text.text); +#else + key = (unsigned char)event.text.text[0]; + return key > 0x7f ? -1 : key; +#endif + } oldkey = event.key.keysym.sym; @@ -235,6 +284,11 @@ static int _process_key_event(void) } } + /* Textual input is handled by the SDL_TEXTINPUT event */ + if (' ' <= key && key <= '~') { + return -1; + } + return key ? key : -1; } @@ -380,6 +434,7 @@ int PDC_get_key(void) break; case SDL_KEYUP: case SDL_KEYDOWN: + case SDL_TEXTINPUT: PDC_mouse_set(); return _process_key_event(); } diff --git a/sdl2/pdcscrn.c b/sdl2/pdcscrn.c index 92a53d48..de1f0a58 100644 --- a/sdl2/pdcscrn.c +++ b/sdl2/pdcscrn.c @@ -223,6 +223,11 @@ int PDC_scr_open(int argc, char **argv) return ERR; } SDL_SetWindowIcon(pdc_window, pdc_icon); + + /* Events must be pumped before calling SDL_GetWindowSurface, or + initial modifiers (e.g. numlock) will be ignored and out-of-sync. */ + SDL_PumpEvents(); + pdc_screen = SDL_GetWindowSurface(pdc_window); if (pdc_screen == NULL) { @@ -266,6 +271,8 @@ int PDC_scr_open(int argc, char **argv) pdc_mapped[i] = SDL_MapRGB(pdc_screen->format, pdc_color[i].r, pdc_color[i].g, pdc_color[i].b); + SDL_StartTextInput(); + PDC_mouse_set(); if (pdc_own_window)