mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2025-01-10 12:40:10 +00:00
macOS: Fix bug that entry cannot press and hold a key to input accented character.
There're two issues in GdkQuartzView's NSTextInputClient implementation causes this bug. 1. The -(NSRange)selectedRange should not return [NSNotFound, 0] if there's no selection. The accented character window will not show if returned NSRange's location is NSNotFound. Instead of that, the NSRange's location should be the caret position in the text input buffer. 2. The accented character window will invoke -(void)insertText:replacementRange: with non-empty replacement range, to replace non-accented character with accented character after user select it from accented character window. This case is not implemented in original code. Here I use another gobject data to pass the information to input module and convert it into 'delete-surrounding' event. Besides these, there's another bug cause gtk_im_context_filter_keypress() return wrong value while user press and hold a key. When user press and hold a key, the accented character window will consume the repeating key down event. Is this case, gtk_im_context_filter_keypress() should return TRUE, indicate the key press is filtered by input method module. But it will return FALSE because gtk_im_context_filter_keypress() assume that every key press event will generate some text from input method module. Fixes #1618
This commit is contained in:
parent
4af1fa872a
commit
cfad43b80d
@ -31,7 +31,7 @@
|
|||||||
if ((self = [super initWithFrame: frameRect]))
|
if ((self = [super initWithFrame: frameRect]))
|
||||||
{
|
{
|
||||||
markedRange = NSMakeRange (NSNotFound, 0);
|
markedRange = NSMakeRange (NSNotFound, 0);
|
||||||
selectedRange = NSMakeRange (NSNotFound, 0);
|
selectedRange = NSMakeRange (0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
@ -57,6 +57,16 @@
|
|||||||
|
|
||||||
-(void) keyDown: (NSEvent *) theEvent
|
-(void) keyDown: (NSEvent *) theEvent
|
||||||
{
|
{
|
||||||
|
/* NOTE: When user press Cmd+A, interpretKeyEvents: will call noop:
|
||||||
|
method. When user press and hold A to show the accented char window,
|
||||||
|
it consumed repeating key down events for key 'A' do NOT call
|
||||||
|
any other method. We use this behavior to determine if this key
|
||||||
|
down event is filtered by interpretKeyEvents.
|
||||||
|
*/
|
||||||
|
|
||||||
|
g_object_set_data (G_OBJECT (gdk_window), GIC_FILTER_KEY,
|
||||||
|
GUINT_TO_POINTER (GIC_FILTER_FILTERED));
|
||||||
|
|
||||||
GDK_NOTE (EVENTS, g_message ("keyDown"));
|
GDK_NOTE (EVENTS, g_message ("keyDown"));
|
||||||
[self interpretKeyEvents: [NSArray arrayWithObject: theEvent]];
|
[self interpretKeyEvents: [NSArray arrayWithObject: theEvent]];
|
||||||
}
|
}
|
||||||
@ -124,7 +134,8 @@
|
|||||||
-(void)unmarkText
|
-(void)unmarkText
|
||||||
{
|
{
|
||||||
GDK_NOTE (EVENTS, g_message ("unmarkText"));
|
GDK_NOTE (EVENTS, g_message ("unmarkText"));
|
||||||
markedRange = selectedRange = NSMakeRange (NSNotFound, 0);
|
selectedRange = NSMakeRange (0, 0);
|
||||||
|
markedRange = NSMakeRange (NSNotFound, 0);
|
||||||
|
|
||||||
g_object_set_data_full (G_OBJECT (gdk_window), TIC_MARKED_TEXT, NULL, g_free);
|
g_object_set_data_full (G_OBJECT (gdk_window), TIC_MARKED_TEXT, NULL, g_free);
|
||||||
}
|
}
|
||||||
@ -209,8 +220,15 @@
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
str = [string UTF8String];
|
str = [string UTF8String];
|
||||||
|
selectedRange = NSMakeRange ([string length], 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (replacementRange.length > 0)
|
||||||
|
{
|
||||||
|
g_object_set_data (G_OBJECT (gdk_window), TIC_INSERT_TEXT_REPLACE_LEN,
|
||||||
|
GINT_TO_POINTER (replacementRange.length));
|
||||||
|
}
|
||||||
|
|
||||||
g_object_set_data_full (G_OBJECT (gdk_window), TIC_INSERT_TEXT, g_strdup (str), g_free);
|
g_object_set_data_full (G_OBJECT (gdk_window), TIC_INSERT_TEXT, g_strdup (str), g_free);
|
||||||
GDK_NOTE (EVENTS, g_message ("insertText: set %s (%p, nsview %p): %s",
|
GDK_NOTE (EVENTS, g_message ("insertText: set %s (%p, nsview %p): %s",
|
||||||
TIC_INSERT_TEXT, gdk_window, self,
|
TIC_INSERT_TEXT, gdk_window, self,
|
||||||
@ -537,6 +555,8 @@
|
|||||||
-(void)noop: (id)sender
|
-(void)noop: (id)sender
|
||||||
{
|
{
|
||||||
GDK_NOTE (EVENTS, g_message ("noop"));
|
GDK_NOTE (EVENTS, g_message ("noop"));
|
||||||
|
g_object_set_data (G_OBJECT (gdk_window), GIC_FILTER_KEY,
|
||||||
|
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------- */
|
/* --------------------------------------------------------------- */
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#define TIC_SELECTED_POS "tic-selected-pos"
|
#define TIC_SELECTED_POS "tic-selected-pos"
|
||||||
#define TIC_SELECTED_LEN "tic-selected-len"
|
#define TIC_SELECTED_LEN "tic-selected-len"
|
||||||
#define TIC_INSERT_TEXT "tic-insert-text"
|
#define TIC_INSERT_TEXT "tic-insert-text"
|
||||||
|
#define TIC_INSERT_TEXT_REPLACE_LEN "tic-insert-text-replace-len"
|
||||||
#define TIC_IN_KEY_DOWN "tic-in-key-down"
|
#define TIC_IN_KEY_DOWN "tic-in-key-down"
|
||||||
|
|
||||||
/* GtkIMContext */
|
/* GtkIMContext */
|
||||||
|
@ -129,8 +129,11 @@ output_result (GtkIMContext *context,
|
|||||||
{
|
{
|
||||||
GtkIMContextQuartz *qc = GTK_IM_CONTEXT_QUARTZ (context);
|
GtkIMContextQuartz *qc = GTK_IM_CONTEXT_QUARTZ (context);
|
||||||
gboolean retval = FALSE;
|
gboolean retval = FALSE;
|
||||||
|
int fixed_str_replace_len;
|
||||||
gchar *fixed_str, *marked_str;
|
gchar *fixed_str, *marked_str;
|
||||||
|
|
||||||
|
fixed_str_replace_len = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (win),
|
||||||
|
TIC_INSERT_TEXT_REPLACE_LEN));
|
||||||
fixed_str = g_strdup (g_object_get_data (G_OBJECT (win), TIC_INSERT_TEXT));
|
fixed_str = g_strdup (g_object_get_data (G_OBJECT (win), TIC_INSERT_TEXT));
|
||||||
marked_str = g_strdup (g_object_get_data (G_OBJECT (win), TIC_MARKED_TEXT));
|
marked_str = g_strdup (g_object_get_data (G_OBJECT (win), TIC_MARKED_TEXT));
|
||||||
if (fixed_str)
|
if (fixed_str)
|
||||||
@ -139,6 +142,13 @@ output_result (GtkIMContext *context,
|
|||||||
g_free (qc->preedit_str);
|
g_free (qc->preedit_str);
|
||||||
qc->preedit_str = NULL;
|
qc->preedit_str = NULL;
|
||||||
g_object_set_data (G_OBJECT (win), TIC_INSERT_TEXT, NULL);
|
g_object_set_data (G_OBJECT (win), TIC_INSERT_TEXT, NULL);
|
||||||
|
if (fixed_str_replace_len)
|
||||||
|
{
|
||||||
|
gboolean retval;
|
||||||
|
g_object_set_data (G_OBJECT (win), TIC_INSERT_TEXT_REPLACE_LEN, 0);
|
||||||
|
g_signal_emit_by_name (context, "delete-surrounding",
|
||||||
|
-fixed_str_replace_len, fixed_str_replace_len, &retval);
|
||||||
|
}
|
||||||
g_signal_emit_by_name (context, "commit", fixed_str);
|
g_signal_emit_by_name (context, "commit", fixed_str);
|
||||||
g_signal_emit_by_name (context, "preedit_changed");
|
g_signal_emit_by_name (context, "preedit_changed");
|
||||||
|
|
||||||
@ -168,6 +178,11 @@ output_result (GtkIMContext *context,
|
|||||||
}
|
}
|
||||||
if (!fixed_str && !marked_str)
|
if (!fixed_str && !marked_str)
|
||||||
{
|
{
|
||||||
|
unsigned int filtered =
|
||||||
|
GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (win),
|
||||||
|
GIC_FILTER_KEY));
|
||||||
|
if (filtered)
|
||||||
|
retval = TRUE;
|
||||||
if (qc->preedit_str && strlen (qc->preedit_str) > 0)
|
if (qc->preedit_str && strlen (qc->preedit_str) > 0)
|
||||||
retval = TRUE;
|
retval = TRUE;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user