Bug 705750 Quartz input method doesn't work correctly for Chinese characters

Modified from original for Gtk3.
This commit is contained in:
Ek Kato 2013-08-16 09:54:34 -07:00 committed by John Ralls
parent 77059dbaba
commit 08042ea830
5 changed files with 117 additions and 41 deletions

View File

@ -167,6 +167,13 @@
GDK_NOTE (EVENTS, g_print ("setMarkedText: set %s (%p, nsview %p): %s\n",
TIC_MARKED_TEXT, gdk_window, self,
str ? str : "(empty)"));
/* handle text input changes by mouse events */
if (!GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (gdk_window),
TIC_IN_KEY_DOWN)))
{
_gdk_quartz_synthesize_null_key_event(gdk_window);
}
}
-(void)doCommandBySelector: (SEL)aSelector
@ -180,19 +187,32 @@
{
GDK_NOTE (EVENTS, g_print ("insertText\n"));
const char *str;
NSString *string;
gchar *prev_str;
if ([self hasMarkedText])
[self unmarkText];
if ([aString isKindOfClass: [NSAttributedString class]])
string = [aString string];
else
string = aString;
NSCharacterSet *ctrlChars = [NSCharacterSet controlCharacterSet];
NSCharacterSet *wsnlChars = [NSCharacterSet whitespaceAndNewlineCharacterSet];
if ([string rangeOfCharacterFromSet:ctrlChars].length &&
[string rangeOfCharacterFromSet:wsnlChars].length == 0)
{
str = [[aString string] UTF8String];
/* discard invalid text input with Chinese input methods */
str = "";
[self unmarkText];
NSInputManager *currentInputManager = [NSInputManager currentInputManager];
[currentInputManager markedTextAbandoned:self];
}
else
{
str = [aString UTF8String];
}
{
str = [string UTF8String];
}
prev_str = g_object_get_data (G_OBJECT (gdk_window), TIC_INSERT_TEXT);
if (prev_str)
@ -204,6 +224,13 @@
g_object_set_data (G_OBJECT (gdk_window), GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_FILTERED));
/* handle text input changes by mouse events */
if (!GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (gdk_window),
TIC_IN_KEY_DOWN)))
{
_gdk_quartz_synthesize_null_key_event(gdk_window);
}
}
-(void)deleteBackward: (id)sender

View File

@ -24,6 +24,7 @@
#define TIC_SELECTED_POS "tic-selected-pos"
#define TIC_SELECTED_LEN "tic-selected-len"
#define TIC_INSERT_TEXT "tic-insert-text"
#define TIC_IN_KEY_DOWN "tic-in-key-down"
/* GtkIMContext */
#define GIC_CURSOR_RECT "gic-cursor-rect"

View File

@ -1156,6 +1156,24 @@ synthesize_crossing_event (GdkWindow *window,
return FALSE;
}
void
_gdk_quartz_synthesize_null_key_event (GdkWindow *window)
{
GdkEvent *event;
GdkQuartzDeviceManagerCore *device_manager;
event = gdk_event_new (GDK_KEY_PRESS);
event->any.type = GDK_KEY_PRESS;
event->key.window = window;
event->key.state = 0;
event->key.hardware_keycode = 0;
event->key.group = 0;
event->key.keyval = GDK_KEY_VoidSymbol;
device_manager = GDK_QUARTZ_DEVICE_MANAGER_CORE (_gdk_display->device_manager);
gdk_event_set_device (event, device_manager->core_keyboard);
append_event(event, FALSE);
}
GdkModifierType
_gdk_quartz_events_get_current_keyboard_modifiers (void)
{

View File

@ -74,6 +74,7 @@ void _gdk_quartz_event_loop_release_event (NSEvent *event);
/* Keys */
GdkEventType _gdk_quartz_keys_event_type (NSEvent *event);
gboolean _gdk_quartz_keys_is_modifier (guint keycode);
void _gdk_quartz_synthesize_null_key_event (GdkWindow *window);
/* Drag and Drop */
void _gdk_quartz_window_register_dnd (GdkWindow *window);

View File

@ -126,48 +126,13 @@ quartz_get_preedit_string (GtkIMContext *context,
}
static gboolean
quartz_filter_keypress (GtkIMContext *context,
GdkEventKey *event)
output_result (GtkIMContext *context,
GdkWindow *win)
{
GtkIMContextQuartz *qc = GTK_IM_CONTEXT_QUARTZ (context);
gboolean retval = FALSE;
NSView *nsview;
GdkWindow *win;
gchar *fixed_str, *marked_str;
GTK_NOTE (MISC, g_print ("quartz_filter_keypress\n"));
if (!qc->client_window)
return FALSE;
nsview = gdk_quartz_window_get_nsview (qc->client_window);
if (GDK_IS_WINDOW (nsview))
/* it gets GDK_WINDOW in some cases */
return gtk_im_context_filter_keypress (qc->slave, event);
else
win = (GdkWindow *)[ (GdkQuartzView *)nsview gdkWindow];
GTK_NOTE (MISC, g_print ("client_window: %p, win: %p, nsview: %p\n",
qc->client_window, win, nsview));
NSEvent *nsevent = gdk_quartz_event_get_nsevent ((GdkEvent *)event);
if (!nsevent)
return gtk_im_context_filter_keypress (qc->slave, event);
if (event->type == GDK_KEY_RELEASE)
return FALSE;
if (event->hardware_keycode == 55) /* Command */
return FALSE;
NSEventType etype = [nsevent type];
if (etype == NSKeyDown)
[nsview keyDown: nsevent];
/* JIS_Eisu || JIS_Kana */
if (event->hardware_keycode == 102 || event->hardware_keycode == 104)
return FALSE;
GTK_NOTE (MISC,
g_print ("quartz_filter_keypress: getting tic-insert-text\n"));
fixed_str = g_object_get_data (G_OBJECT (win), TIC_INSERT_TEXT);
marked_str = g_object_get_data (G_OBJECT (win), TIC_MARKED_TEXT);
if (fixed_str)
@ -203,10 +168,74 @@ quartz_filter_keypress (GtkIMContext *context,
g_signal_emit_by_name (context, "preedit_changed");
retval = TRUE;
}
if (!fixed_str && !marked_str)
{
if (qc->preedit_str && strlen (qc->preedit_str) > 0)
retval = TRUE;
}
g_free (fixed_str);
g_free (marked_str);
return retval;
}
static gboolean
quartz_filter_keypress (GtkIMContext *context,
GdkEventKey *event)
{
GtkIMContextQuartz *qc = GTK_IM_CONTEXT_QUARTZ (context);
gboolean retval;
NSView *nsview;
GdkWindow *win;
GTK_NOTE (MISC, g_print ("quartz_filter_keypress\n"));
if (!qc->client_window)
return FALSE;
nsview = gdk_quartz_window_get_nsview (qc->client_window);
if (GDK_IS_WINDOW (nsview))
/* it gets GDK_WINDOW in some cases */
return gtk_im_context_filter_keypress (qc->slave, event);
else
win = (GdkWindow *)[ (GdkQuartzView *)nsview gdkWindow];
GTK_NOTE (MISC, g_print ("client_window: %p, win: %p, nsview: %p\n",
qc->client_window, win, nsview));
NSEvent *nsevent = gdk_quartz_event_get_nsevent ((GdkEvent *)event);
if (!nsevent)
{
if (event->hardware_keycode == 0 && event->keyval == 0xffffff)
/* update text input changes by mouse events */
output_result(context, win);
else
return gtk_im_context_filter_keypress (qc->slave, event);
}
if (event->type == GDK_KEY_RELEASE)
return FALSE;
if (event->hardware_keycode == 55) /* Command */
return FALSE;
NSEventType etype = [nsevent type];
if (etype == NSKeyDown)
{
g_object_set_data (G_OBJECT (win), TIC_IN_KEY_DOWN,
GUINT_TO_POINTER (TRUE));
[nsview keyDown: nsevent];
}
/* JIS_Eisu || JIS_Kana */
if (event->hardware_keycode == 102 || event->hardware_keycode == 104)
return FALSE;
retval = output_result(context, win);
g_object_set_data (G_OBJECT (win), TIC_IN_KEY_DOWN,
GUINT_TO_POINTER (FALSE));
GTK_NOTE (MISC, g_print ("quartz_filter_keypress done\n"));
return retval;
}