diff options
author | hbono@chromium.org <hbono@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-11-10 06:43:11 +0000 |
---|---|---|
committer | hbono@chromium.org <hbono@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-11-10 06:43:11 +0000 |
commit | 253601010dde1eae42992519244e8b3ffe5499b7 (patch) | |
tree | 13b743c3608bb7ac69bbb5aed12ff8bc11a84a8e /chrome/views/text_field.cc | |
parent | bda00571b1638107491ac3eea8f340f1ae625f01 (diff) | |
download | chromium_src-253601010dde1eae42992519244e8b3ffe5499b7.zip chromium_src-253601010dde1eae42992519244e8b3ffe5499b7.tar.gz chromium_src-253601010dde1eae42992519244e8b3ffe5499b7.tar.bz2 |
Fixes Issue 3096 in chromium "[Find in page] responds each IME composition, making "not found" noises or jumping within the page."
This issue is caued by the TextField::Edit class which start searching a page with a string retrieved with the GetWindowText() function every time when a user presses a key. A string retrived with the GetWindowText() function contains a composition string, a string being composed by an IME. This string changes too often and users do not like to start searching a page with the string.
To fix this issue, this change removes a composition string from a search string to emulate Firefox.
BUG=3096 "Issue 3096: [Find in page] responds each IME composition, making "not found" noises or jumping within the page."
Review URL: http://codereview.chromium.org/9634
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@5096 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/views/text_field.cc')
-rw-r--r-- | chrome/views/text_field.cc | 77 |
1 files changed, 74 insertions, 3 deletions
diff --git a/chrome/views/text_field.cc b/chrome/views/text_field.cc index c36fdbb..d45e875 100644 --- a/chrome/views/text_field.cc +++ b/chrome/views/text_field.cc @@ -67,6 +67,7 @@ class TextField::Edit MSG_WM_CONTEXTMENU(OnContextMenu) MSG_WM_COPY(OnCopy) MSG_WM_CUT(OnCut) + MESSAGE_HANDLER_EX(WM_IME_STARTCOMPOSITION, OnImeStartComposition) MESSAGE_HANDLER_EX(WM_IME_COMPOSITION, OnImeComposition) MSG_WM_KEYDOWN(OnKeyDown) MSG_WM_LBUTTONDBLCLK(OnLButtonDblClk) @@ -112,6 +113,7 @@ class TextField::Edit void OnContextMenu(HWND window, const CPoint& point); void OnCopy(); void OnCut(); + LRESULT OnImeStartComposition(UINT message, WPARAM wparam, LPARAM lparam); LRESULT OnImeComposition(UINT message, WPARAM wparam, LPARAM lparam); void OnKeyDown(TCHAR key, UINT repeat_count, UINT flags); void OnLButtonDblClk(UINT keys, const CPoint& point); @@ -187,6 +189,13 @@ class TextField::Edit // This interface is useful for accessing the CRichEditCtrl at a low level. mutable CComQIPtr<ITextDocument> text_object_model_; + // The position and the length of the ongoing composition string. + // These values are used for removing a composition string from a search + // text to emulate Firefox. + bool ime_discard_composition_; + int ime_composition_start_; + int ime_composition_length_; + DISALLOW_EVIL_CONSTRUCTORS(Edit); }; @@ -230,7 +239,10 @@ TextField::Edit::Edit(TextField* parent, bool draw_border) double_click_time_(0), can_discard_mousemove_(false), contains_mouse_(false), - draw_border_(draw_border) { + draw_border_(draw_border), + ime_discard_composition_(false), + ime_composition_start_(0), + ime_composition_length_(0) { if (!did_load_library_) did_load_library_ = !!LoadLibrary(L"riched20.dll"); @@ -388,11 +400,53 @@ void TextField::Edit::OnCut() { ReplaceSel(L"", true); } +LRESULT TextField::Edit::OnImeStartComposition(UINT message, + WPARAM wparam, + LPARAM lparam) { + // Users may press alt+shift or control+shift keys to change their keyboard + // layouts. So, we retrieve the input locale identifier everytime we start + // an IME composition. + int language_id = PRIMARYLANGID(GetKeyboardLayout(0)); + ime_discard_composition_ = + language_id == LANG_JAPANESE || language_id == LANG_CHINESE; + ime_composition_start_ = 0; + ime_composition_length_ = 0; + + return DefWindowProc(message, wparam, lparam); +} + LRESULT TextField::Edit::OnImeComposition(UINT message, WPARAM wparam, LPARAM lparam) { - OnBeforePossibleChange(); + text_before_change_.clear(); LRESULT result = DefWindowProc(message, wparam, lparam); + + ime_composition_start_ = 0; + ime_composition_length_ = 0; + if (ime_discard_composition_) { + // Call IMM32 functions to retrieve the position and the length of the + // ongoing composition string and notify the OnAfterPossibleChange() + // function that it should discard the composition string from a search + // string. We should not call IMM32 functions in the function because it + // is called when an IME is not composing a string. + HIMC imm_context = ImmGetContext(m_hWnd); + if (imm_context) { + CHARRANGE selection; + GetSel(selection); + const int cursor_position = + ImmGetCompositionString(imm_context, GCS_CURSORPOS, NULL, 0); + if (cursor_position >= 0) + ime_composition_start_ = selection.cpMin - cursor_position; + + const int composition_size = + ImmGetCompositionString(imm_context, GCS_COMPSTR, NULL, 0); + if (composition_size >= 0) + ime_composition_length_ = composition_size / sizeof(wchar_t); + + ImmReleaseContext(m_hWnd, imm_context); + } + } + OnAfterPossibleChange(); return result; } @@ -463,6 +517,12 @@ void TextField::Edit::OnKeyDown(TCHAR key, UINT repeat_count, UINT flags) { case 0xbb: // Ctrl-'='. Triggers subscripting, even in plain text mode. return; + + case VK_PROCESSKEY: + // This key event is consumed by an IME. + // We ignore this event because an IME sends WM_IME_COMPOSITION messages + // when it updates the CRichEditCtrl text. + return; } // CRichEditCtrl changes its text on WM_KEYDOWN instead of WM_CHAR for many @@ -715,8 +775,19 @@ void TextField::Edit::OnAfterPossibleChange() { SetSel(new_sel); } - const std::wstring new_text(GetText()); + std::wstring new_text(GetText()); if (new_text != text_before_change_) { + if (ime_discard_composition_ && ime_composition_start_ >= 0 && + ime_composition_length_ > 0) { + // A string retrieved with a GetText() call contains a string being + // composed by an IME. We remove the composition string from this search + // string. + new_text.erase(ime_composition_start_, ime_composition_length_); + ime_composition_start_ = 0; + ime_composition_length_ = 0; + if (new_text.empty()) + return; + } parent_->SyncText(); if (parent_->GetController()) parent_->GetController()->ContentsChanged(parent_, new_text); |