Commit f6ab5725 authored by suzhe@google.com's avatar suzhe@google.com

Workaround a nasty ibus issue.

The reason of this bug is:
Because of some reason, ibus will send a fake event to the application for each real key event. These extra fake key events apparently confuse those web apps. This CL tries to suppress those extra key events faked by ibus, while keeping the behavior of other input methods unaffected as much as possible.
It's a hacky workaround. Hope it won't cause any other problem.

BUG=chromium-os:6582
TEST=See bug report.

Review URL: http://codereview.chromium.org/6336003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@71883 0039d316-1c4b-4281-b951-d872f2087c98
parent 05afda1f
...@@ -56,7 +56,10 @@ GtkIMContextWrapper::GtkIMContextWrapper(RenderWidgetHostViewGtk* host_view) ...@@ -56,7 +56,10 @@ GtkIMContextWrapper::GtkIMContextWrapper(RenderWidgetHostViewGtk* host_view)
preedit_selection_start_(0), preedit_selection_start_(0),
preedit_selection_end_(0), preedit_selection_end_(0),
is_preedit_changed_(false), 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_);
DCHECK(context_simple_); DCHECK(context_simple_);
...@@ -159,11 +162,19 @@ void GtkIMContextWrapper::ProcessKeyEvent(GdkEventKey* event) { ...@@ -159,11 +162,19 @@ void GtkIMContextWrapper::ProcessKeyEvent(GdkEventKey* event) {
// RenderView::UnhandledKeyboardEvent() from processing it. // RenderView::UnhandledKeyboardEvent() from processing it.
// Otherwise unexpected result may occur. For example if it's a // Otherwise unexpected result may occur. For example if it's a
// Backspace key event, the browser may go back to previous page. // 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; wke.skip_in_browser = true;
const int key_code = wke.windowsKeyCode;
const bool has_result = HasInputMethodResult();
// Send filtered keydown event before sending IME result. // 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); ProcessFilteredKeyPressEvent(&wke);
// Send IME results. In most cases, it's only available if the key event // Send IME results. In most cases, it's only available if the key event
...@@ -183,13 +194,26 @@ void GtkIMContextWrapper::ProcessKeyEvent(GdkEventKey* event) { ...@@ -183,13 +194,26 @@ void GtkIMContextWrapper::ProcessKeyEvent(GdkEventKey* event) {
// //
// In this case, the input box will be in a strange state if keydown // 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. // 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. // 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); ProcessUnfilteredKeyPressEvent(&wke);
else if (event->type == GDK_KEY_RELEASE) } else if (event->type == GDK_KEY_RELEASE) {
host_view_->ForwardKeyboardEvent(wke); // 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, void GtkIMContextWrapper::UpdateInputMethodState(WebKit::WebTextInputType type,
...@@ -230,6 +254,10 @@ void GtkIMContextWrapper::OnFocusIn() { ...@@ -230,6 +254,10 @@ void GtkIMContextWrapper::OnFocusIn() {
// GtkIMContext object correctly later when IME is enabled by WebKit. // GtkIMContext object correctly later when IME is enabled by WebKit.
is_focused_ = true; 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 // Notify the GtkIMContext object of this focus-in event only if IME is
// enabled by WebKit. // enabled by WebKit.
if (is_enabled_) if (is_enabled_)
...@@ -323,7 +351,7 @@ void GtkIMContextWrapper::CancelComposition() { ...@@ -323,7 +351,7 @@ void GtkIMContextWrapper::CancelComposition() {
is_in_key_event_handler_ = false; 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 // 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 // committed, then the character will be send to webkit as a Char event
// instead of a confirmed composition text. // instead of a confirmed composition text.
...@@ -332,6 +360,10 @@ bool GtkIMContextWrapper::NeedCommitByForwardingCharEvent() { ...@@ -332,6 +360,10 @@ bool GtkIMContextWrapper::NeedCommitByForwardingCharEvent() {
return !is_composing_text_ && commit_text_.length() == 1; return !is_composing_text_ && commit_text_.length() == 1;
} }
bool GtkIMContextWrapper::HasInputMethodResult() const {
return commit_text_.length() || is_preedit_changed_;
}
void GtkIMContextWrapper::ProcessFilteredKeyPressEvent( void GtkIMContextWrapper::ProcessFilteredKeyPressEvent(
NativeWebKeyboardEvent* wke) { NativeWebKeyboardEvent* wke) {
// If IME has filtered this event, then replace virtual key code with // If IME has filtered this event, then replace virtual key code with
......
...@@ -70,7 +70,10 @@ class GtkIMContextWrapper { ...@@ -70,7 +70,10 @@ class GtkIMContextWrapper {
// Check if a text needs commit by forwarding a char event instead of // Check if a text needs commit by forwarding a char event instead of
// by confirming as a composition text. // 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 ProcessFilteredKeyPressEvent(NativeWebKeyboardEvent* wke);
void ProcessUnfilteredKeyPressEvent(NativeWebKeyboardEvent* wke); void ProcessUnfilteredKeyPressEvent(NativeWebKeyboardEvent* wke);
...@@ -206,6 +209,12 @@ class GtkIMContextWrapper { ...@@ -206,6 +209,12 @@ class GtkIMContextWrapper {
// TODO(suzhe): Remove it after input methods get fixed. // TODO(suzhe): Remove it after input methods get fixed.
bool suppress_next_commit_; 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); DISALLOW_COPY_AND_ASSIGN(GtkIMContextWrapper);
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment