gdkevents-win32.c: Split out keyboard and IME events
...from gdk_event_translate(), as that function is getting too big and makes it harder to track things.
This commit is contained in:
@@ -1718,6 +1718,367 @@ _gdk_win32_surface_fill_min_max_info (GdkSurface *surface,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
handle_keyboard_event (GdkDisplay *display,
|
||||
GdkSurface *surface,
|
||||
MSG *msg,
|
||||
int *ret_valp,
|
||||
gboolean *goto_done)
|
||||
{
|
||||
GdkEvent *event;
|
||||
GdkWin32Display *win32_display = GDK_WIN32_DISPLAY (display);
|
||||
GdkWin32Keymap *win32_keymap;
|
||||
GdkTranslatedKey translated;
|
||||
gboolean return_val = FALSE;
|
||||
|
||||
switch (msg->message)
|
||||
{
|
||||
case WM_INPUTLANGCHANGE:
|
||||
{
|
||||
HKL input_locale;
|
||||
|
||||
win32_keymap = GDK_WIN32_KEYMAP (gdk_display_get_keymap (display));
|
||||
|
||||
input_locale = (HKL) msg->lParam;
|
||||
gdk_win32_display_set_input_locale (win32_display, input_locale);
|
||||
_gdk_win32_keymap_set_active_layout (win32_keymap, input_locale);
|
||||
gdk_win32_display_increment_keymap_serial (win32_display);
|
||||
GDK_NOTE (EVENTS,
|
||||
g_print (" cs:%lu hkl:%p%s",
|
||||
(gulong) msg->wParam,
|
||||
(gpointer) msg->lParam,
|
||||
gdk_win32_display_input_locale_is_ime (win32_display) ? " (IME)" : ""));
|
||||
gdk_display_setting_changed (display, "gtk-im-module");
|
||||
|
||||
/* Generate a dummy key event to "nudge" IMContext */
|
||||
translated.keyval = GDK_KEY_VoidSymbol;
|
||||
translated.consumed = 0;
|
||||
translated.layout = 0;
|
||||
translated.level = 0;
|
||||
event = gdk_key_event_new (GDK_KEY_PRESS,
|
||||
surface,
|
||||
win32_display->device_manager->core_keyboard,
|
||||
_gdk_win32_get_next_tick (msg->time),
|
||||
0,
|
||||
0,
|
||||
FALSE,
|
||||
&translated,
|
||||
&translated,
|
||||
NULL);
|
||||
_gdk_win32_append_event (event);
|
||||
}
|
||||
break;
|
||||
case WM_SYSKEYUP:
|
||||
case WM_SYSKEYDOWN:
|
||||
GDK_NOTE (EVENTS,
|
||||
g_print (" %s ch:%.02x %s",
|
||||
_gdk_win32_key_to_string (msg->lParam),
|
||||
(int) msg->wParam,
|
||||
decode_key_lparam (msg->lParam)));
|
||||
|
||||
/* If posted without us having keyboard focus, ignore */
|
||||
if ((msg->wParam != VK_F10 && msg->wParam != VK_MENU) &&
|
||||
!(HIWORD (msg->lParam) & KF_ALTDOWN))
|
||||
break;
|
||||
|
||||
/* Let the system handle Alt-Tab, Alt-Space and Alt-F4 unless
|
||||
* the keyboard is grabbed.
|
||||
*/
|
||||
if (!_gdk_display_get_last_device_grab (display, win32_display->device_manager->core_keyboard) &&
|
||||
(msg->wParam == VK_TAB ||
|
||||
msg->wParam == VK_SPACE ||
|
||||
msg->wParam == VK_F4))
|
||||
break;
|
||||
|
||||
/* Jump to code in common with WM_KEYUP and WM_KEYDOWN */
|
||||
G_GNUC_FALLTHROUGH;
|
||||
|
||||
case WM_KEYUP:
|
||||
case WM_KEYDOWN:
|
||||
{
|
||||
GdkModifierType state;
|
||||
guint keyval;
|
||||
guint16 keycode;
|
||||
guint8 group;
|
||||
gboolean is_modifier;
|
||||
GdkTranslatedKey no_lock;
|
||||
BYTE key_state[256];
|
||||
GArray *translation;
|
||||
MSG msg2;
|
||||
int level = 0;
|
||||
int effective_group = 0;
|
||||
GdkModifierType consumed = 0;
|
||||
char *composed = NULL;
|
||||
GdkWin32Surface *impl;
|
||||
|
||||
if (msg->message == WM_KEYUP || msg->message == WM_KEYDOWN)
|
||||
{
|
||||
GDK_NOTE (EVENTS,
|
||||
g_print (" %s ch:%.02x %s",
|
||||
_gdk_win32_key_to_string (msg->lParam),
|
||||
(int) msg->wParam,
|
||||
decode_key_lparam (msg->lParam)));
|
||||
}
|
||||
|
||||
/* Ignore key messages intended for the IME */
|
||||
if (msg->wParam == VK_PROCESSKEY || win32_display->event_record->in_ime_composition)
|
||||
break;
|
||||
|
||||
/* Ignore autorepeats on modifiers */
|
||||
if (msg->message == WM_KEYDOWN &&
|
||||
(msg->wParam == VK_MENU || msg->wParam == VK_CONTROL || msg->wParam == VK_SHIFT) &&
|
||||
((HIWORD(msg->lParam) & KF_REPEAT) >= 1))
|
||||
break;
|
||||
|
||||
if (GDK_SURFACE_DESTROYED (surface))
|
||||
break;
|
||||
|
||||
win32_keymap = GDK_WIN32_KEYMAP (gdk_display_get_keymap (display));
|
||||
impl = GDK_WIN32_SURFACE (surface);
|
||||
|
||||
API_CALL (GetKeyboardState, (key_state));
|
||||
|
||||
keyval = GDK_KEY_VoidSymbol;
|
||||
keycode = msg->wParam;
|
||||
|
||||
/* Get the WinAPI translation of the WM_KEY messages to characters.
|
||||
|
||||
The WM_CHAR messages are generated by a previous call to TranslateMessage() and always
|
||||
follow directly after the corresponding WM_KEY* messages.
|
||||
There could be 0 or more WM_CHAR messages following (for example dead keys don't generate
|
||||
WM_CHAR messages - they generate WM_DEAD_CHAR instead, but we are not interested in those
|
||||
messages). */
|
||||
|
||||
translation = g_array_sized_new (FALSE, FALSE, sizeof (gunichar2), 2);
|
||||
while (PeekMessageW (&msg2, msg->hwnd, 0, 0, 0) && (msg2.message == WM_CHAR || msg2.message == WM_SYSCHAR))
|
||||
{
|
||||
/* The character is encoded in WPARAM as UTF-16. */
|
||||
gunichar2 c = msg2.wParam;
|
||||
|
||||
/* Append character to translation string. */
|
||||
g_array_append_val (translation, c);
|
||||
|
||||
/* Remove message from queue */
|
||||
GetMessageW (&msg2, msg->hwnd, 0, 0);
|
||||
}
|
||||
|
||||
if (translation->len > 0)
|
||||
composed = g_utf16_to_utf8 ((gunichar2*)translation->data,
|
||||
translation->len, NULL, NULL, NULL);
|
||||
|
||||
g_array_unref (translation);
|
||||
translation = NULL;
|
||||
|
||||
/* Ignore control sequences like Backspace */
|
||||
if (composed && g_unichar_iscntrl (g_utf8_get_char (composed)))
|
||||
g_clear_pointer (&composed, g_free);
|
||||
|
||||
if (HIWORD (msg->lParam) & KF_EXTENDED)
|
||||
{
|
||||
switch (msg->wParam)
|
||||
{
|
||||
case VK_CONTROL:
|
||||
keycode = VK_RCONTROL;
|
||||
break;
|
||||
case VK_SHIFT: /* Actually, KF_EXTENDED is not set
|
||||
* for the right shift key.
|
||||
*/
|
||||
keycode = VK_RSHIFT;
|
||||
break;
|
||||
case VK_MENU:
|
||||
keycode = VK_RMENU;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (msg->wParam == VK_SHIFT &&
|
||||
LOBYTE (HIWORD (msg->lParam)) == _gdk_win32_keymap_get_rshift_scancode (win32_keymap))
|
||||
keycode = VK_RSHIFT;
|
||||
|
||||
is_modifier = (msg->wParam == VK_CONTROL ||
|
||||
msg->wParam == VK_SHIFT ||
|
||||
msg->wParam == VK_MENU);
|
||||
|
||||
state = build_key_event_state (display, key_state);
|
||||
group = get_active_group (display);
|
||||
|
||||
gdk_keymap_translate_keyboard_state ((GdkKeymap*) win32_keymap, keycode, state, group,
|
||||
&keyval, &effective_group, &level, &consumed);
|
||||
translated.keyval = keyval;
|
||||
translated.consumed = consumed;
|
||||
translated.layout = effective_group;
|
||||
translated.level = level;
|
||||
|
||||
gdk_keymap_translate_keyboard_state ((GdkKeymap*) win32_keymap, keycode,
|
||||
state & ~GDK_LOCK_MASK, group, &keyval,
|
||||
&effective_group, &level, &consumed);
|
||||
no_lock.keyval = keyval;
|
||||
no_lock.consumed = consumed;
|
||||
no_lock.layout = effective_group;
|
||||
no_lock.level = level;
|
||||
|
||||
/* Only one release key event is fired when both shift keys are pressed together
|
||||
and then released. In order to send the missing event, press events for shift
|
||||
keys are recorded and sent together when the release event occurs.
|
||||
Other modifiers (e.g. ctrl, alt) don't have this problem. */
|
||||
if (msg->message == WM_KEYDOWN && msg->wParam == VK_SHIFT)
|
||||
{
|
||||
int pressed_shift = msg->lParam & 0xffffff; /* mask shift modifier */
|
||||
|
||||
if (win32_display->event_record->both_shift_pressed[0] == 0)
|
||||
win32_display->event_record->both_shift_pressed[0] = pressed_shift;
|
||||
else if (win32_display->event_record->both_shift_pressed[0] != pressed_shift)
|
||||
win32_display->event_record->both_shift_pressed[1] = pressed_shift;
|
||||
}
|
||||
|
||||
if (msg->message == WM_KEYUP && msg->wParam == VK_SHIFT)
|
||||
{
|
||||
if (win32_display->event_record->both_shift_pressed[0] != 0 &&
|
||||
win32_display->event_record->both_shift_pressed[1] != 0)
|
||||
{
|
||||
int tmp_retval;
|
||||
MSG fake_release = *msg;
|
||||
int pressed_shift = msg->lParam & 0xffffff;
|
||||
|
||||
if (win32_display->event_record->both_shift_pressed[0] == pressed_shift)
|
||||
fake_release.lParam = win32_display->event_record->both_shift_pressed[1];
|
||||
else
|
||||
fake_release.lParam = win32_display->event_record->both_shift_pressed[0];
|
||||
|
||||
win32_display->event_record->both_shift_pressed[0] = win32_display->event_record->both_shift_pressed[1] = 0;
|
||||
gdk_event_translate (&fake_release, &tmp_retval);
|
||||
}
|
||||
win32_display->event_record->both_shift_pressed[0] = win32_display->event_record->both_shift_pressed[1] = 0;
|
||||
}
|
||||
|
||||
/* Reset ALT_MASK if it is the Alt key itself */
|
||||
if (msg->wParam == VK_MENU)
|
||||
state &= ~GDK_ALT_MASK;
|
||||
|
||||
event = gdk_key_event_new ((msg->message == WM_KEYDOWN || msg->message == WM_SYSKEYDOWN) ? GDK_KEY_PRESS : GDK_KEY_RELEASE,
|
||||
surface,
|
||||
win32_display->device_manager->core_keyboard,
|
||||
_gdk_win32_get_next_tick (msg->time),
|
||||
keycode,
|
||||
state,
|
||||
is_modifier,
|
||||
&translated,
|
||||
&no_lock,
|
||||
composed);
|
||||
|
||||
_gdk_win32_append_event (event);
|
||||
|
||||
g_free (composed);
|
||||
return_val = TRUE;
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_SYSCHAR:
|
||||
if (msg->wParam != VK_SPACE)
|
||||
{
|
||||
/* To prevent beeps, don't let DefWindowProcW() be called */
|
||||
return_val = TRUE;
|
||||
*goto_done = TRUE;
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_IME_STARTCOMPOSITION:
|
||||
win32_display->event_record->in_ime_composition = TRUE;
|
||||
break;
|
||||
|
||||
case WM_IME_ENDCOMPOSITION:
|
||||
win32_display->event_record->in_ime_composition = FALSE;
|
||||
break;
|
||||
case WM_IME_COMPOSITION:
|
||||
{
|
||||
BYTE key_state[256];
|
||||
wchar_t wbuf[100];
|
||||
int ccount = 0;
|
||||
HIMC himc;
|
||||
int i;
|
||||
|
||||
/* On Win2k WM_IME_CHAR doesn't work correctly for non-Unicode
|
||||
* applications. Thus, handle WM_IME_COMPOSITION with
|
||||
* GCS_RESULTSTR instead, fetch the Unicode chars from the IME
|
||||
* with ImmGetCompositionStringW().
|
||||
*
|
||||
* See for instance
|
||||
* http://groups.google.com/groups?selm=natX5.57%24g77.19788%40nntp2.onemain.com
|
||||
* and
|
||||
* http://groups.google.com/groups?selm=u2XfrXw5BHA.1628%40tkmsftngp02
|
||||
* for comments by other people that seems to have the same
|
||||
* experience. WM_IME_CHAR just gives question marks, apparently
|
||||
* because of going through some conversion to the current code
|
||||
* page.
|
||||
*
|
||||
* WM_IME_CHAR might work on NT4 or Win9x with ActiveIMM, but
|
||||
* use WM_IME_COMPOSITION there, too, to simplify the code.
|
||||
*/
|
||||
GDK_NOTE (EVENTS, g_print (" %#lx", (long) msg->lParam));
|
||||
|
||||
if (!(msg->lParam & GCS_RESULTSTR))
|
||||
break;
|
||||
|
||||
if (GDK_SURFACE_DESTROYED (surface))
|
||||
break;
|
||||
|
||||
himc = ImmGetContext (msg->hwnd);
|
||||
ccount = ImmGetCompositionStringW (himc, GCS_RESULTSTR,
|
||||
wbuf, sizeof (wbuf));
|
||||
ImmReleaseContext (msg->hwnd, himc);
|
||||
|
||||
ccount /= 2;
|
||||
|
||||
API_CALL (GetKeyboardState, (key_state));
|
||||
|
||||
for (i = 0; i < ccount; i++)
|
||||
{
|
||||
GdkTranslatedKey translated;
|
||||
|
||||
/* Build a key press event */
|
||||
translated.keyval = gdk_unicode_to_keyval (wbuf[i]);
|
||||
translated.consumed = 0;
|
||||
translated.layout = get_active_group (display);
|
||||
translated.level = 0;
|
||||
event = gdk_key_event_new (GDK_KEY_PRESS,
|
||||
surface,
|
||||
win32_display->device_manager->core_keyboard,
|
||||
_gdk_win32_get_next_tick (msg->time),
|
||||
0,
|
||||
build_key_event_state (display, key_state),
|
||||
FALSE,
|
||||
&translated,
|
||||
&translated,
|
||||
NULL);
|
||||
|
||||
_gdk_win32_append_event (event);
|
||||
|
||||
/* Build a key release event. */
|
||||
event = gdk_key_event_new (GDK_KEY_RELEASE,
|
||||
surface,
|
||||
win32_display->device_manager->core_keyboard,
|
||||
_gdk_win32_get_next_tick (msg->time),
|
||||
0,
|
||||
build_key_event_state (display, key_state),
|
||||
FALSE,
|
||||
&translated,
|
||||
&translated,
|
||||
NULL);
|
||||
|
||||
_gdk_win32_append_event (event);
|
||||
}
|
||||
|
||||
return_val = TRUE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
g_warning ("Maybe this was reached because this is not a keyboard-related event");
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
return return_val;
|
||||
}
|
||||
|
||||
|
||||
#define GDK_ANY_BUTTON_MASK (GDK_BUTTON1_MASK | \
|
||||
GDK_BUTTON2_MASK | \
|
||||
GDK_BUTTON3_MASK | \
|
||||
@@ -1732,7 +2093,6 @@ gdk_event_translate (MSG *msg,
|
||||
POINT point;
|
||||
MINMAXINFO *mmi;
|
||||
HWND hwnd;
|
||||
HIMC himc;
|
||||
WINDOWPOS *hwndpos;
|
||||
gboolean ignore_leave;
|
||||
|
||||
@@ -1754,8 +2114,7 @@ gdk_event_translate (MSG *msg,
|
||||
int button;
|
||||
|
||||
gboolean return_val = FALSE;
|
||||
|
||||
int i;
|
||||
gboolean goto_done = FALSE;
|
||||
|
||||
display = gdk_display_get_default ();
|
||||
win32_display = GDK_WIN32_DISPLAY (display);
|
||||
@@ -1811,346 +2170,19 @@ gdk_event_translate (MSG *msg,
|
||||
|
||||
switch (msg->message)
|
||||
{
|
||||
/* keyboard inpout related events (including IME events) */
|
||||
case WM_INPUTLANGCHANGE:
|
||||
{
|
||||
GdkWin32Keymap *win32_keymap;
|
||||
GdkTranslatedKey translated;
|
||||
HKL input_locale;
|
||||
|
||||
win32_keymap = GDK_WIN32_KEYMAP (gdk_display_get_keymap (display));
|
||||
|
||||
input_locale = (HKL) msg->lParam;
|
||||
gdk_win32_display_set_input_locale (win32_display, input_locale);
|
||||
_gdk_win32_keymap_set_active_layout (win32_keymap, input_locale);
|
||||
gdk_win32_display_increment_keymap_serial (win32_display);
|
||||
GDK_NOTE (EVENTS,
|
||||
g_print (" cs:%lu hkl:%p%s",
|
||||
(gulong) msg->wParam,
|
||||
(gpointer) msg->lParam,
|
||||
gdk_win32_display_input_locale_is_ime (win32_display) ? " (IME)" : ""));
|
||||
gdk_display_setting_changed (display, "gtk-im-module");
|
||||
|
||||
/* Generate a dummy key event to "nudge" IMContext */
|
||||
translated.keyval = GDK_KEY_VoidSymbol;
|
||||
translated.consumed = 0;
|
||||
translated.layout = 0;
|
||||
translated.level = 0;
|
||||
event = gdk_key_event_new (GDK_KEY_PRESS,
|
||||
surface,
|
||||
win32_display->device_manager->core_keyboard,
|
||||
_gdk_win32_get_next_tick (msg->time),
|
||||
0,
|
||||
0,
|
||||
FALSE,
|
||||
&translated,
|
||||
&translated,
|
||||
NULL);
|
||||
_gdk_win32_append_event (event);
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_SYSKEYUP:
|
||||
case WM_SYSKEYDOWN:
|
||||
GDK_NOTE (EVENTS,
|
||||
g_print (" %s ch:%.02x %s",
|
||||
_gdk_win32_key_to_string (msg->lParam),
|
||||
(int) msg->wParam,
|
||||
decode_key_lparam (msg->lParam)));
|
||||
|
||||
/* If posted without us having keyboard focus, ignore */
|
||||
if ((msg->wParam != VK_F10 && msg->wParam != VK_MENU) &&
|
||||
!(HIWORD (msg->lParam) & KF_ALTDOWN))
|
||||
break;
|
||||
|
||||
/* Let the system handle Alt-Tab, Alt-Space and Alt-F4 unless
|
||||
* the keyboard is grabbed.
|
||||
*/
|
||||
if (!keyboard_grab &&
|
||||
(msg->wParam == VK_TAB ||
|
||||
msg->wParam == VK_SPACE ||
|
||||
msg->wParam == VK_F4))
|
||||
break;
|
||||
|
||||
/* Jump to code in common with WM_KEYUP and WM_KEYDOWN */
|
||||
goto keyup_or_down;
|
||||
|
||||
case WM_KEYUP:
|
||||
case WM_KEYDOWN:
|
||||
GDK_NOTE (EVENTS,
|
||||
g_print (" %s ch:%.02x %s",
|
||||
_gdk_win32_key_to_string (msg->lParam),
|
||||
(int) msg->wParam,
|
||||
decode_key_lparam (msg->lParam)));
|
||||
|
||||
keyup_or_down:
|
||||
{
|
||||
GdkWin32Keymap *win32_keymap;
|
||||
GdkModifierType state;
|
||||
guint keyval;
|
||||
guint16 keycode;
|
||||
guint8 group;
|
||||
gboolean is_modifier;
|
||||
GdkTranslatedKey translated;
|
||||
GdkTranslatedKey no_lock;
|
||||
BYTE key_state[256];
|
||||
GArray *translation;
|
||||
MSG msg2;
|
||||
int level = 0;
|
||||
int effective_group = 0;
|
||||
GdkModifierType consumed = 0;
|
||||
char *composed = NULL;
|
||||
|
||||
/* Ignore key messages intended for the IME */
|
||||
if (msg->wParam == VK_PROCESSKEY || win32_display->event_record->in_ime_composition)
|
||||
break;
|
||||
|
||||
/* Ignore autorepeats on modifiers */
|
||||
if (msg->message == WM_KEYDOWN &&
|
||||
(msg->wParam == VK_MENU ||
|
||||
msg->wParam == VK_CONTROL ||
|
||||
msg->wParam == VK_SHIFT) &&
|
||||
((HIWORD(msg->lParam) & KF_REPEAT) >= 1))
|
||||
break;
|
||||
|
||||
if (GDK_SURFACE_DESTROYED (surface))
|
||||
break;
|
||||
|
||||
win32_keymap = GDK_WIN32_KEYMAP (gdk_display_get_keymap (display));
|
||||
impl = GDK_WIN32_SURFACE (surface);
|
||||
|
||||
API_CALL (GetKeyboardState, (key_state));
|
||||
|
||||
keyval = GDK_KEY_VoidSymbol;
|
||||
keycode = msg->wParam;
|
||||
|
||||
/* Get the WinAPI translation of the WM_KEY messages to characters.
|
||||
|
||||
The WM_CHAR messages are generated by a previous call to TranslateMessage() and always
|
||||
follow directly after the corresponding WM_KEY* messages.
|
||||
There could be 0 or more WM_CHAR messages following (for example dead keys don't generate
|
||||
WM_CHAR messages - they generate WM_DEAD_CHAR instead, but we are not interested in those
|
||||
messages). */
|
||||
|
||||
translation = g_array_sized_new (FALSE, FALSE, sizeof (gunichar2), 2);
|
||||
while (PeekMessageW (&msg2, msg->hwnd, 0, 0, 0) && (msg2.message == WM_CHAR || msg2.message == WM_SYSCHAR))
|
||||
{
|
||||
/* The character is encoded in WPARAM as UTF-16. */
|
||||
gunichar2 c = msg2.wParam;
|
||||
|
||||
/* Append character to translation string. */
|
||||
g_array_append_val (translation, c);
|
||||
|
||||
/* Remove message from queue */
|
||||
GetMessageW (&msg2, msg->hwnd, 0, 0);
|
||||
}
|
||||
|
||||
if (translation->len > 0)
|
||||
composed = g_utf16_to_utf8 ((gunichar2*)translation->data,
|
||||
translation->len, NULL, NULL, NULL);
|
||||
|
||||
g_array_unref (translation);
|
||||
translation = NULL;
|
||||
|
||||
/* Ignore control sequences like Backspace */
|
||||
if (composed && g_unichar_iscntrl (g_utf8_get_char (composed)))
|
||||
g_clear_pointer (&composed, g_free);
|
||||
|
||||
if (HIWORD (msg->lParam) & KF_EXTENDED)
|
||||
{
|
||||
switch (msg->wParam)
|
||||
{
|
||||
case VK_CONTROL:
|
||||
keycode = VK_RCONTROL;
|
||||
break;
|
||||
case VK_SHIFT: /* Actually, KF_EXTENDED is not set
|
||||
* for the right shift key.
|
||||
*/
|
||||
keycode = VK_RSHIFT;
|
||||
break;
|
||||
case VK_MENU:
|
||||
keycode = VK_RMENU;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (msg->wParam == VK_SHIFT &&
|
||||
LOBYTE (HIWORD (msg->lParam)) == _gdk_win32_keymap_get_rshift_scancode (win32_keymap))
|
||||
keycode = VK_RSHIFT;
|
||||
|
||||
is_modifier = (msg->wParam == VK_CONTROL ||
|
||||
msg->wParam == VK_SHIFT ||
|
||||
msg->wParam == VK_MENU);
|
||||
|
||||
state = build_key_event_state (display, key_state);
|
||||
group = get_active_group (display);
|
||||
|
||||
gdk_keymap_translate_keyboard_state ((GdkKeymap*) win32_keymap, keycode, state, group,
|
||||
&keyval, &effective_group, &level, &consumed);
|
||||
translated.keyval = keyval;
|
||||
translated.consumed = consumed;
|
||||
translated.layout = effective_group;
|
||||
translated.level = level;
|
||||
|
||||
gdk_keymap_translate_keyboard_state ((GdkKeymap*) win32_keymap, keycode,
|
||||
state & ~GDK_LOCK_MASK, group, &keyval,
|
||||
&effective_group, &level, &consumed);
|
||||
no_lock.keyval = keyval;
|
||||
no_lock.consumed = consumed;
|
||||
no_lock.layout = effective_group;
|
||||
no_lock.level = level;
|
||||
|
||||
/* Only one release key event is fired when both shift keys are pressed together
|
||||
and then released. In order to send the missing event, press events for shift
|
||||
keys are recorded and sent together when the release event occurs.
|
||||
Other modifiers (e.g. ctrl, alt) don't have this problem. */
|
||||
if (msg->message == WM_KEYDOWN && msg->wParam == VK_SHIFT)
|
||||
{
|
||||
int pressed_shift = msg->lParam & 0xffffff; /* mask shift modifier */
|
||||
if (win32_display->event_record->both_shift_pressed[0] == 0)
|
||||
win32_display->event_record->both_shift_pressed[0] = pressed_shift;
|
||||
else if (win32_display->event_record->both_shift_pressed[0] != pressed_shift)
|
||||
win32_display->event_record->both_shift_pressed[1] = pressed_shift;
|
||||
}
|
||||
|
||||
if (msg->message == WM_KEYUP && msg->wParam == VK_SHIFT)
|
||||
{
|
||||
if (win32_display->event_record->both_shift_pressed[0] != 0 &&
|
||||
win32_display->event_record->both_shift_pressed[1] != 0)
|
||||
{
|
||||
int tmp_retval;
|
||||
MSG fake_release = *msg;
|
||||
int pressed_shift = msg->lParam & 0xffffff;
|
||||
|
||||
if (win32_display->event_record->both_shift_pressed[0] == pressed_shift)
|
||||
fake_release.lParam = win32_display->event_record->both_shift_pressed[1];
|
||||
else
|
||||
fake_release.lParam = win32_display->event_record->both_shift_pressed[0];
|
||||
|
||||
win32_display->event_record->both_shift_pressed[0] = win32_display->event_record->both_shift_pressed[1] = 0;
|
||||
gdk_event_translate (&fake_release, &tmp_retval);
|
||||
}
|
||||
win32_display->event_record->both_shift_pressed[0] = win32_display->event_record->both_shift_pressed[1] = 0;
|
||||
}
|
||||
|
||||
/* Reset ALT_MASK if it is the Alt key itself */
|
||||
if (msg->wParam == VK_MENU)
|
||||
state &= ~GDK_ALT_MASK;
|
||||
|
||||
event = gdk_key_event_new ((msg->message == WM_KEYDOWN || msg->message == WM_SYSKEYDOWN)
|
||||
? GDK_KEY_PRESS
|
||||
: GDK_KEY_RELEASE,
|
||||
surface,
|
||||
win32_display->device_manager->core_keyboard,
|
||||
_gdk_win32_get_next_tick (msg->time),
|
||||
keycode,
|
||||
state,
|
||||
is_modifier,
|
||||
&translated,
|
||||
&no_lock,
|
||||
composed);
|
||||
|
||||
_gdk_win32_append_event (event);
|
||||
|
||||
g_free (composed);
|
||||
return_val = TRUE;
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_SYSCHAR:
|
||||
if (msg->wParam != VK_SPACE)
|
||||
{
|
||||
/* To prevent beeps, don't let DefWindowProcW() be called */
|
||||
return_val = TRUE;
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_IME_STARTCOMPOSITION:
|
||||
win32_display->event_record->in_ime_composition = TRUE;
|
||||
break;
|
||||
|
||||
case WM_IME_ENDCOMPOSITION:
|
||||
win32_display->event_record->in_ime_composition = FALSE;
|
||||
break;
|
||||
|
||||
case WM_IME_COMPOSITION:
|
||||
{
|
||||
BYTE key_state[256];
|
||||
wchar_t wbuf[100];
|
||||
int ccount = 0;
|
||||
|
||||
/* On Win2k WM_IME_CHAR doesn't work correctly for non-Unicode
|
||||
* applications. Thus, handle WM_IME_COMPOSITION with
|
||||
* GCS_RESULTSTR instead, fetch the Unicode chars from the IME
|
||||
* with ImmGetCompositionStringW().
|
||||
*
|
||||
* See for instance
|
||||
* http://groups.google.com/groups?selm=natX5.57%24g77.19788%40nntp2.onemain.com
|
||||
* and
|
||||
* http://groups.google.com/groups?selm=u2XfrXw5BHA.1628%40tkmsftngp02
|
||||
* for comments by other people that seems to have the same
|
||||
* experience. WM_IME_CHAR just gives question marks, apparently
|
||||
* because of going through some conversion to the current code
|
||||
* page.
|
||||
*
|
||||
* WM_IME_CHAR might work on NT4 or Win9x with ActiveIMM, but
|
||||
* use WM_IME_COMPOSITION there, too, to simplify the code.
|
||||
*/
|
||||
GDK_NOTE (EVENTS, g_print (" %#lx", (long) msg->lParam));
|
||||
|
||||
if (!(msg->lParam & GCS_RESULTSTR))
|
||||
break;
|
||||
|
||||
if (GDK_SURFACE_DESTROYED (surface))
|
||||
break;
|
||||
|
||||
himc = ImmGetContext (msg->hwnd);
|
||||
ccount = ImmGetCompositionStringW (himc, GCS_RESULTSTR,
|
||||
wbuf, sizeof (wbuf));
|
||||
ImmReleaseContext (msg->hwnd, himc);
|
||||
|
||||
ccount /= 2;
|
||||
|
||||
API_CALL (GetKeyboardState, (key_state));
|
||||
|
||||
for (i = 0; i < ccount; i++)
|
||||
{
|
||||
GdkTranslatedKey translated;
|
||||
|
||||
/* Build a key press event */
|
||||
translated.keyval = gdk_unicode_to_keyval (wbuf[i]);
|
||||
translated.consumed = 0;
|
||||
translated.layout = get_active_group (display);
|
||||
translated.level = 0;
|
||||
event = gdk_key_event_new (GDK_KEY_PRESS,
|
||||
surface,
|
||||
win32_display->device_manager->core_keyboard,
|
||||
_gdk_win32_get_next_tick (msg->time),
|
||||
0,
|
||||
build_key_event_state (display, key_state),
|
||||
FALSE,
|
||||
&translated,
|
||||
&translated,
|
||||
NULL);
|
||||
|
||||
_gdk_win32_append_event (event);
|
||||
|
||||
/* Build a key release event. */
|
||||
event = gdk_key_event_new (GDK_KEY_RELEASE,
|
||||
surface,
|
||||
win32_display->device_manager->core_keyboard,
|
||||
_gdk_win32_get_next_tick (msg->time),
|
||||
0,
|
||||
build_key_event_state (display, key_state),
|
||||
FALSE,
|
||||
&translated,
|
||||
&translated,
|
||||
NULL);
|
||||
|
||||
_gdk_win32_append_event (event);
|
||||
}
|
||||
|
||||
return_val = TRUE;
|
||||
}
|
||||
return_val = handle_keyboard_event (display, surface, msg, ret_valp, &goto_done);
|
||||
if (goto_done)
|
||||
goto done;
|
||||
break;
|
||||
|
||||
case WM_LBUTTONDOWN:
|
||||
|
Reference in New Issue
Block a user