Skip to content

Instantly share code, notes, and snippets.

@bratsche
Created September 16, 2013 20:46
Show Gist options
  • Save bratsche/6586375 to your computer and use it in GitHub Desktop.
Save bratsche/6586375 to your computer and use it in GitHub Desktop.
Updated patch
diff --git a/gdk/win32/gdkevents-win32.c b/gdk/win32/gdkevents-win32.c
index 1cde4fc..a9ffc09 100644
--- a/gdk/win32/gdkevents-win32.c
+++ b/gdk/win32/gdkevents-win32.c
@@ -2029,6 +2029,114 @@ ensure_stacking_on_activate_app (MSG *msg,
}
}
+static gboolean
+wm_char_wparam_needs_translation (WPARAM wParam)
+{
+ switch (wParam)
+ {
+ case VK_RETURN:
+ case VK_TAB:
+ case VK_BACK:
+ return TRUE;
+
+ default:
+ return FALSE;
+ }
+}
+
+static void
+emit_gdk_key_event (MSG *msg,
+ gint gdk_evt_type,
+ guint16 hardware_keycode,
+ 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;
+ event->key.hardware_keycode = hardware_keycode;
+ //event->key.hardware_keycode = MapVirtualKey (msg->wParam, 1);
+ }
+ 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 +2156,8 @@ gdk_event_translate (MSG *msg,
HIMC himc;
WINDOWPOS *windowpos;
gboolean ignore_leave;
+ MSG msg2;
+ gboolean msg2_res;
GdkEvent *event;
@@ -2057,7 +2167,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 +2181,13 @@ 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;
+ static guint16 last_hardware_keycode = 0;
+
if (_gdk_default_filters)
{
/* Apply global filters */
@@ -2086,7 +2203,6 @@ gdk_event_translate (MSG *msg,
}
window = gdk_win32_handle_table_lookup ((GdkNativeWindow) msg->hwnd);
- orig_window = window;
if (window == NULL)
{
@@ -2231,10 +2347,13 @@ 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,
+ 0,
+ window,
+ _gdk_display->keyboard_grab);
+ break;
- case WM_KEYUP:
case WM_KEYDOWN:
GDK_NOTE (EVENTS,
g_print (" %s ch:%.02x %s",
@@ -2242,77 +2361,96 @@ 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;
+ }
+
+ last_hardware_keycode = msg->wParam;
- /* 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,
+ msg->wParam,
+ 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,
+ msg->wParam,
+ 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));
+ break;
+ }
- /* 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);
+ if (!PeekMessageW (&msg2, NULL, WM_CHAR, WM_CHAR, PM_NOREMOVE))
+ {
+ emit_gdk_key_event (msg,
+ GDK_KEY_RELEASE,
+ msg->wParam,
+ window,
+ _gdk_display->keyboard_grab);
+ }
- 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);
+ last_hardware_keycode = 0;
- 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,
+ last_hardware_keycode,
+ 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