summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/renderer_host/gtk_im_context_wrapper.cc48
-rw-r--r--chrome/browser/renderer_host/gtk_im_context_wrapper.h11
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);
};