diff options
-rw-r--r-- | chrome/browser/renderer_host/gtk_im_context_wrapper.cc | 48 | ||||
-rw-r--r-- | chrome/browser/renderer_host/gtk_im_context_wrapper.h | 11 |
2 files changed, 50 insertions, 9 deletions
diff --git a/chrome/browser/renderer_host/gtk_im_context_wrapper.cc b/chrome/browser/renderer_host/gtk_im_context_wrapper.cc index c523442..87d12bf 100644 --- a/chrome/browser/renderer_host/gtk_im_context_wrapper.cc +++ b/chrome/browser/renderer_host/gtk_im_context_wrapper.cc @@ -56,7 +56,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_); @@ -159,11 +162,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 @@ -183,13 +194,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, @@ -230,6 +254,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_) @@ -323,7 +351,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. @@ -332,6 +360,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 diff --git a/chrome/browser/renderer_host/gtk_im_context_wrapper.h b/chrome/browser/renderer_host/gtk_im_context_wrapper.h index 92fb576..60bff99 100644 --- a/chrome/browser/renderer_host/gtk_im_context_wrapper.h +++ b/chrome/browser/renderer_host/gtk_im_context_wrapper.h @@ -70,7 +70,10 @@ class GtkIMContextWrapper { // Check if a text needs commit by forwarding a char event instead of // by confirming as a composition text. - bool NeedCommitByForwardingCharEvent(); + bool NeedCommitByForwardingCharEvent() const; + + // Check if the input method returned any result, eg. preedit and commit text. + bool HasInputMethodResult() const; void ProcessFilteredKeyPressEvent(NativeWebKeyboardEvent* wke); void ProcessUnfilteredKeyPressEvent(NativeWebKeyboardEvent* wke); @@ -206,6 +209,12 @@ class GtkIMContextWrapper { // TODO(suzhe): Remove it after input methods get fixed. bool suppress_next_commit_; + // Information of the last key event, for working around + // http://crosbug.com/6582 + int last_key_code_; + bool last_key_was_up_; + bool last_key_filtered_no_result_; + DISALLOW_COPY_AND_ASSIGN(GtkIMContextWrapper); }; |