diff --git a/gdk/quartz/GdkQuartzView.c b/gdk/quartz/GdkQuartzView.c index 95ce69f3cf..26700ff23d 100644 --- a/gdk/quartz/GdkQuartzView.c +++ b/gdk/quartz/GdkQuartzView.c @@ -170,6 +170,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 @@ -183,19 +190,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) @@ -207,6 +227,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 diff --git a/gdk/quartz/GdkQuartzView.h b/gdk/quartz/GdkQuartzView.h index c9059f8865..2f86de71e2 100644 --- a/gdk/quartz/GdkQuartzView.h +++ b/gdk/quartz/GdkQuartzView.h @@ -26,6 +26,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" diff --git a/gdk/quartz/gdkevents-quartz.c b/gdk/quartz/gdkevents-quartz.c index 69094d3f06..9e57edd5b7 100644 --- a/gdk/quartz/gdkevents-quartz.c +++ b/gdk/quartz/gdkevents-quartz.c @@ -1157,6 +1157,21 @@ synthesize_crossing_event (GdkWindow *window, return FALSE; } +void +_gdk_quartz_synthesize_null_key_event (GdkWindow *window) +{ + GdkEvent *event; + + 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_VoidSymbol; + append_event(event, FALSE); +} + GdkEventMask _gdk_quartz_events_get_current_event_mask (void) { diff --git a/gdk/quartz/gdkprivate-quartz.h b/gdk/quartz/gdkprivate-quartz.h index af0931a0f1..b78c353698 100644 --- a/gdk/quartz/gdkprivate-quartz.h +++ b/gdk/quartz/gdkprivate-quartz.h @@ -198,6 +198,7 @@ GdkImage *_gdk_quartz_image_copy_to_image (GdkDrawable *drawable, /* 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); /* Drawable */ void _gdk_quartz_drawable_finish (GdkDrawable *drawable); diff --git a/modules/input/imquartz.c b/modules/input/imquartz.c index 06ebc6837b..febf41bc69 100644 --- a/modules/input/imquartz.c +++ b/modules/input/imquartz.c @@ -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; }