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.
This commit is contained in:
Robin Gustafsson
2016-11-19 01:30:38 +01:00
parent 586d3bfca7
commit 4f87bc9973
2 changed files with 62 additions and 0 deletions

View File

@@ -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();
}

View File

@@ -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)