summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChun-wei Fan <fanc999@yahoo.com.tw>2020-07-24 02:27:41 +0000
committerChun-wei Fan <fanc999@yahoo.com.tw>2020-07-24 02:27:41 +0000
commit522e5d4fa55b39dbd4397ed77370dc023db92b4e (patch)
tree670dd7819a52207f5a2b9b6506d50f89da036654
parent63a0e7664671dbdc7e897085bc0f3050739a4e88 (diff)
parent5b818642111231c7f22e5d4d2bf60b449ec69e64 (diff)
downloadgtk+-522e5d4fa55b39dbd4397ed77370dc023db92b4e.tar.gz
Merge branch 'win32-native-input' into 'gtk-3-24'
Use native Windows API for converting keystrokes to characters See merge request GNOME/gtk!991
-rw-r--r--gdk/gdkevents.c12
-rw-r--r--gdk/gdkinternals.h9
-rw-r--r--gdk/win32/gdkevents-win32.c100
-rw-r--r--gdk/win32/gdkwindow-win32.h8
-rw-r--r--modules/input/gtkimcontextime.c121
-rw-r--r--modules/input/imime.c2
6 files changed, 71 insertions, 181 deletions
diff --git a/gdk/gdkevents.c b/gdk/gdkevents.c
index b4c4c01986..12af9ccb96 100644
--- a/gdk/gdkevents.c
+++ b/gdk/gdkevents.c
@@ -585,7 +585,7 @@ gdk_event_new (GdkEventType type)
return new_event;
}
-static gboolean
+gboolean
gdk_event_is_allocated (const GdkEvent *event)
{
if (event_hash)
@@ -663,6 +663,11 @@ gdk_event_copy (const GdkEvent *event)
new_private->source_device = private->source_device ? g_object_ref (private->source_device) : NULL;
new_private->seat = private->seat;
new_private->tool = private->tool;
+
+#ifdef GDK_WINDOWING_WIN32
+ new_private->translation_len = private->translation_len;
+ new_private->translation = g_memdup (private->translation, private->translation_len * sizeof (private->translation[0]));
+#endif
}
switch (event->any.type)
@@ -767,6 +772,9 @@ gdk_event_free (GdkEvent *event)
private = (GdkEventPrivate *) event;
g_clear_object (&private->device);
g_clear_object (&private->source_device);
+#ifdef GDK_WINDOWING_WIN32
+ g_free (private->translation);
+#endif
}
switch (event->any.type)
@@ -2564,4 +2572,4 @@ gdk_event_get_scancode (GdkEvent *event)
private = (GdkEventPrivate *) event;
return private->key_scancode;
-}
+} \ No newline at end of file
diff --git a/gdk/gdkinternals.h b/gdk/gdkinternals.h
index 50ebdaa235..e2c1d10c9c 100644
--- a/gdk/gdkinternals.h
+++ b/gdk/gdkinternals.h
@@ -192,6 +192,11 @@ struct _GdkEventPrivate
GdkSeat *seat;
GdkDeviceTool *tool;
guint16 key_scancode;
+
+#ifdef GDK_WINDOWING_WIN32
+ gunichar2 *translation;
+ guint translation_len;
+#endif
};
typedef struct _GdkWindowPaint GdkWindowPaint;
@@ -413,6 +418,10 @@ void gdk_event_set_scancode (GdkEvent *event,
void gdk_event_set_seat (GdkEvent *event,
GdkSeat *seat);
+/* The IME IM module needs this symbol exported. */
+_GDK_EXTERN
+gboolean gdk_event_is_allocated (const GdkEvent *event);
+
void _gdk_event_emit (GdkEvent *event);
GList* _gdk_event_queue_find_first (GdkDisplay *display);
void _gdk_event_queue_remove_link (GdkDisplay *display,
diff --git a/gdk/win32/gdkevents-win32.c b/gdk/win32/gdkevents-win32.c
index 7aef277c27..327d288bc7 100644
--- a/gdk/win32/gdkevents-win32.c
+++ b/gdk/win32/gdkevents-win32.c
@@ -2556,31 +2556,6 @@ gdk_event_translate (MSG *msg,
API_CALL (GetKeyboardState, (key_state));
- ccount = 0;
-
- if (msg->wParam == VK_PACKET)
- {
- ccount = ToUnicode (VK_PACKET, HIWORD (msg->lParam), key_state, wbuf, 1, 0);
- if (ccount == 1)
- {
- if (wbuf[0] >= 0xD800 && wbuf[0] < 0xDC00)
- {
- if (msg->message == WM_KEYDOWN)
- impl->leading_surrogate_keydown = wbuf[0];
- else
- impl->leading_surrogate_keyup = wbuf[0];
-
- /* don't emit an event */
- return_val = TRUE;
- break;
- }
- else
- {
- /* wait until an event is created */;
- }
- }
- }
-
event = gdk_event_new ((msg->message == WM_KEYDOWN ||
msg->message == WM_SYSKEYDOWN) ?
GDK_KEY_PRESS : GDK_KEY_RELEASE);
@@ -2595,6 +2570,39 @@ gdk_event_translate (MSG *msg,
gdk_event_set_device (event, device_manager_win32->core_keyboard);
gdk_event_set_source_device (event, device_manager_win32->system_keyboard);
gdk_event_set_seat (event, gdk_device_get_seat (device_manager_win32->core_keyboard));
+
+ /* 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). */
+
+ if (gdk_event_is_allocated (event)) /* Should always be true */
+ {
+ GdkEventPrivate *event_priv = (GdkEventPrivate*) event;
+
+ MSG msg2;
+ 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;
+
+ /* Ignore control sequences like Backspace */
+ if (!g_unichar_iscntrl(c))
+ {
+ /* Append character to translation string. */
+ event_priv->translation_len ++;
+ event_priv->translation = g_realloc (event_priv->translation, event_priv->translation_len * sizeof (event_priv->translation[0]));
+ event_priv->translation[event_priv->translation_len - 1] = c;
+ }
+
+ /* Remove message from queue */
+ GetMessageW (&msg2, msg->hwnd, 0, 0);
+ }
+ }
+
if (HIWORD (msg->lParam) & KF_EXTENDED)
{
switch (msg->wParam)
@@ -2623,42 +2631,12 @@ gdk_event_translate (MSG *msg,
build_key_event_state (event, key_state);
- if (msg->wParam == VK_PACKET && ccount == 1)
- {
- if (wbuf[0] >= 0xD800 && wbuf[0] < 0xDC00)
- {
- g_assert_not_reached ();
- }
- else if (wbuf[0] >= 0xDC00 && wbuf[0] < 0xE000)
- {
- wchar_t leading;
-
- if (msg->message == WM_KEYDOWN)
- leading = impl->leading_surrogate_keydown;
- else
- leading = impl->leading_surrogate_keyup;
-
- event->key.keyval = gdk_unicode_to_keyval ((leading - 0xD800) * 0x400 + wbuf[0] - 0xDC00 + 0x10000);
- }
- else
- {
- event->key.keyval = gdk_unicode_to_keyval (wbuf[0]);
- }
- }
- else
- {
- gdk_keymap_translate_keyboard_state (_gdk_win32_display_get_keymap (display),
- event->key.hardware_keycode,
- event->key.state,
- event->key.group,
- &event->key.keyval,
- NULL, NULL, NULL);
- }
-
- if (msg->message == WM_KEYDOWN)
- impl->leading_surrogate_keydown = 0;
- else
- impl->leading_surrogate_keyup = 0;
+ gdk_keymap_translate_keyboard_state (_gdk_win32_display_get_keymap (display),
+ event->key.hardware_keycode,
+ event->key.state,
+ event->key.group,
+ &event->key.keyval,
+ NULL, NULL, NULL);
fill_key_event_string (event);
diff --git a/gdk/win32/gdkwindow-win32.h b/gdk/win32/gdkwindow-win32.h
index e1ef92096d..23f5b8d86c 100644
--- a/gdk/win32/gdkwindow-win32.h
+++ b/gdk/win32/gdkwindow-win32.h
@@ -240,14 +240,6 @@ struct _GdkWindowImplWin32
HICON hicon_big;
HICON hicon_small;
- /* When VK_PACKET sends us a leading surrogate, it's stashed here.
- * Later, when another VK_PACKET sends a tailing surrogate, we make up
- * a full unicode character from them, or discard the leading surrogate,
- * if the next key is not a tailing surrogate.
- */
- wchar_t leading_surrogate_keydown;
- wchar_t leading_surrogate_keyup;
-
/* Window size hints */
gint hint_flags;
GdkGeometry hints;
diff --git a/modules/input/gtkimcontextime.c b/modules/input/gtkimcontextime.c
index 3ca7b5e661..8973b70113 100644
--- a/modules/input/gtkimcontextime.c
+++ b/modules/input/gtkimcontextime.c
@@ -27,13 +27,16 @@
#undef GTK_DISABLE_DEPRECATED
#endif
+#include "config.h"
#include "gtkimcontextime.h"
#include "imm-extra.h"
#include "gdk/gdkkeysyms-compat.h"
#include "gdk/win32/gdkwin32.h"
+#include "gdk/win32/gdkprivate-win32.h"
#include "gdk/gdkkeysyms.h"
+#include "gdk/gdkinternals.h"
#include <pango/pango.h>
@@ -59,10 +62,6 @@ typedef enum {
GTK_WIN32_IME_FOCUS_BEHAVIOR_FOLLOW,
} GtkWin32IMEFocusBehavior;
-#define IS_DEAD_KEY(k) \
- ((k) >= GDK_dead_grave && (k) <= (GDK_dead_dasia+1))
-
-
struct _GtkIMContextIMEPrivate
{
/* When pretend_empty_preedit is set to TRUE,
@@ -80,7 +79,6 @@ struct _GtkIMContextIMEPrivate
* https://gitlab.gnome.org/GNOME/gtk/commit/c255ba68fc2c918dd84da48a472e7973d3c00b03
*/
gboolean pretend_empty_preedit;
- guint32 dead_key_keyval;
GtkWin32IMEFocusBehavior focus_behavior;
};
@@ -318,125 +316,30 @@ gtk_im_context_ime_set_client_window (GtkIMContext *context,
g_return_if_fail (GDK_IS_WINDOW (context_ime->toplevel));
}
-static gunichar
-_gtk_im_context_ime_dead_key_unichar (guint keyval,
- gboolean spacing)
-{
- switch (keyval)
- {
-#define CASE(keysym, unicode, spacing_unicode) \
- case GDK_dead_##keysym: return (spacing) ? spacing_unicode : unicode;
-
- CASE (grave, 0x0300, 0x0060);
- CASE (acute, 0x0301, 0x00b4);
- CASE (circumflex, 0x0302, 0x005e);
- CASE (tilde, 0x0303, 0x007e); /* Also used with perispomeni, 0x342. */
- CASE (macron, 0x0304, 0x00af);
- CASE (breve, 0x0306, 0x02d8);
- CASE (abovedot, 0x0307, 0x02d9);
- CASE (diaeresis, 0x0308, 0x00a8);
- CASE (hook, 0x0309, 0);
- CASE (abovering, 0x030A, 0x02da);
- CASE (doubleacute, 0x030B, 0x2dd);
- CASE (caron, 0x030C, 0x02c7);
- CASE (abovecomma, 0x0313, 0); /* Equivalent to psili */
- CASE (abovereversedcomma, 0x0314, 0); /* Equivalent to dasia */
- CASE (horn, 0x031B, 0); /* Legacy use for psili, 0x313 (or 0x343). */
- CASE (belowdot, 0x0323, 0);
- CASE (cedilla, 0x0327, 0x00b8);
- CASE (ogonek, 0x0328, 0); /* Legacy use for dasia, 0x314.*/
- CASE (iota, 0x0345, 0);
-
-#undef CASE
- default:
- return 0;
- }
-}
-
-static void
-_gtk_im_context_ime_commit_unichar (GtkIMContextIME *context_ime,
- gunichar c)
-{
- gchar utf8[10];
- int len;
-
- if (context_ime->priv->dead_key_keyval != 0)
- {
- gunichar combining;
-
- combining =
- _gtk_im_context_ime_dead_key_unichar (context_ime->priv->dead_key_keyval,
- FALSE);
- g_unichar_compose (c, combining, &c);
- }
-
- len = g_unichar_to_utf8 (c, utf8);
- utf8[len] = 0;
-
- g_signal_emit_by_name (context_ime, "commit", utf8);
- context_ime->priv->dead_key_keyval = 0;
-}
-
static gboolean
gtk_im_context_ime_filter_keypress (GtkIMContext *context,
GdkEventKey *event)
{
GtkIMContextIME *context_ime;
- gboolean retval = FALSE;
- guint32 c;
+ GdkEventPrivate *event_priv;
+ gchar *utf8;
g_return_val_if_fail (GTK_IS_IM_CONTEXT_IME (context), FALSE);
g_return_val_if_fail (event, FALSE);
- if (event->type == GDK_KEY_RELEASE)
- return FALSE;
-
- if (event->state & GDK_CONTROL_MASK)
- return FALSE;
-
context_ime = GTK_IM_CONTEXT_IME (context);
- if (!context_ime->focus)
- return FALSE;
+ g_return_val_if_fail (gdk_event_is_allocated ((GdkEvent*)event), FALSE);
- if (!GDK_IS_WINDOW (context_ime->client_window))
+ event_priv = (GdkEventPrivate*) event;
+ if (event_priv->translation_len == 0)
return FALSE;
- if (event->keyval == GDK_space &&
- context_ime->priv->dead_key_keyval != 0)
- {
- c = _gtk_im_context_ime_dead_key_unichar (context_ime->priv->dead_key_keyval, TRUE);
- context_ime->priv->dead_key_keyval = 0;
- _gtk_im_context_ime_commit_unichar (context_ime, c);
- return TRUE;
- }
-
- c = gdk_keyval_to_unicode (event->keyval);
-
- if (c)
- {
- _gtk_im_context_ime_commit_unichar (context_ime, c);
- retval = TRUE;
- }
- else if (IS_DEAD_KEY (event->keyval))
- {
- gunichar dead_key;
-
- dead_key = _gtk_im_context_ime_dead_key_unichar (event->keyval, FALSE);
-
- /* Emulate double input of dead keys */
- if (dead_key && event->keyval == context_ime->priv->dead_key_keyval)
- {
- c = _gtk_im_context_ime_dead_key_unichar (context_ime->priv->dead_key_keyval, TRUE);
- context_ime->priv->dead_key_keyval = 0;
- _gtk_im_context_ime_commit_unichar (context_ime, c);
- _gtk_im_context_ime_commit_unichar (context_ime, c);
- }
- else
- context_ime->priv->dead_key_keyval = event->keyval;
- }
+ utf8 = g_utf16_to_utf8 (event_priv->translation, event_priv->translation_len, NULL, NULL, NULL);
+ g_signal_emit_by_name (context_ime, "commit", utf8);
+ g_free (utf8);
- return retval;
+ return TRUE;
}
diff --git a/modules/input/imime.c b/modules/input/imime.c
index d2943cf9cd..dea7ae12c7 100644
--- a/modules/input/imime.c
+++ b/modules/input/imime.c
@@ -30,7 +30,7 @@ static const GtkIMContextInfo ime_info = {
NC_("input method menu", "Windows IME"),
GETTEXT_PACKAGE,
"",
- "ja:ko:zh",
+ "*",
};
static const GtkIMContextInfo *info_list[] = {