forked from AuroraMiddleware/gtk
Merge branch 'win32-native-input' into 'gtk-3-24'
Use native Windows API for converting keystrokes to characters See merge request GNOME/gtk!991
This commit is contained in:
commit
522e5d4fa5
@ -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;
|
||||
}
|
||||
}
|
@ -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,
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
g_return_val_if_fail (gdk_event_is_allocated ((GdkEvent*)event), FALSE);
|
||||
|
||||
event_priv = (GdkEventPrivate*) event;
|
||||
if (event_priv->translation_len == 0)
|
||||
return FALSE;
|
||||
|
||||
if (!GDK_IS_WINDOW (context_ime->client_window))
|
||||
return FALSE;
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
return retval;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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[] = {
|
||||
|
Loading…
Reference in New Issue
Block a user