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)
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
......
......@@ -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);
};
......
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