Skip to content
Permalink
Browse files

Fixed bug 1876 - SDL_TEXTINPUT only returns '?' (0x3F) in event.text.…

…text with Khmer language input

Andreas

The issue comes down to this line on MSDN:
"TranslateMessage produces WM_CHAR messages only for keys that are mapped to ASCII characters by the keyboard driver."

"WM_KEYDOWN and WM_KEYUP combinations produce a WM_CHAR or WM_DEADCHAR message. WM_SYSKEYDOWN and WM_SYSKEYUP combinations produce a WM_SYSCHAR or WM_SYSDEADCHAR message."
Except for WM_CHAR, none of these messages are used in SDL. Hence TranslateMessage should be dropped entirely and proper handling be included in the WM_KEYDOWN event.
Currently TranslateMessage is called for every message even if it must not be called in certain cases (like "An application should not call TranslateMessage if the TranslateAccelerator function returns a nonzero value.").

WM_CHAR message handling should remain for external processes posting these messages - additionally, WM_UNICHAR should be added.

I made a patch for src/video/windows/SDL_windowsevents.c that seems to work fine. It doesn't solve the "missing" composition for Khmer, but at least input for languages that cannot be mapped to ASCII characters (and for which IME is not used) will now work on Windows.
  • Loading branch information
slouken committed Aug 16, 2013
1 parent bb2671b commit b4b12d950e67dbfbd148ebcdd891ffb2f9b4b1f5
Showing with 54 additions and 18 deletions.
  1. +54 −18 src/video/windows/SDL_windowsevents.c
@@ -256,6 +256,33 @@ WIN_CheckRawMouseButtons( ULONG rawButtons, SDL_WindowData *data )
}
}

static SDL_FORCE_INLINE BOOL
WIN_ConvertUTF32toUTF8(UINT32 codepoint, char * text)
{
if (codepoint <= 0x7F) {
text[0] = (char) codepoint;
text[1] = '\0';
} else if (codepoint <= 0x7FF) {
text[0] = 0xC0 | (char) ((codepoint >> 6) & 0x1F);
text[1] = 0x80 | (char) (codepoint & 0x3F);
text[2] = '\0';
} else if (codepoint <= 0xFFFF) {
text[0] = 0xE0 | (char) ((codepoint >> 12) & 0x0F);
text[1] = 0x80 | (char) ((codepoint >> 6) & 0x3F);
text[2] = 0x80 | (char) (codepoint & 0x3F);
text[3] = '\0';
} else if (codepoint <= 0x10FFFF) {
text[0] = 0xF0 | (char) ((codepoint >> 18) & 0x0F);
text[1] = 0x80 | (char) ((codepoint >> 12) & 0x3F);
text[2] = 0x80 | (char) ((codepoint >> 6) & 0x3F);
text[3] = 0x80 | (char) (codepoint & 0x3F);
text[4] = '\0';
} else {
return SDL_FALSE;
}
return SDL_TRUE;
}

LRESULT CALLBACK
WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
@@ -459,8 +486,23 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
break;
#endif /* WM_MOUSELEAVE */

case WM_SYSKEYDOWN:
case WM_KEYDOWN:
{
BYTE keyboardState[256];
char text[5];
UINT32 utf32 = 0;

GetKeyboardState(keyboardState);
if (ToUnicode(wParam, (lParam >> 16) & 0xff, keyboardState, (LPWSTR)&utf32, 1, 0) > 0) {
WORD repitition;
for (repitition = lParam & 0xffff; repitition > 0; repitition--) {
WIN_ConvertUTF32toUTF8(utf32, text);
SDL_SendKeyboardText(text);
}
}
}
// no break
case WM_SYSKEYDOWN:
{
SDL_Scancode code = WindowsScanCodeToSDLScanCode( lParam, wParam );
if ( code != SDL_SCANCODE_UNKNOWN ) {
@@ -485,24 +527,19 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
returnCode = 0;
break;

case WM_CHAR:
case WM_UNICHAR:
{
char text[4];

/* Convert to UTF-8 and send it on... */
if (wParam <= 0x7F) {
text[0] = (char) wParam;
text[1] = '\0';
} else if (wParam <= 0x7FF) {
text[0] = 0xC0 | (char) ((wParam >> 6) & 0x1F);
text[1] = 0x80 | (char) (wParam & 0x3F);
text[2] = '\0';
} else {
text[0] = 0xE0 | (char) ((wParam >> 12) & 0x0F);
text[1] = 0x80 | (char) ((wParam >> 6) & 0x3F);
text[2] = 0x80 | (char) (wParam & 0x3F);
text[3] = '\0';
if (wParam == UNICODE_NOCHAR) {
returnCode = 1;
break;
}
}
// no break
case WM_CHAR:
{
char text[5];

WIN_ConvertUTF32toUTF8(wParam, text);
SDL_SendKeyboardText(text);
}
returnCode = 0;
@@ -772,7 +809,6 @@ WIN_PumpEvents(_THIS)
const Uint8 *keystate;
MSG msg;
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}

0 comments on commit b4b12d9

Please sign in to comment.