mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2025-01-12 13:30:19 +00:00
Merge branch 'forward-port-mr-991-to-gtk4-2' into 'main'
Use native Windows API for converting keystrokes to characters Closes #2944 See merge request GNOME/gtk!4986
This commit is contained in:
commit
995f00d23f
@ -262,7 +262,8 @@ _gdk_broadway_events_got_input (GdkDisplay *display,
|
|||||||
message->key.state,
|
message->key.state,
|
||||||
FALSE,
|
FALSE,
|
||||||
&translated,
|
&translated,
|
||||||
&translated);
|
&translated,
|
||||||
|
NULL);
|
||||||
|
|
||||||
node = _gdk_event_queue_append (display, event);
|
node = _gdk_event_queue_append (display, event);
|
||||||
_gdk_windowing_got_event (display, node, event, message->base.serial);
|
_gdk_windowing_got_event (display, node, event, message->base.serial);
|
||||||
|
@ -1517,6 +1517,16 @@ gdk_button_event_get_button (GdkEvent *event)
|
|||||||
* An event related to a key-based device.
|
* An event related to a key-based device.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdk_key_event_finalize (GdkEvent *event)
|
||||||
|
{
|
||||||
|
GdkKeyEvent *self = (GdkKeyEvent *) event;
|
||||||
|
|
||||||
|
g_free (self->compose_sequence);
|
||||||
|
|
||||||
|
GDK_EVENT_SUPER (event)->finalize (event);
|
||||||
|
}
|
||||||
|
|
||||||
static GdkModifierType
|
static GdkModifierType
|
||||||
gdk_key_event_get_state (GdkEvent *event)
|
gdk_key_event_get_state (GdkEvent *event)
|
||||||
{
|
{
|
||||||
@ -1528,7 +1538,7 @@ gdk_key_event_get_state (GdkEvent *event)
|
|||||||
static const GdkEventTypeInfo gdk_key_event_info = {
|
static const GdkEventTypeInfo gdk_key_event_info = {
|
||||||
sizeof (GdkKeyEvent),
|
sizeof (GdkKeyEvent),
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
gdk_key_event_finalize,
|
||||||
gdk_key_event_get_state,
|
gdk_key_event_get_state,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
@ -1552,6 +1562,10 @@ GDK_DEFINE_EVENT_TYPE (GdkKeyEvent, gdk_key_event,
|
|||||||
* @is_modifier: whether the event is a modifiers only event
|
* @is_modifier: whether the event is a modifiers only event
|
||||||
* @translated: the translated key data for the given @state
|
* @translated: the translated key data for the given @state
|
||||||
* @no_lock: the translated key data without the given @state
|
* @no_lock: the translated key data without the given @state
|
||||||
|
* @compose_sequence: (transfer none) (nullable):
|
||||||
|
* The compose sequence string, either partial or only the
|
||||||
|
* final composed string, if that can be determined at event
|
||||||
|
* creation time. Used by selected IM modules.
|
||||||
*
|
*
|
||||||
* Creates a new `GdkKeyEvent`.
|
* Creates a new `GdkKeyEvent`.
|
||||||
*
|
*
|
||||||
@ -1566,7 +1580,8 @@ gdk_key_event_new (GdkEventType type,
|
|||||||
GdkModifierType state,
|
GdkModifierType state,
|
||||||
gboolean is_modifier,
|
gboolean is_modifier,
|
||||||
GdkTranslatedKey *translated,
|
GdkTranslatedKey *translated,
|
||||||
GdkTranslatedKey *no_lock)
|
GdkTranslatedKey *no_lock,
|
||||||
|
char *compose_sequence)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (type == GDK_KEY_PRESS ||
|
g_return_val_if_fail (type == GDK_KEY_PRESS ||
|
||||||
type == GDK_KEY_RELEASE, NULL);
|
type == GDK_KEY_RELEASE, NULL);
|
||||||
@ -1579,6 +1594,7 @@ gdk_key_event_new (GdkEventType type,
|
|||||||
self->key_is_modifier = is_modifier;
|
self->key_is_modifier = is_modifier;
|
||||||
self->translated[0] = *translated;
|
self->translated[0] = *translated;
|
||||||
self->translated[1] = *no_lock;
|
self->translated[1] = *no_lock;
|
||||||
|
self->compose_sequence = g_strdup (compose_sequence);
|
||||||
|
|
||||||
return event;
|
return event;
|
||||||
}
|
}
|
||||||
@ -1609,6 +1625,26 @@ gdk_key_event_get_translated_key (GdkEvent *event,
|
|||||||
return &(self->translated[0]);
|
return &(self->translated[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*< private >
|
||||||
|
* gdk_key_event_get_compose_sequence:
|
||||||
|
* @event: (type GdkKeyEvent): a key event
|
||||||
|
*
|
||||||
|
* Extracts the compose sequence string from a key event.
|
||||||
|
*
|
||||||
|
* Returns: (transfer none): the compose sequence string
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
gdk_key_event_get_compose_sequence (GdkEvent *event)
|
||||||
|
{
|
||||||
|
GdkKeyEvent *self = (GdkKeyEvent *) event;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GDK_IS_EVENT (event), 0);
|
||||||
|
g_return_val_if_fail (GDK_IS_EVENT_TYPE (event, GDK_KEY_PRESS) ||
|
||||||
|
GDK_IS_EVENT_TYPE (event, GDK_KEY_RELEASE), FALSE);
|
||||||
|
|
||||||
|
return self->compose_sequence;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gdk_key_event_get_keyval:
|
* gdk_key_event_get_keyval:
|
||||||
* @event: (type GdkKeyEvent): a key event
|
* @event: (type GdkKeyEvent): a key event
|
||||||
|
@ -259,6 +259,9 @@ typedef struct {
|
|||||||
* @keycode: the raw code of the key that was pressed or released.
|
* @keycode: the raw code of the key that was pressed or released.
|
||||||
* @translated: the result of translating @keycode. First with the full
|
* @translated: the result of translating @keycode. First with the full
|
||||||
* @state, then while ignoring Caps Lock.
|
* @state, then while ignoring Caps Lock.
|
||||||
|
* @compose_sequence: optional string for use by selected IM modules.
|
||||||
|
* Contains either partial compose sequences or the final composed
|
||||||
|
* string of the keystroke sequence.
|
||||||
*
|
*
|
||||||
* Describes a key press or key release event.
|
* Describes a key press or key release event.
|
||||||
*/
|
*/
|
||||||
@ -270,6 +273,7 @@ struct _GdkKeyEvent
|
|||||||
guint32 keycode;
|
guint32 keycode;
|
||||||
gboolean key_is_modifier;
|
gboolean key_is_modifier;
|
||||||
GdkTranslatedKey translated[2];
|
GdkTranslatedKey translated[2];
|
||||||
|
char *compose_sequence;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -470,7 +474,8 @@ GdkEvent * gdk_key_event_new (GdkEventType type,
|
|||||||
GdkModifierType modifiers,
|
GdkModifierType modifiers,
|
||||||
gboolean is_modifier,
|
gboolean is_modifier,
|
||||||
GdkTranslatedKey *translated,
|
GdkTranslatedKey *translated,
|
||||||
GdkTranslatedKey *no_lock);
|
GdkTranslatedKey *no_lock,
|
||||||
|
char *compose_sequence);
|
||||||
|
|
||||||
GdkEvent * gdk_focus_event_new (GdkSurface *surface,
|
GdkEvent * gdk_focus_event_new (GdkSurface *surface,
|
||||||
GdkDevice *device,
|
GdkDevice *device,
|
||||||
@ -597,6 +602,8 @@ GdkEvent * gdk_grab_broken_event_new (GdkSurface *surface,
|
|||||||
GdkTranslatedKey * gdk_key_event_get_translated_key (GdkEvent *event,
|
GdkTranslatedKey * gdk_key_event_get_translated_key (GdkEvent *event,
|
||||||
gboolean no_lock);
|
gboolean no_lock);
|
||||||
|
|
||||||
|
char * gdk_key_event_get_compose_sequence (GdkEvent *event);
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
/* Following flag is set for events on the event queue during
|
/* Following flag is set for events on the event queue during
|
||||||
@ -626,7 +633,6 @@ void _gdk_event_queue_flush (GdkDisplay *display);
|
|||||||
|
|
||||||
double * gdk_event_dup_axes (GdkEvent *event);
|
double * gdk_event_dup_axes (GdkEvent *event);
|
||||||
|
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __GDK_EVENTS_PRIVATE_H__ */
|
#endif /* __GDK_EVENTS_PRIVATE_H__ */
|
||||||
|
@ -431,7 +431,8 @@ fill_key_event (GdkMacosDisplay *display,
|
|||||||
state,
|
state,
|
||||||
is_modifier,
|
is_modifier,
|
||||||
&translated,
|
&translated,
|
||||||
&no_lock);
|
&no_lock,
|
||||||
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GdkEvent *
|
static GdkEvent *
|
||||||
|
@ -944,7 +944,8 @@ _gdk_macos_surface_synthesize_null_key (GdkMacosSurface *self)
|
|||||||
0,
|
0,
|
||||||
FALSE,
|
FALSE,
|
||||||
&translated,
|
&translated,
|
||||||
&no_lock);
|
&no_lock,
|
||||||
|
NULL);
|
||||||
_gdk_event_queue_append (display, event);
|
_gdk_event_queue_append (display, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2205,7 +2205,8 @@ deliver_key_event (GdkWaylandSeat *seat,
|
|||||||
device_get_modifiers (seat->logical_pointer),
|
device_get_modifiers (seat->logical_pointer),
|
||||||
_gdk_wayland_keymap_key_is_modifier (keymap, key),
|
_gdk_wayland_keymap_key_is_modifier (keymap, key),
|
||||||
&translated,
|
&translated,
|
||||||
&no_lock);
|
&no_lock,
|
||||||
|
NULL);
|
||||||
|
|
||||||
_gdk_wayland_display_deliver_event (seat->display, event);
|
_gdk_wayland_display_deliver_event (seat->display, event);
|
||||||
|
|
||||||
|
@ -1857,7 +1857,8 @@ gdk_event_translate (MSG *msg,
|
|||||||
0,
|
0,
|
||||||
FALSE,
|
FALSE,
|
||||||
&translated,
|
&translated,
|
||||||
&translated);
|
&translated,
|
||||||
|
NULL);
|
||||||
_gdk_win32_append_event (event);
|
_gdk_win32_append_event (event);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -1906,8 +1907,12 @@ gdk_event_translate (MSG *msg,
|
|||||||
GdkTranslatedKey translated;
|
GdkTranslatedKey translated;
|
||||||
GdkTranslatedKey no_lock;
|
GdkTranslatedKey no_lock;
|
||||||
BYTE key_state[256];
|
BYTE key_state[256];
|
||||||
wchar_t wbuf[100];
|
GArray *translation;
|
||||||
int ccount = 0;
|
MSG msg2;
|
||||||
|
int level = 0;
|
||||||
|
int effective_group = 0;
|
||||||
|
GdkModifierType consumed = 0;
|
||||||
|
char *composed = NULL;
|
||||||
|
|
||||||
/* Ignore key messages intended for the IME */
|
/* Ignore key messages intended for the IME */
|
||||||
if (msg->wParam == VK_PROCESSKEY || in_ime_composition)
|
if (msg->wParam == VK_PROCESSKEY || in_ime_composition)
|
||||||
@ -1929,34 +1934,41 @@ gdk_event_translate (MSG *msg,
|
|||||||
|
|
||||||
API_CALL (GetKeyboardState, (key_state));
|
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 */;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
keyval = GDK_KEY_VoidSymbol;
|
keyval = GDK_KEY_VoidSymbol;
|
||||||
keycode = msg->wParam;
|
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)
|
if (HIWORD (msg->lParam) & KF_EXTENDED)
|
||||||
{
|
{
|
||||||
switch (msg->wParam)
|
switch (msg->wParam)
|
||||||
@ -1985,61 +1997,20 @@ gdk_event_translate (MSG *msg,
|
|||||||
state = build_key_event_state (key_state);
|
state = build_key_event_state (key_state);
|
||||||
group = get_active_group ();
|
group = get_active_group ();
|
||||||
|
|
||||||
if (msg->wParam == VK_PACKET && ccount == 1)
|
gdk_keymap_translate_keyboard_state ((GdkKeymap*) win32_keymap, keycode, state, group,
|
||||||
{
|
&keyval, &effective_group, &level, &consumed);
|
||||||
if (wbuf[0] >= 0xD800 && wbuf[0] < 0xDC00)
|
translated.keyval = keyval;
|
||||||
{
|
translated.consumed = consumed;
|
||||||
g_assert_not_reached ();
|
translated.layout = effective_group;
|
||||||
}
|
translated.level = level;
|
||||||
else if (wbuf[0] >= 0xDC00 && wbuf[0] < 0xE000)
|
|
||||||
{
|
|
||||||
wchar_t leading;
|
|
||||||
|
|
||||||
if (msg->message == WM_KEYDOWN)
|
gdk_keymap_translate_keyboard_state ((GdkKeymap*) win32_keymap, keycode,
|
||||||
leading = impl->leading_surrogate_keydown;
|
state & ~GDK_LOCK_MASK, group, &keyval,
|
||||||
else
|
&effective_group, &level, &consumed);
|
||||||
leading = impl->leading_surrogate_keyup;
|
no_lock.keyval = keyval;
|
||||||
|
no_lock.consumed = consumed;
|
||||||
keyval = gdk_unicode_to_keyval ((leading - 0xD800) * 0x400 + wbuf[0] - 0xDC00 + 0x10000);
|
no_lock.layout = effective_group;
|
||||||
}
|
no_lock.level = level;
|
||||||
else
|
|
||||||
{
|
|
||||||
keyval = gdk_unicode_to_keyval (wbuf[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
translated.keyval = keyval;
|
|
||||||
translated.consumed = 0;
|
|
||||||
translated.layout = 0;
|
|
||||||
translated.level = 0;
|
|
||||||
|
|
||||||
no_lock = translated;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int level = 0;
|
|
||||||
int effective_group = 0;
|
|
||||||
GdkModifierType consumed = 0;
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (msg->message == WM_KEYDOWN)
|
|
||||||
impl->leading_surrogate_keydown = 0;
|
|
||||||
else
|
|
||||||
impl->leading_surrogate_keyup = 0;
|
|
||||||
|
|
||||||
/* Only one release key event is fired when both shift keys are pressed together
|
/* 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
|
and then released. In order to send the missing event, press events for shift
|
||||||
@ -2087,10 +2058,12 @@ gdk_event_translate (MSG *msg,
|
|||||||
state,
|
state,
|
||||||
is_modifier,
|
is_modifier,
|
||||||
&translated,
|
&translated,
|
||||||
&no_lock);
|
&no_lock,
|
||||||
|
composed);
|
||||||
|
|
||||||
_gdk_win32_append_event (event);
|
_gdk_win32_append_event (event);
|
||||||
|
|
||||||
|
g_free (composed);
|
||||||
return_val = TRUE;
|
return_val = TRUE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -2169,7 +2142,8 @@ gdk_event_translate (MSG *msg,
|
|||||||
build_key_event_state (key_state),
|
build_key_event_state (key_state),
|
||||||
FALSE,
|
FALSE,
|
||||||
&translated,
|
&translated,
|
||||||
&translated);
|
&translated,
|
||||||
|
NULL);
|
||||||
|
|
||||||
_gdk_win32_append_event (event);
|
_gdk_win32_append_event (event);
|
||||||
|
|
||||||
@ -2182,7 +2156,8 @@ gdk_event_translate (MSG *msg,
|
|||||||
build_key_event_state (key_state),
|
build_key_event_state (key_state),
|
||||||
FALSE,
|
FALSE,
|
||||||
&translated,
|
&translated,
|
||||||
&translated);
|
&translated,
|
||||||
|
NULL);
|
||||||
|
|
||||||
_gdk_win32_append_event (event);
|
_gdk_win32_append_event (event);
|
||||||
}
|
}
|
||||||
|
@ -235,14 +235,6 @@ struct _GdkWin32Surface
|
|||||||
/* The cursor that GDK set for this window via GdkDevice */
|
/* The cursor that GDK set for this window via GdkDevice */
|
||||||
GdkWin32HCursor *cursor;
|
GdkWin32HCursor *cursor;
|
||||||
|
|
||||||
/* 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 */
|
/* Window size hints */
|
||||||
int hint_flags;
|
int hint_flags;
|
||||||
GdkGeometry hints;
|
GdkGeometry hints;
|
||||||
|
@ -1595,7 +1595,8 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
|
|||||||
state,
|
state,
|
||||||
gdk_x11_keymap_key_is_modifier (keymap, xev->detail),
|
gdk_x11_keymap_key_is_modifier (keymap, xev->detail),
|
||||||
&translated,
|
&translated,
|
||||||
&no_lock);
|
&no_lock,
|
||||||
|
NULL);
|
||||||
|
|
||||||
if (ev->evtype == XI_KeyPress)
|
if (ev->evtype == XI_KeyPress)
|
||||||
set_user_time (event);
|
set_user_time (event);
|
||||||
|
@ -607,7 +607,8 @@ gtk_im_context_filter_key (GtkIMContext *context,
|
|||||||
state,
|
state,
|
||||||
FALSE, /* FIXME */
|
FALSE, /* FIXME */
|
||||||
&translated,
|
&translated,
|
||||||
&no_lock);
|
&no_lock,
|
||||||
|
NULL);
|
||||||
|
|
||||||
ret = GTK_IM_CONTEXT_GET_CLASS (context)->filter_keypress (context, key);
|
ret = GTK_IM_CONTEXT_GET_CLASS (context)->filter_keypress (context, key);
|
||||||
|
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#include "imm-extra.h"
|
#include "imm-extra.h"
|
||||||
|
|
||||||
#include "gdk/gdkkeysyms.h"
|
#include "gdk/gdkkeysyms.h"
|
||||||
|
#include "gdk/gdkeventsprivate.h"
|
||||||
#include "gdk/win32/gdkwin32.h"
|
#include "gdk/win32/gdkwin32.h"
|
||||||
#include "gtk/gtkimmodule.h"
|
#include "gtk/gtkimmodule.h"
|
||||||
#include "gtk/deprecated/gtkstylecontextprivate.h"
|
#include "gtk/deprecated/gtkstylecontextprivate.h"
|
||||||
@ -61,9 +62,6 @@ typedef enum {
|
|||||||
GTK_WIN32_IME_FOCUS_BEHAVIOR_FOLLOW,
|
GTK_WIN32_IME_FOCUS_BEHAVIOR_FOLLOW,
|
||||||
} GtkWin32IMEFocusBehavior;
|
} GtkWin32IMEFocusBehavior;
|
||||||
|
|
||||||
#define IS_DEAD_KEY(k) \
|
|
||||||
((k) >= GDK_KEY_dead_grave && (k) <= (GDK_KEY_dead_dasia+1))
|
|
||||||
|
|
||||||
struct _GtkIMContextIMEPrivate
|
struct _GtkIMContextIMEPrivate
|
||||||
{
|
{
|
||||||
/* When pretend_empty_preedit is set to TRUE,
|
/* When pretend_empty_preedit is set to TRUE,
|
||||||
@ -81,7 +79,6 @@ struct _GtkIMContextIMEPrivate
|
|||||||
* https://gitlab.gnome.org/GNOME/gtk/commit/c255ba68fc2c918dd84da48a472e7973d3c00b03
|
* https://gitlab.gnome.org/GNOME/gtk/commit/c255ba68fc2c918dd84da48a472e7973d3c00b03
|
||||||
*/
|
*/
|
||||||
gboolean pretend_empty_preedit;
|
gboolean pretend_empty_preedit;
|
||||||
guint32 dead_key_keyval;
|
|
||||||
GtkWin32IMEFocusBehavior focus_behavior;
|
GtkWin32IMEFocusBehavior focus_behavior;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -277,134 +274,26 @@ gtk_im_context_ime_set_client_widget (GtkIMContext *context,
|
|||||||
context_ime->client_surface = surface;
|
context_ime->client_surface = surface;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gunichar
|
|
||||||
_gtk_im_context_ime_dead_key_unichar (guint keyval,
|
|
||||||
gboolean spacing)
|
|
||||||
{
|
|
||||||
switch (keyval)
|
|
||||||
{
|
|
||||||
#define CASE(keysym, unicode, spacing_unicode) \
|
|
||||||
case GDK_KEY_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)
|
|
||||||
{
|
|
||||||
char 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
|
static gboolean
|
||||||
gtk_im_context_ime_filter_keypress (GtkIMContext *context,
|
gtk_im_context_ime_filter_keypress (GtkIMContext *context,
|
||||||
GdkEvent *event)
|
GdkEvent *event)
|
||||||
{
|
{
|
||||||
GtkIMContextIME *context_ime;
|
GtkIMContextIME *context_ime;
|
||||||
gboolean retval = FALSE;
|
char *compose_sequence = NULL;
|
||||||
guint32 c;
|
|
||||||
GdkModifierType state, consumed_modifiers, no_text_input_mask;
|
|
||||||
guint keyval;
|
|
||||||
|
|
||||||
g_return_val_if_fail (GTK_IS_IM_CONTEXT_IME (context), FALSE);
|
g_return_val_if_fail (GTK_IS_IM_CONTEXT_IME (context), FALSE);
|
||||||
g_return_val_if_fail (event, FALSE);
|
g_return_val_if_fail (event, FALSE);
|
||||||
|
|
||||||
if (gdk_event_get_event_type ((GdkEvent *) event) == GDK_KEY_RELEASE)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
no_text_input_mask = GDK_ALT_MASK|GDK_CONTROL_MASK;
|
|
||||||
|
|
||||||
state = gdk_event_get_modifier_state ((GdkEvent *) event);
|
|
||||||
consumed_modifiers = gdk_key_event_get_consumed_modifiers (event);
|
|
||||||
|
|
||||||
if (state & no_text_input_mask & ~consumed_modifiers)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
context_ime = GTK_IM_CONTEXT_IME (context);
|
context_ime = GTK_IM_CONTEXT_IME (context);
|
||||||
|
|
||||||
if (!context_ime->focus)
|
compose_sequence = gdk_key_event_get_compose_sequence (event);
|
||||||
return FALSE;
|
if (compose_sequence)
|
||||||
|
|
||||||
if (!GDK_IS_SURFACE (context_ime->client_surface))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
keyval = gdk_key_event_get_keyval ((GdkEvent *) event);
|
|
||||||
|
|
||||||
if (keyval == GDK_KEY_space &&
|
|
||||||
context_ime->priv->dead_key_keyval != 0)
|
|
||||||
{
|
{
|
||||||
c = _gtk_im_context_ime_dead_key_unichar (context_ime->priv->dead_key_keyval, TRUE);
|
g_signal_emit_by_name (context_ime, "commit", compose_sequence);
|
||||||
context_ime->priv->dead_key_keyval = 0;
|
|
||||||
_gtk_im_context_ime_commit_unichar (context_ime, c);
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
c = gdk_keyval_to_unicode (keyval);
|
return FALSE;
|
||||||
|
|
||||||
if (c && !g_unichar_iscntrl(c))
|
|
||||||
{
|
|
||||||
_gtk_im_context_ime_commit_unichar (context_ime, c);
|
|
||||||
retval = TRUE;
|
|
||||||
}
|
|
||||||
else if (IS_DEAD_KEY (keyval))
|
|
||||||
{
|
|
||||||
gunichar dead_key;
|
|
||||||
|
|
||||||
dead_key = _gtk_im_context_ime_dead_key_unichar (keyval, FALSE);
|
|
||||||
|
|
||||||
/* Emulate double input of dead keys */
|
|
||||||
if (dead_key && 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 = keyval;
|
|
||||||
}
|
|
||||||
|
|
||||||
return retval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -663,7 +663,8 @@ no_sequence_matches (GtkIMContextSimple *context_simple,
|
|||||||
gdk_event_get_modifier_state (event),
|
gdk_event_get_modifier_state (event),
|
||||||
FALSE,
|
FALSE,
|
||||||
&translated,
|
&translated,
|
||||||
&translated);
|
&translated,
|
||||||
|
NULL);
|
||||||
|
|
||||||
gtk_im_context_filter_keypress (context, tmp_event);
|
gtk_im_context_filter_keypress (context, tmp_event);
|
||||||
gdk_event_unref (tmp_event);
|
gdk_event_unref (tmp_event);
|
||||||
|
@ -1084,7 +1084,8 @@ rewrite_event_for_toplevel (GdkEvent *event)
|
|||||||
gdk_key_event_get_keycode (event),
|
gdk_key_event_get_keycode (event),
|
||||||
gdk_event_get_modifier_state (event),
|
gdk_event_get_modifier_state (event),
|
||||||
gdk_key_event_is_modifier (event),
|
gdk_key_event_is_modifier (event),
|
||||||
key, key_no_lock);
|
key, key_no_lock,
|
||||||
|
gdk_key_event_get_compose_sequence (event));
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
Loading…
Reference in New Issue
Block a user