diff options
author | penghuang@chromium.org <penghuang@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-10-31 09:11:57 +0000 |
---|---|---|
committer | penghuang@chromium.org <penghuang@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-10-31 09:11:57 +0000 |
commit | bb953fdae04e514c4f989e644256f9416e096b64 (patch) | |
tree | 7a342994708efd705c9724b210feb7a91247062f /views/ime | |
parent | 1a771269be8885389b4269e14714759f0fcf8660 (diff) | |
download | chromium_src-bb953fdae04e514c4f989e644256f9416e096b64.zip chromium_src-bb953fdae04e514c4f989e644256f9416e096b64.tar.gz chromium_src-bb953fdae04e514c4f989e644256f9416e096b64.tar.bz2 |
Support IMM32 reconversion on Windows.
BUG=45605
TEST=Tested it with Google Japanese Input method on Win7
Review URL: http://codereview.chromium.org/8294026
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@107934 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'views/ime')
-rw-r--r-- | views/ime/input_method_win.cc | 147 | ||||
-rw-r--r-- | views/ime/input_method_win.h | 4 | ||||
-rw-r--r-- | views/ime/text_input_client.h | 14 |
3 files changed, 157 insertions, 8 deletions
diff --git a/views/ime/input_method_win.cc b/views/ime/input_method_win.cc index 4ab1a18..cb27e588 100644 --- a/views/ime/input_method_win.cc +++ b/views/ime/input_method_win.cc @@ -10,6 +10,10 @@ #include "ui/base/keycodes/keyboard_codes.h" #include "views/events/event.h" +// Extra number of chars before and after selection (or composition) range which +// is returned to IME for improving conversion accuracy. +static const size_t kExtraNumberOfChars = 20; + namespace views { InputMethodWin::InputMethodWin(internal::InputMethodDelegate* delegate) @@ -115,6 +119,9 @@ LRESULT InputMethodWin::OnImeMessages( case WM_IME_ENDCOMPOSITION: result = OnImeEndComposition(message, w_param, l_param, handled); break; + case WM_IME_REQUEST: + result = OnImeRequest(message, w_param, l_param, handled); + break; case WM_CHAR: case WM_SYSCHAR: result = OnChar(message, w_param, l_param, handled); @@ -219,6 +226,29 @@ LRESULT InputMethodWin::OnImeEndComposition( return 0; } +LRESULT InputMethodWin::OnImeRequest( + UINT message, WPARAM wparam, LPARAM lparam, BOOL* handled) { + *handled = FALSE; + + // Should not receive WM_IME_REQUEST message, if IME is disabled. + const ui::TextInputType type = GetTextInputType(); + if (type == ui::TEXT_INPUT_TYPE_NONE || + type == ui::TEXT_INPUT_TYPE_PASSWORD) { + return 0; + } + + switch (wparam) { + case IMR_RECONVERTSTRING: + *handled = TRUE; + return OnReconvertString(reinterpret_cast<RECONVERTSTRING*>(lparam)); + case IMR_DOCUMENTFEED: + *handled = TRUE; + return OnDocumentFeed(reinterpret_cast<RECONVERTSTRING*>(lparam)); + default: + return 0; + } +} + LRESULT InputMethodWin::OnChar( UINT message, WPARAM wparam, LPARAM lparam, BOOL* handled) { *handled = TRUE; @@ -254,6 +284,123 @@ LRESULT InputMethodWin::OnDeadChar( return 0; } +LRESULT InputMethodWin::OnDocumentFeed(RECONVERTSTRING* reconv) { + TextInputClient* client = GetTextInputClient(); + if (!client) + return 0; + + ui::Range text_range; + if (!client->GetTextRange(&text_range) || text_range.is_empty()) + return 0; + + bool result = false; + ui::Range target_range; + if (client->HasCompositionText()) + result = client->GetCompositionTextRange(&target_range); + + if (!result || target_range.is_empty()) { + if (!client->GetSelectionRange(&target_range) || + !target_range.IsValid()) { + return 0; + } + } + + if (!text_range.Contains(target_range)) + return 0; + + if (target_range.GetMin() - text_range.start() > kExtraNumberOfChars) + text_range.set_start(target_range.GetMin() - kExtraNumberOfChars); + + if (text_range.end() - target_range.GetMax() > kExtraNumberOfChars) + text_range.set_end(target_range.GetMax() + kExtraNumberOfChars); + + size_t len = text_range.length(); + size_t need_size = sizeof(RECONVERTSTRING) + len * sizeof(WCHAR); + + if (!reconv) + return need_size; + + if (reconv->dwSize < need_size) + return 0; + + string16 text; + if (!GetTextInputClient()->GetTextFromRange(text_range, &text)) + return 0; + DCHECK_EQ(text_range.length(), text.length()); + + reconv->dwVersion = 0; + reconv->dwStrLen = len; + reconv->dwStrOffset = sizeof(RECONVERTSTRING); + reconv->dwCompStrLen = + client->HasCompositionText() ? target_range.length() : 0; + reconv->dwCompStrOffset = + (target_range.GetMin() - text_range.start()) * sizeof(WCHAR); + reconv->dwTargetStrLen = target_range.length(); + reconv->dwTargetStrOffset = reconv->dwCompStrOffset; + + memcpy((char*)reconv + sizeof(RECONVERTSTRING), + text.c_str(), len * sizeof(WCHAR)); + + // According to Microsft API document, IMR_RECONVERTSTRING and + // IMR_DOCUMENTFEED should return reconv, but some applications return + // need_size. + return reinterpret_cast<LRESULT>(reconv); +} + +LRESULT InputMethodWin::OnReconvertString(RECONVERTSTRING* reconv) { + TextInputClient* client = GetTextInputClient(); + if (!client) + return 0; + + // If there is a composition string already, we don't allow reconversion. + if (client->HasCompositionText()) + return 0; + + ui::Range text_range; + if (!client->GetTextRange(&text_range) || text_range.is_empty()) + return 0; + + ui::Range selection_range; + if (!client->GetSelectionRange(&selection_range) || + selection_range.is_empty()) { + return 0; + } + + DCHECK(text_range.Contains(selection_range)); + + size_t len = selection_range.length(); + size_t need_size = sizeof(RECONVERTSTRING) + len * sizeof(WCHAR); + + if (!reconv) + return need_size; + + if (reconv->dwSize < need_size) + return 0; + + // TODO(penghuang): Return some extra context to help improve IME's + // reconversion accuracy. + string16 text; + if (!GetTextInputClient()->GetTextFromRange(selection_range, &text)) + return 0; + DCHECK_EQ(selection_range.length(), text.length()); + + reconv->dwVersion = 0; + reconv->dwStrLen = len; + reconv->dwStrOffset = sizeof(RECONVERTSTRING); + reconv->dwCompStrLen = len; + reconv->dwCompStrOffset = 0; + reconv->dwTargetStrLen = len; + reconv->dwTargetStrOffset = 0; + + memcpy(reinterpret_cast<char*>(reconv) + sizeof(RECONVERTSTRING), + text.c_str(), len * sizeof(WCHAR)); + + // According to Microsft API document, IMR_RECONVERTSTRING and + // IMR_DOCUMENTFEED should return reconv, but some applications return + // need_size. + return reinterpret_cast<LRESULT>(reconv); +} + void InputMethodWin::ConfirmCompositionText() { if (!IsTextInputTypeNone()) { ime_input_.CleanupComposition(hwnd()); diff --git a/views/ime/input_method_win.h b/views/ime/input_method_win.h index d917508..8fdc90c 100644 --- a/views/ime/input_method_win.h +++ b/views/ime/input_method_win.h @@ -54,6 +54,8 @@ class InputMethodWin : public InputMethodBase { UINT message, WPARAM wparam, LPARAM lparam, BOOL* handled); LRESULT OnImeEndComposition( UINT message, WPARAM wparam, LPARAM lparam, BOOL* handled); + LRESULT OnImeRequest( + UINT message, WPARAM wparam, LPARAM lparam, BOOL* handled); // For both WM_CHAR and WM_SYSCHAR LRESULT OnChar( UINT message, WPARAM wparam, LPARAM lparam, BOOL* handled); @@ -61,6 +63,8 @@ class InputMethodWin : public InputMethodBase { LRESULT OnDeadChar( UINT message, WPARAM wparam, LPARAM lparam, BOOL* handled); + LRESULT OnDocumentFeed(RECONVERTSTRING *reconv); + LRESULT OnReconvertString(RECONVERTSTRING *reconv); // Overridden from InputMethodBase. virtual void FocusedViewWillChange() OVERRIDE; diff --git a/views/ime/text_input_client.h b/views/ime/text_input_client.h index 35c595f..a0dd86a3 100644 --- a/views/ime/text_input_client.h +++ b/views/ime/text_input_client.h @@ -9,7 +9,6 @@ #include <vector> #include "base/basictypes.h" -#include "base/callback.h" #include "base/string16.h" #include "ui/base/ime/composition_text.h" #include "ui/base/ime/text_input_type.h" @@ -74,7 +73,8 @@ class VIEWS_EXPORT TextInputClient { // Document content operations ---------------------------------------------- - // Retrieves the UTF-16 based character range containing all text in the View. + // Retrieves the UTF-16 based character range containing accessibled text in + // the View. It must cover the composition and selection range. // Returns false if the information cannot be retrieved right now. virtual bool GetTextRange(ui::Range* range) = 0; @@ -98,12 +98,10 @@ class VIEWS_EXPORT TextInputClient { virtual bool DeleteRange(const ui::Range& range) = 0; // Retrieves the text content in a given UTF-16 based character range. - // The result will be send back to the input method by calling the given - // callback, which may happen asynchronously. - // Returns false if the operation is not supported. - virtual bool GetTextFromRange( - const ui::Range& range, - const base::Callback<void(const string16&)>& callback) = 0; + // The result will be stored into |*text|. + // Returns false if the operation is not supported or the specified range + // is out of the text range returned by GetTextRange(). + virtual bool GetTextFromRange(const ui::Range& range, string16* text) = 0; // Miscellaneous ------------------------------------------------------------ |