Index: chrome/browser/renderer_host/gtk_im_context_wrapper.cc |
diff --git a/chrome/browser/renderer_host/gtk_im_context_wrapper.cc b/chrome/browser/renderer_host/gtk_im_context_wrapper.cc |
index 0c2002cdb54774964d23fff864563ac3a7e668ae..0008ec96d5eb2d57828b0f70a3be6fe12f653afa 100644 |
--- a/chrome/browser/renderer_host/gtk_im_context_wrapper.cc |
+++ b/chrome/browser/renderer_host/gtk_im_context_wrapper.cc |
@@ -55,7 +55,10 @@ GtkIMContextWrapper::GtkIMContextWrapper(RenderWidgetHostViewGtk* host_view) |
preedit_selection_start_(0), |
preedit_selection_end_(0), |
is_preedit_changed_(false), |
- suppress_next_commit_(false) { |
+ suppress_next_commit_(false), |
+ last_key_code_(0), |
+ last_key_was_up_(false), |
+ last_key_filtered_no_result_(false) { |
DCHECK(context_); |
DCHECK(context_simple_); |
@@ -158,11 +161,19 @@ void GtkIMContextWrapper::ProcessKeyEvent(GdkEventKey* event) { |
// RenderView::UnhandledKeyboardEvent() from processing it. |
// Otherwise unexpected result may occur. For example if it's a |
// Backspace key event, the browser may go back to previous page. |
- if (filtered) |
+ // We just send all keyup events to the browser to avoid breaking the |
+ // browser's MENU key function, which is actually the only keyup event |
+ // handled in the browser. |
+ if (filtered && event->type == GDK_KEY_PRESS) |
wke.skip_in_browser = true; |
+ const int key_code = wke.windowsKeyCode; |
+ const bool has_result = HasInputMethodResult(); |
+ |
// Send filtered keydown event before sending IME result. |
- if (event->type == GDK_KEY_PRESS && filtered) |
+ // In order to workaround http://crosbug.com/6582, we only send a filtered |
+ // keydown event if it generated any input method result. |
+ if (event->type == GDK_KEY_PRESS && filtered && has_result) |
ProcessFilteredKeyPressEvent(&wke); |
// Send IME results. In most cases, it's only available if the key event |
@@ -182,13 +193,26 @@ void GtkIMContextWrapper::ProcessKeyEvent(GdkEventKey* event) { |
// |
// In this case, the input box will be in a strange state if keydown |
// Backspace is sent to webkit before commit "a" and preedit end. |
- ProcessInputMethodResult(event, filtered); |
+ if (has_result) |
+ ProcessInputMethodResult(event, filtered); |
// Send unfiltered keydown and keyup events after sending IME result. |
- if (event->type == GDK_KEY_PRESS && !filtered) |
+ if (event->type == GDK_KEY_PRESS && !filtered) { |
ProcessUnfilteredKeyPressEvent(&wke); |
- else if (event->type == GDK_KEY_RELEASE) |
- host_view_->ForwardKeyboardEvent(wke); |
+ } else if (event->type == GDK_KEY_RELEASE) { |
+ // In order to workaround http://crosbug.com/6582, we need to suppress |
+ // the keyup event if corresponding keydown event was suppressed, or |
+ // the last key event was a keyup event with the same keycode. |
+ const bool suppress = (last_key_code_ == key_code) && |
+ (last_key_was_up_ || last_key_filtered_no_result_); |
+ |
+ if (!suppress) |
+ host_view_->ForwardKeyboardEvent(wke); |
+ } |
+ |
+ last_key_code_ = key_code; |
+ last_key_was_up_ = (event->type == GDK_KEY_RELEASE); |
+ last_key_filtered_no_result_ = (filtered && !has_result); |
} |
void GtkIMContextWrapper::UpdateInputMethodState(WebKit::WebTextInputType type, |
@@ -229,6 +253,10 @@ void GtkIMContextWrapper::OnFocusIn() { |
// GtkIMContext object correctly later when IME is enabled by WebKit. |
is_focused_ = true; |
+ last_key_code_ = 0; |
+ last_key_was_up_ = false; |
+ last_key_filtered_no_result_ = false; |
+ |
// Notify the GtkIMContext object of this focus-in event only if IME is |
// enabled by WebKit. |
if (is_enabled_) |
@@ -322,7 +350,7 @@ void GtkIMContextWrapper::CancelComposition() { |
is_in_key_event_handler_ = false; |
} |
-bool GtkIMContextWrapper::NeedCommitByForwardingCharEvent() { |
+bool GtkIMContextWrapper::NeedCommitByForwardingCharEvent() const { |
// If there is no composition text and has only one character to be |
// committed, then the character will be send to webkit as a Char event |
// instead of a confirmed composition text. |
@@ -331,6 +359,10 @@ bool GtkIMContextWrapper::NeedCommitByForwardingCharEvent() { |
return !is_composing_text_ && commit_text_.length() == 1; |
} |
+bool GtkIMContextWrapper::HasInputMethodResult() const { |
+ return commit_text_.length() || is_preedit_changed_; |
+} |
+ |
void GtkIMContextWrapper::ProcessFilteredKeyPressEvent( |
NativeWebKeyboardEvent* wke) { |
// If IME has filtered this event, then replace virtual key code with |