Last active
December 23, 2015 04:39
-
-
Save bratsche/6581909 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/gdk/win32/gdkevents-win32.c b/gdk/win32/gdkevents-win32.c | |
index 1cde4fc..065b350 100644 | |
--- a/gdk/win32/gdkevents-win32.c | |
+++ b/gdk/win32/gdkevents-win32.c | |
@@ -2029,6 +2029,110 @@ ensure_stacking_on_activate_app (MSG *msg, | |
} | |
} | |
+static gboolean | |
+wm_char_wparam_needs_translation (WPARAM wParam) | |
+{ | |
+ switch (wParam) | |
+ { | |
+ case VK_RETURN: | |
+ case VK_TAB: | |
+ return TRUE; | |
+ | |
+ default: | |
+ return FALSE; | |
+ } | |
+} | |
+ | |
+static void | |
+emit_gdk_key_event (MSG *msg, | |
+ gint gdk_evt_type, | |
+ GdkWindow *window, | |
+ GdkKeyboardGrabInfo keyboard_grab) | |
+{ | |
+ GdkEvent *event = NULL; | |
+ wchar_t wbuf[100]; | |
+ BYTE key_state[256]; | |
+ | |
+ /* Ignore key messages intended for the IME */ | |
+ if (in_ime_composition || msg->wParam == VK_PROCESSKEY) | |
+ return; | |
+ | |
+ if (!propagate (&window, msg, | |
+ keyboard_grab.window, | |
+ keyboard_grab.owner_events, | |
+ GDK_ALL_EVENTS_MASK, | |
+ doesnt_want_key)) | |
+ return; | |
+ | |
+ if (GDK_WINDOW_DESTROYED (window)) | |
+ return; | |
+ | |
+ event = gdk_event_new (gdk_evt_type); | |
+ event->key.window = window; | |
+ event->key.time = _gdk_win32_get_next_tick (msg->time); | |
+ event->key.keyval = GDK_KEY_VoidSymbol; | |
+ event->key.string = NULL; | |
+ event->key.length = 0; | |
+ event->key.hardware_keycode = msg->wParam; | |
+ | |
+ if (HIWORD (msg->lParam) & KF_EXTENDED) | |
+ { | |
+ switch (msg->wParam) | |
+ { | |
+ case VK_CONTROL: | |
+ event->key.hardware_keycode = VK_RCONTROL; | |
+ break; | |
+ | |
+ case VK_SHIFT: | |
+ /* Actually, KF_EXTENDED is not set for the right shift key */ | |
+ event->key.hardware_keycode = VK_RSHIFT; | |
+ break; | |
+ | |
+ case VK_MENU: | |
+ event->key.hardware_keycode = VK_RMENU; | |
+ break; | |
+ } | |
+ } | |
+ else if (msg->wParam == VK_SHIFT && LOBYTE (HIWORD (msg->lParam)) == _scancode_rshift) | |
+ { | |
+ event->key.hardware_keycode = VK_RSHIFT; | |
+ } | |
+ | |
+ API_CALL (GetKeyboardState, (key_state)); | |
+ | |
+ build_key_event_state (event, key_state); | |
+ | |
+ if (msg->message == WM_CHAR && !wm_char_wparam_needs_translation (msg->wParam)) | |
+ { | |
+ event->key.keyval = msg->wParam; | |
+ } | |
+ else | |
+ { | |
+ if (msg->wParam == VK_PACKET && | |
+ ToUnicode (VK_PACKET, HIWORD (msg->lParam), key_state, wbuf, 1, 0) == 1) | |
+ { | |
+ event->key.keyval = gdk_unicode_to_keyval (wbuf[0]); | |
+ } | |
+ else | |
+ { | |
+ gdk_keymap_translate_keyboard_state (NULL, | |
+ event->key.hardware_keycode, | |
+ event->key.state, | |
+ event->key.group, | |
+ &event->key.keyval, | |
+ NULL, NULL, NULL); | |
+ } | |
+ } | |
+ | |
+ fill_key_event_string (event); | |
+ | |
+ /* Reset MOD1_MASK if it is the Alt key itself */ | |
+ if (msg->wParam == VK_MENU) | |
+ event->key.state &= ~GDK_MOD1_MASK; | |
+ | |
+ _gdk_win32_append_event (event); | |
+} | |
+ | |
#define GDK_ANY_BUTTON_MASK (GDK_BUTTON1_MASK | \ | |
GDK_BUTTON2_MASK | \ | |
GDK_BUTTON3_MASK | \ | |
@@ -2048,6 +2152,8 @@ gdk_event_translate (MSG *msg, | |
HIMC himc; | |
WINDOWPOS *windowpos; | |
gboolean ignore_leave; | |
+ MSG msg2; | |
+ gboolean msg2_res; | |
GdkEvent *event; | |
@@ -2057,7 +2163,7 @@ gdk_event_translate (MSG *msg, | |
GdkWindow *window = NULL; | |
GdkWindowImplWin32 *impl; | |
- GdkWindow *orig_window, *new_window; | |
+ GdkWindow *new_window; | |
GdkPointerGrabInfo *grab = NULL; | |
GdkWindow *grab_window = NULL; | |
@@ -2071,6 +2177,12 @@ gdk_event_translate (MSG *msg, | |
int i; | |
+ /* Internal state about keyboard sequence for dead key input */ | |
+ static gboolean have_dead = FALSE; | |
+ static gboolean finished_dead = FALSE; | |
+ static gboolean in_dead_sequence = FALSE; | |
+ static gboolean awaiting_next_in_sequence = FALSE; | |
+ | |
if (_gdk_default_filters) | |
{ | |
/* Apply global filters */ | |
@@ -2086,7 +2198,6 @@ gdk_event_translate (MSG *msg, | |
} | |
window = gdk_win32_handle_table_lookup ((GdkNativeWindow) msg->hwnd); | |
- orig_window = window; | |
if (window == NULL) | |
{ | |
@@ -2231,10 +2342,12 @@ gdk_event_translate (MSG *msg, | |
msg->wParam == VK_F4)) | |
break; | |
- /* Jump to code in common with WM_KEYUP and WM_KEYDOWN */ | |
- goto keyup_or_down; | |
+ emit_gdk_key_event (msg, | |
+ GDK_KEY_PRESS, | |
+ window, | |
+ _gdk_display->keyboard_grab); | |
+ break; | |
- case WM_KEYUP: | |
case WM_KEYDOWN: | |
GDK_NOTE (EVENTS, | |
g_print (" %s ch:%.02x %s", | |
@@ -2242,77 +2355,88 @@ gdk_event_translate (MSG *msg, | |
(int) msg->wParam, | |
decode_key_lparam (msg->lParam))); | |
- keyup_or_down: | |
+ if (PeekMessageW (&msg2, NULL, WM_DEADCHAR, WM_DEADCHAR, PM_NOREMOVE)) | |
+ { | |
+ have_dead = in_dead_sequence = TRUE; | |
+ return_val = FALSE; | |
+ break; | |
+ } | |
+ else if (have_dead && PeekMessageW (&msg2, NULL, WM_CHAR, WM_CHAR, PM_NOREMOVE)) | |
+ { | |
+ break; | |
+ } | |
- /* Ignore key messages intended for the IME */ | |
- if (msg->wParam == VK_PROCESSKEY || | |
- in_ime_composition) | |
- break; | |
+ msg2_res = PeekMessageW (&msg2, NULL, WM_CHAR, WM_CHAR, PM_NOREMOVE); | |
+ API_CALL (GetKeyboardState, (key_state)); | |
+ if (!msg2_res || | |
+ (key_state[VK_SHIFT] & 0x80) || | |
+ (key_state[VK_LCONTROL] & 0x80) || | |
+ (key_state[VK_RMENU] & 0x80) || | |
+ (key_state[VK_RCONTROL] & 0x80) || | |
+ (key_state[VK_LMENU] & 0x80) || | |
+ (key_state[VK_CONTROL] & 0x80) || | |
+ (key_state[VK_MENU] & 0x80)) | |
+ { | |
+ /* Eat the WM_CHAR message and emit it right now. */ | |
+ PeekMessageW (&msg2, NULL, WM_CHAR, WM_CHAR, PM_REMOVE); | |
- if (!propagate (&window, msg, | |
- _gdk_display->keyboard_grab.window, | |
- _gdk_display->keyboard_grab.owner_events, | |
- GDK_ALL_EVENTS_MASK, | |
- doesnt_want_key)) | |
- break; | |
+ emit_gdk_key_event (msg, | |
+ GDK_KEY_PRESS, | |
+ window, | |
+ _gdk_display->keyboard_grab); | |
+ } | |
- if (GDK_WINDOW_DESTROYED (window)) | |
- break; | |
+ break; | |
- event = gdk_event_new ((msg->message == WM_KEYDOWN || | |
- msg->message == WM_SYSKEYDOWN) ? | |
- GDK_KEY_PRESS : GDK_KEY_RELEASE); | |
- event->key.window = window; | |
- event->key.time = _gdk_win32_get_next_tick (msg->time); | |
- event->key.keyval = GDK_VoidSymbol; | |
- event->key.string = NULL; | |
- event->key.length = 0; | |
- event->key.hardware_keycode = msg->wParam; | |
- if (HIWORD (msg->lParam) & KF_EXTENDED) | |
+ case WM_KEYUP: | |
+ if (in_dead_sequence) | |
{ | |
- switch (msg->wParam) | |
+ if (finished_dead) | |
{ | |
- case VK_CONTROL: | |
- event->key.hardware_keycode = VK_RCONTROL; | |
- break; | |
- case VK_SHIFT: /* Actually, KF_EXTENDED is not set | |
- * for the right shift key. | |
- */ | |
- event->key.hardware_keycode = VK_RSHIFT; | |
- break; | |
- case VK_MENU: | |
- event->key.hardware_keycode = VK_RMENU; | |
- break; | |
+ if (!awaiting_next_in_sequence) | |
+ { | |
+ emit_gdk_key_event (msg, | |
+ GDK_KEY_RELEASE, | |
+ window, | |
+ _gdk_display->keyboard_grab); | |
+ in_dead_sequence = finished_dead = have_dead = FALSE; | |
+ return_val = TRUE; | |
+ break; | |
+ } | |
+ else | |
+ { | |
+ awaiting_next_in_sequence = FALSE; | |
+ } | |
+ } | |
+ else | |
+ { | |
+ finished_dead = TRUE; | |
+ awaiting_next_in_sequence = TRUE; | |
} | |
- } | |
- else if (msg->wParam == VK_SHIFT && | |
- LOBYTE (HIWORD (msg->lParam)) == _scancode_rshift) | |
- event->key.hardware_keycode = VK_RSHIFT; | |
- | |
- API_CALL (GetKeyboardState, (key_state)); | |
- /* g_print ("ctrl:%02x lctrl:%02x rctrl:%02x alt:%02x lalt:%02x ralt:%02x\n", key_state[VK_CONTROL], key_state[VK_LCONTROL], key_state[VK_RCONTROL], key_state[VK_MENU], key_state[VK_LMENU], key_state[VK_RMENU]); */ | |
- | |
- build_key_event_state (event, key_state); | |
+ break; | |
+ } | |
- if (msg->wParam == VK_PACKET && | |
- ToUnicode (VK_PACKET, HIWORD (msg->lParam), key_state, wbuf, 1, 0) == 1) | |
- event->key.keyval = gdk_unicode_to_keyval (wbuf[0]); | |
- else | |
- gdk_keymap_translate_keyboard_state (NULL, | |
- event->key.hardware_keycode, | |
- event->key.state, | |
- event->key.group, | |
- &event->key.keyval, | |
- NULL, NULL, NULL); | |
+ if (!PeekMessageW (&msg2, NULL, WM_CHAR, WM_CHAR, PM_NOREMOVE)) | |
+ { | |
+ emit_gdk_key_event (msg, | |
+ GDK_KEY_RELEASE, | |
+ window, | |
+ _gdk_display->keyboard_grab); | |
+ } | |
- fill_key_event_string (event); | |
+ break; | |
- /* Reset MOD1_MASK if it is the Alt key itself */ | |
- if (msg->wParam == VK_MENU) | |
- event->key.state &= ~GDK_MOD1_MASK; | |
+ case WM_CHAR: | |
+ if (in_dead_sequence) | |
+ { | |
+ finished_dead = TRUE; | |
+ } | |
- _gdk_win32_append_event (event); | |
+ emit_gdk_key_event (msg, | |
+ GDK_KEY_PRESS, | |
+ window, | |
+ _gdk_display->keyboard_grab); | |
return_val = TRUE; | |
break; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment