From 2daa83d476eaa0636e7b2cd85a7a8e64822450f9 Mon Sep 17 00:00:00 2001 From: Pavel Sountsov Date: Fri, 11 Oct 2024 21:33:17 -0700 Subject: [PATCH] Enable WM_CHAR to support IME and Alt codes --- include/allegro5/platform/aintwin.h | 2 + src/win/d3d_disp.cpp | 4 +- src/win/wgl_disp.c | 4 +- src/win/wkeyboard.c | 96 +++++++++++++++++++++++------ src/win/wwindow.c | 9 +++ 5 files changed, 93 insertions(+), 22 deletions(-) diff --git a/include/allegro5/platform/aintwin.h b/include/allegro5/platform/aintwin.h index a2b6a93fe..e74e0e915 100644 --- a/include/allegro5/platform/aintwin.h +++ b/include/allegro5/platform/aintwin.h @@ -126,6 +126,8 @@ void _al_win_kbd_handle_key_press(int scode, int vcode, bool extended, bool repeated, ALLEGRO_DISPLAY_WIN *win_disp); void _al_win_kbd_handle_key_release(int scode, int vcode, bool extended, ALLEGRO_DISPLAY_WIN *win_disp); +void _al_win_kbd_handle_char(int scode, int unichar, bool extended, + bool repeated, ALLEGRO_DISPLAY_WIN *win_disp); void _al_win_fix_modifiers(void); /* mouse routines */ diff --git a/src/win/d3d_disp.cpp b/src/win/d3d_disp.cpp index 67103555b..3a3bf8aab 100644 --- a/src/win/d3d_disp.cpp +++ b/src/win/d3d_disp.cpp @@ -1473,8 +1473,10 @@ static void *d3d_display_thread_proc(void *arg) al_rest(0.001); if (PeekMessage(&msg, NULL, 0, 0, FALSE)) { - if (GetMessage(&msg, NULL, 0, 0) != 0) + if (GetMessage(&msg, NULL, 0, 0) != 0) { + TranslateMessage(&msg); DispatchMessage(&msg); + } else break; /* WM_QUIT received or error (GetMessage returned -1) */ } diff --git a/src/win/wgl_disp.c b/src/win/wgl_disp.c index 94316d067..cc46c2cfb 100644 --- a/src/win/wgl_disp.c +++ b/src/win/wgl_disp.c @@ -1314,8 +1314,10 @@ static void display_thread_proc(void *arg) while (!win_disp->end_thread) { /* get a message from the queue */ - if (GetMessage(&msg, NULL, 0, 0) != 0) + if (GetMessage(&msg, NULL, 0, 0) != 0) { + TranslateMessage(&msg); DispatchMessage(&msg); + } else break; /* WM_QUIT received or error (GetMessage returned -1) */ } diff --git a/src/win/wkeyboard.c b/src/win/wkeyboard.c index b1bff956b..27e4814df 100644 --- a/src/win/wkeyboard.c +++ b/src/win/wkeyboard.c @@ -32,6 +32,7 @@ static bool installed = false; static ALLEGRO_KEYBOARD the_keyboard; static ALLEGRO_KEYBOARD_STATE the_state; static int modifiers = 0; +static int surrogate = 0; /* lookup table for converting virtualkey VK_* codes into Allegro ALLEGRO_KEY_* codes */ /* For handling of extended keys, extkey_to_keycode() takes priority over this. */ @@ -322,6 +323,61 @@ static void update_toggle_modifiers(void) } +/* Some unicode characters are passed as pairs of events. We detect + * them based on the fact that the individual characters will be + * members of a surrogate pair. + */ +void _al_win_kbd_handle_char(int scode, int unichar, bool extended, + bool repeated, ALLEGRO_DISPLAY_WIN *win_disp) +{ + ALLEGRO_DISPLAY *display = (ALLEGRO_DISPLAY *)win_disp; + int my_code; + int vcode; + + if (!installed) + return; + + if ((unichar >= 0xD800) && (unichar <= 0xDBFF)) { + surrogate = unichar; + } + else { + if ((unichar >= 0xDC00) && (unichar <= 0xDFFF)) { + unichar = ((surrogate - 0xD800) << 10) + (unichar - 0xDC00) + 0x0010000; + surrogate = 0; + } + + vcode = MapVirtualKey(scode, MAPVK_VSC_TO_VK_EX); + + my_code = 0; + if (extended) + my_code = extkey_to_keycode(vcode); + else + my_code = hw_to_mycode[vcode]; + + /* Send char events, but not for modifier keys or dead keys. */ + if (my_code < ALLEGRO_KEY_MODIFIERS) { + ALLEGRO_EVENT event; + + bool actual_repeat = repeated && _AL_KEYBOARD_STATE_KEY_DOWN(the_state, my_code); + _AL_KEYBOARD_STATE_SET_KEY_DOWN(the_state, my_code); + _al_event_source_lock(&the_keyboard.es); + event.keyboard.timestamp = al_get_time(); + event.keyboard.display = display; + event.keyboard.keycode = my_code; + event.keyboard.type = ALLEGRO_EVENT_KEY_CHAR; + update_toggle_modifiers(); + event.keyboard.modifiers = modifiers; + event.keyboard.repeat = actual_repeat; + event.keyboard.unichar = unichar; + _al_event_source_emit_event(&the_keyboard.es, &event); + + _al_event_source_unlock(&the_keyboard.es); + } + } +} + + + /* _al_win_kbd_handle_key_press: * Does stuff when a key is pressed. @@ -377,26 +433,26 @@ void _al_win_kbd_handle_key_press(int scode, int vcode, bool extended, _al_event_source_emit_event(&the_keyboard.es, &event); } - /* Send char events, but not for modifier keys or dead keys. */ - if (my_code < ALLEGRO_KEY_MODIFIERS) { - char_count = ToUnicode(vcode, scode, GetKeyboardState(ks) ? ks : NULL, buf, 8, 0); - /* Send ASCII code 127 for both Del keys. */ - if (char_count == 0 && vcode == VK_DELETE) { - char_count = 1; - buf[0] = 127; - } - if (char_count != -1) { /* -1 means it was a dead key. */ - event_count = char_count ? char_count : 1; - event.keyboard.type = ALLEGRO_EVENT_KEY_CHAR; - update_toggle_modifiers(); - event.keyboard.modifiers = modifiers; - event.keyboard.repeat = actual_repeat; - for (i = 0; i < event_count; i++) { - event.keyboard.unichar = buf[i]; - _al_event_source_emit_event(&the_keyboard.es, &event); - } - } - } + //~ /* Send char events, but not for modifier keys or dead keys. */ + //~ if (my_code < ALLEGRO_KEY_MODIFIERS) { + //~ char_count = ToUnicode(vcode, scode, GetKeyboardState(ks) ? ks : NULL, buf, 8, 0); + //~ /* Send ASCII code 127 for both Del keys. */ + //~ if (char_count == 0 && vcode == VK_DELETE) { + //~ char_count = 1; + //~ buf[0] = 127; + //~ } + //~ if (char_count != -1) { /* -1 means it was a dead key. */ + //~ event_count = char_count ? char_count : 1; + //~ event.keyboard.type = ALLEGRO_EVENT_KEY_CHAR; + //~ update_toggle_modifiers(); + //~ event.keyboard.modifiers = modifiers; + //~ event.keyboard.repeat = actual_repeat; + //~ for (i = 0; i < event_count; i++) { + //~ event.keyboard.unichar = buf[i]; + //~ _al_event_source_emit_event(&the_keyboard.es, &event); + //~ } + //~ } + //~ } _al_event_source_unlock(&the_keyboard.es); /* Toggle mouse grab key. */ diff --git a/src/win/wwindow.c b/src/win/wwindow.c index f114c08e7..3e9f3cb6e 100644 --- a/src/win/wwindow.c +++ b/src/win/wwindow.c @@ -730,6 +730,15 @@ static LRESULT CALLBACK window_callback(HWND hWnd, UINT message, } break; } + case WM_SYSCHAR: + case WM_CHAR: { + int vcode = wParam; + int scode = (lParam >> 16) & 0xff; + bool extended = (lParam >> 24) & 0x1; + bool repeated = (lParam >> 30) & 0x1; + _al_win_kbd_handle_char(scode, vcode, extended, repeated, win_display); + break; + } case WM_SYSKEYDOWN: { int vcode = wParam; int scode = (lParam >> 16) & 0xff;