diff options
author | hbono@chromium.org <hbono@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-11-06 07:40:53 +0000 |
---|---|---|
committer | hbono@chromium.org <hbono@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-11-06 07:40:53 +0000 |
commit | 34f6bc1937fe617875e8f5e95485904569cca582 (patch) | |
tree | 94f201b6bb78ff601a8a97783f4ac0134423af48 /chrome | |
parent | 576d8bff4e6778c6de60b8a7269a78c5e8bf602a (diff) | |
download | chromium_src-34f6bc1937fe617875e8f5e95485904569cca582.zip chromium_src-34f6bc1937fe617875e8f5e95485904569cca582.tar.gz chromium_src-34f6bc1937fe617875e8f5e95485904569cca582.tar.bz2 |
Changes parameters used by IME code to fix several issues caused by Japanese IMEs.
Recent Japanese IMEs (ATOK2008 and MSIME 2007) display a suggestion window (a window which contains suggestions) above a composition string. To fix this issue, we do not only send the lower-left corner of a composition string but also send its upper-left corner and its upper-right corner. So, this change changes IPC parameters used by IME from a tuple of integers to gfx::Rect.
Also, this change fixes cursor positions for Japanese IMEs.
BUG=2770 "IME: Candidate window of Japanese IME follows the end of composition"
BUG=2771 "ATOK 2008 IME pop-ups are displayed below the main Chrome window."
BUG=2775 "IME: Caret is always displayed at the last of IME composition."
Review URL: http://codereview.chromium.org/7385
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@4872 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/browser/ime_input.cc | 37 | ||||
-rw-r--r-- | chrome/browser/ime_input.h | 16 | ||||
-rw-r--r-- | chrome/browser/render_widget_host.cc | 4 | ||||
-rw-r--r-- | chrome/browser/render_widget_host.h | 3 | ||||
-rw-r--r-- | chrome/browser/render_widget_host_view.h | 3 | ||||
-rw-r--r-- | chrome/browser/render_widget_host_view_win.cc | 5 | ||||
-rw-r--r-- | chrome/browser/render_widget_host_view_win.h | 3 | ||||
-rw-r--r-- | chrome/browser/web_contents_unittest.cc | 3 | ||||
-rw-r--r-- | chrome/common/render_messages_internal.h | 14 | ||||
-rw-r--r-- | chrome/renderer/render_widget.cc | 42 |
10 files changed, 73 insertions, 57 deletions
diff --git a/chrome/browser/ime_input.cc b/chrome/browser/ime_input.cc index 83bd090..68bde20 100644 --- a/chrome/browser/ime_input.cc +++ b/chrome/browser/ime_input.cc @@ -20,8 +20,7 @@ ImeInput::ImeInput() input_language_id_(LANG_USER_DEFAULT), is_composing_(false), system_caret_(false), - caret_x_(-1), - caret_y_(-1) { + caret_rect_(-1, -1, 0, 0) { } ImeInput::~ImeInput() { @@ -48,7 +47,10 @@ void ImeInput::CreateImeWindow(HWND window_handle) { // retrieve the position of their IME candidate window. // Therefore, we create a temporary system caret for Chinese IMEs and use // it during this input context. - if (PRIMARYLANGID(input_language_id_) == LANG_CHINESE) { + // Since some third-party Japanese IME also uses ::GetCaretPos() to determine + // their window position, we also create a caret for Japanese IMEs. + if (PRIMARYLANGID(input_language_id_) == LANG_CHINESE || + PRIMARYLANGID(input_language_id_) == LANG_JAPANESE) { if (!system_caret_) { if (::CreateCaret(window_handle, NULL, 1, 1)) { system_caret_ = true; @@ -84,8 +86,8 @@ void ImeInput::DestroyImeWindow(HWND window_handle) { } void ImeInput::MoveImeWindow(HWND window_handle, HIMC imm_context) { - int x = caret_x_; - int y = caret_y_; + int x = caret_rect_.x(); + int y = caret_rect_.y(); const int kCaretMargin = 1; // As written in a comment in ImeInput::CreateImeWindow(), // Chinese IMEs ignore function calls to ::ImmSetCandidateWindow() @@ -101,7 +103,14 @@ void ImeInput::MoveImeWindow(HWND window_handle, HIMC imm_context) { {0, 0, 0, 0}}; ::ImmSetCandidateWindow(imm_context, &candidate_position); if (system_caret_) { - ::SetCaretPos(x, y); + switch (PRIMARYLANGID(input_language_id_)) { + case LANG_JAPANESE: + ::SetCaretPos(x, y + caret_rect_.height()); + break; + default: + ::SetCaretPos(x, y); + break; + } } if (PRIMARYLANGID(input_language_id_) == LANG_KOREAN) { // Chinese IMEs and Japanese IMEs require the upper-left corner of @@ -115,13 +124,13 @@ void ImeInput::MoveImeWindow(HWND window_handle, HIMC imm_context) { // to move their candidate windows when a user disables TSF and CUAS. // Therefore, we also set this parameter here. CANDIDATEFORM exclude_rectangle = {0, CFS_EXCLUDE, {x, y}, - {x, y, x, y + kCaretMargin}}; + {x, y, x + caret_rect_.width(), y + caret_rect_.height()}}; ::ImmSetCandidateWindow(imm_context, &exclude_rectangle); } void ImeInput::UpdateImeWindow(HWND window_handle) { // Just move the IME window attached to the given window. - if (caret_x_ >= 0 && caret_y_ >= 0) { + if (caret_rect_.x() >= 0 && caret_rect_.y() >= 0) { HIMC imm_context = ::ImmGetContext(window_handle); if (imm_context) { MoveImeWindow(window_handle, imm_context); @@ -185,8 +194,6 @@ void ImeInput::GetCaret(HIMC imm_context, LPARAM lparam, // is scanning the attribute of the latest composition string and // retrieving the begining and the end of the target clause, i.e. // a clause being converted. - size_t composition_length = composition->ime_string.length(); - composition->cursor_position = static_cast<int>(composition_length); if (lparam & GCS_COMPATTR) { int attribute_size = ::ImmGetCompositionString(imm_context, GCS_COMPATTR, @@ -297,7 +304,9 @@ void ImeInput::DisableIME(HWND window_handle) { ::ImmAssociateContextEx(window_handle, NULL, 0); } -void ImeInput::EnableIME(HWND window_handle, int x, int y, bool complete) { +void ImeInput::EnableIME(HWND window_handle, + const gfx::Rect& caret_rect, + bool complete) { // Load the default IME context. // NOTE(hbono) // IMM ignores this call if the IME context is loaded. Therefore, we do @@ -318,9 +327,9 @@ void ImeInput::EnableIME(HWND window_handle, int x, int y, bool complete) { // Save the caret position, and Update the position of the IME window. // This update is used for moving an IME window when a renderer process // resize/moves the input caret. - if (x >= 0 && y >= 0) { - caret_x_ = x; - caret_y_ = y; + if (caret_rect.x() >= 0 && caret_rect.y() >= 0) { + caret_rect_.SetRect(caret_rect.x(), caret_rect.y(), caret_rect.width(), + caret_rect.height()); MoveImeWindow(window_handle, imm_context); } ::ImmReleaseContext(window_handle, imm_context); diff --git a/chrome/browser/ime_input.h b/chrome/browser/ime_input.h index 4064f02..8175887 100644 --- a/chrome/browser/ime_input.h +++ b/chrome/browser/ime_input.h @@ -10,6 +10,7 @@ #include <string> #include "base/basictypes.h" +#include "base/gfx/Rect.h" // This header file defines a struct and a class used for encapsulating IMM32 // APIs, controls IMEs attached to a window, and enables the 'on-the-spot' @@ -209,9 +210,9 @@ class ImeInput { // Parameters // * window_handle [in] (HWND) // Represents the window handle of the caller. - // * x [in] (int) - // * y [in] (int) - // Represent the position of the upper-left corner of IME windows. + // * caret_rect [in] (const gfx::Rect&) + // Represent the rectangle of the input caret. + // This rectangle is used for controlling the positions of IME windows. // * complete [in] (bool) // Represents whether or not to complete the ongoing composition. // + true @@ -221,7 +222,9 @@ class ImeInput { // + false // Just move the IME windows of the ongoing composition to the given // position without finishing it. - void EnableIME(HWND window_handle, int x, int y, bool complete); + void EnableIME(HWND window_handle, + const gfx::Rect& caret_rect, + bool complete); // Disable the IME attached to the given window, i.e. prohibits any user-input // events from being dispatched to the IME. @@ -294,9 +297,8 @@ class ImeInput { // * false: it does not create a system caret. bool system_caret_; - // The position of the input caret retrieved from a renderer process. - int caret_x_; - int caret_y_; + // The rectangle of the input caret retrieved from a renderer process. + gfx::Rect caret_rect_; DISALLOW_EVIL_CONSTRUCTORS(ImeInput); }; diff --git a/chrome/browser/render_widget_host.cc b/chrome/browser/render_widget_host.cc index 055d376..449c857 100644 --- a/chrome/browser/render_widget_host.cc +++ b/chrome/browser/render_widget_host.cc @@ -526,9 +526,9 @@ void RenderWidgetHost::OnMsgSetCursor(const WebCursor& cursor) { } void RenderWidgetHost::OnMsgImeUpdateStatus(ViewHostMsg_ImeControl control, - int x, int y) { + const gfx::Rect& caret_rect) { if (view_) { - view_->IMEUpdateStatus(control, x, y); + view_->IMEUpdateStatus(control, caret_rect); } } diff --git a/chrome/browser/render_widget_host.h b/chrome/browser/render_widget_host.h index 4b1ffcc1..825a680 100644 --- a/chrome/browser/render_widget_host.h +++ b/chrome/browser/render_widget_host.h @@ -221,7 +221,8 @@ class RenderWidgetHost : public IPC::Channel::Listener { void OnMsgFocus(); void OnMsgBlur(); void OnMsgSetCursor(const WebCursor& cursor); - void OnMsgImeUpdateStatus(ViewHostMsg_ImeControl control, int x, int y); + void OnMsgImeUpdateStatus(ViewHostMsg_ImeControl control, + const gfx::Rect& caret_rect); void MovePluginWindows( const std::vector<WebPluginGeometry>& plugin_window_moves); diff --git a/chrome/browser/render_widget_host_view.h b/chrome/browser/render_widget_host_view.h index be9c128..0797cc5 100644 --- a/chrome/browser/render_widget_host_view.h +++ b/chrome/browser/render_widget_host_view.h @@ -89,8 +89,7 @@ class RenderWidgetHostView { // Enable or disable IME for the view. virtual void IMEUpdateStatus(ViewHostMsg_ImeControl control, - int x, - int y) = 0; + const gfx::Rect& caret_rect) = 0; // Informs the view that a portion of the widget's backing store was painted. virtual void DidPaintRect(const gfx::Rect& rect) = 0; diff --git a/chrome/browser/render_widget_host_view_win.cc b/chrome/browser/render_widget_host_view_win.cc index 3b2e961..3c86595 100644 --- a/chrome/browser/render_widget_host_view_win.cc +++ b/chrome/browser/render_widget_host_view_win.cc @@ -263,11 +263,12 @@ void RenderWidgetHostViewWin::SetIsLoading(bool is_loading) { } void RenderWidgetHostViewWin::IMEUpdateStatus(ViewHostMsg_ImeControl control, - int x, int y) { + const gfx::Rect& caret_rect) { if (control == IME_DISABLE) { ime_input_.DisableIME(m_hWnd); } else { - ime_input_.EnableIME(m_hWnd, x, y, control == IME_COMPLETE_COMPOSITION); + ime_input_.EnableIME(m_hWnd, caret_rect, + control == IME_COMPLETE_COMPOSITION); } } diff --git a/chrome/browser/render_widget_host_view_win.h b/chrome/browser/render_widget_host_view_win.h index ce0497b7..d1b7730 100644 --- a/chrome/browser/render_widget_host_view_win.h +++ b/chrome/browser/render_widget_host_view_win.h @@ -136,7 +136,8 @@ class RenderWidgetHostViewWin : virtual void UpdateCursor(const WebCursor& cursor); virtual void UpdateCursorIfOverSelf(); virtual void SetIsLoading(bool is_loading); - virtual void IMEUpdateStatus(ViewHostMsg_ImeControl control, int x, int y); + virtual void IMEUpdateStatus(ViewHostMsg_ImeControl control, + const gfx::Rect& caret_rect); virtual void DidPaintRect(const gfx::Rect& rect); virtual void DidScrollRect(const gfx::Rect& rect, int dx, int dy); virtual void RendererGone(); diff --git a/chrome/browser/web_contents_unittest.cc b/chrome/browser/web_contents_unittest.cc index 5319a81..4811350 100644 --- a/chrome/browser/web_contents_unittest.cc +++ b/chrome/browser/web_contents_unittest.cc @@ -42,7 +42,8 @@ class TestRenderWidgetHostView : public RenderWidgetHostView { virtual void UpdateCursorIfOverSelf() {} // Indicates if the page has finished loading. virtual void SetIsLoading(bool is_loading) {} - virtual void IMEUpdateStatus(ViewHostMsg_ImeControl control, int x, int y) {} + virtual void IMEUpdateStatus(ViewHostMsg_ImeControl control, + const gfx::Rect& caret_rect) {} virtual void DidPaintRect(const gfx::Rect& rect) {} virtual void DidScrollRect(const gfx::Rect& rect, int dx, int dy) {} virtual void RendererGone() {} diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h index 4e6643c..a4098a0 100644 --- a/chrome/common/render_messages_internal.h +++ b/chrome/common/render_messages_internal.h @@ -890,8 +890,8 @@ IPC_BEGIN_MESSAGES(ViewHost, 2) // - Notifying a renderer process moves its input focus from a // password input to an editable control which is NOT a password // input. - // A renderer process also has to set caret_x and caret_y and - // specify the new caret position. + // A renderer process also has to set caret_rect and + // specify the new caret rectangle. // + IME_COMPLETE_COMPOSITION // Finish the current composition. // This code is used for notifying a renderer process moves its @@ -899,13 +899,11 @@ IPC_BEGIN_MESSAGES(ViewHost, 2) // which is NOT a password input. A browser process closes its IME // windows without changing the activation status of its IME, i.e. it // keeps activating its IME. - // * caret_x (int) - // * caret_y (int) - // They specify the position of the input caret. - IPC_MESSAGE_ROUTED3(ViewHostMsg_ImeUpdateStatus, + // * caret_rect (gfx::Rect) + // They specify the rectangle of the input caret. + IPC_MESSAGE_ROUTED2(ViewHostMsg_ImeUpdateStatus, ViewHostMsg_ImeControl, /* control */ - int, /* caret_x */ - int /* caret_y */) + gfx::Rect /* caret_rect */) // Response for InspectElement request. Returns the number of resources // identified by InspectorController. diff --git a/chrome/renderer/render_widget.cc b/chrome/renderer/render_widget.cc index c8d3070..ab1a270 100644 --- a/chrome/renderer/render_widget.cc +++ b/chrome/renderer/render_widget.cc @@ -667,11 +667,9 @@ void RenderWidget::OnImeSetComposition(int string_type, int target_start, int target_end, const std::wstring& ime_string) { if (webwidget_) { - int string_length = static_cast<int>(ime_string.length()); - const wchar_t* string_data = ime_string.data(); webwidget_->ImeSetComposition(string_type, cursor_position, target_start, target_end, - string_length, string_data); + ime_string); } } @@ -693,17 +691,20 @@ void RenderWidget::UpdateIME() { if (!ime_is_active_) { return; } - // Retrieve the caret position from the focused widget. - bool enable_ime; - int x, y; - const void *id; - if (!webwidget_ || !webwidget_->ImeUpdateStatus(&enable_ime, &id, &x, &y)) { + // Retrieve the caret position from the focused widget and verify we should + // enabled IMEs attached to the browser process. + bool enable_ime = false; + const void* node = NULL; + gfx::Rect caret_rect; + if (!webwidget_ || + !webwidget_->ImeUpdateStatus(&enable_ime, &node, &caret_rect)) { // There are not any editable widgets attached to this process. // We should disable the IME to prevent it from sending CJK strings to // non-editable widgets. ime_control_updated_ = true; ime_control_new_state_ = false; } + ime_control_new_state_ = enable_ime; if (ime_control_updated_) { // The input focus has been changed. // Compare the current state with the updated state and choose actions. @@ -711,20 +712,22 @@ void RenderWidget::UpdateIME() { if (ime_control_new_state_) { // Case 1: a text input -> another text input // Complete the current composition and notify the caret position. - enum ViewHostMsg_ImeControl control = IME_COMPLETE_COMPOSITION; - Send(new ViewHostMsg_ImeUpdateStatus(routing_id(), control, x, y)); + Send(new ViewHostMsg_ImeUpdateStatus(routing_id(), + IME_COMPLETE_COMPOSITION, + caret_rect)); } else { // Case 2: a text input -> a password input (or a static control) // Complete the current composition and disable the IME. - enum ViewHostMsg_ImeControl control = IME_DISABLE; - Send(new ViewHostMsg_ImeUpdateStatus(routing_id(), control, x, y)); + Send(new ViewHostMsg_ImeUpdateStatus(routing_id(), IME_DISABLE, + caret_rect)); } } else { if (ime_control_new_state_) { // Case 3: a password input (or a static control) -> a text input // Enable the IME and notify the caret position. - enum ViewHostMsg_ImeControl control = IME_COMPLETE_COMPOSITION; - Send(new ViewHostMsg_ImeUpdateStatus(routing_id(), control, x, y)); + Send(new ViewHostMsg_ImeUpdateStatus(routing_id(), + IME_COMPLETE_COMPOSITION, + caret_rect)); } else { // Case 4: a password input (or a static contol) -> another password // input (or another static control). @@ -735,17 +738,18 @@ void RenderWidget::UpdateIME() { // The input focus is not changed. // Notify the caret position to a browser process only if it is changed. if (ime_control_enable_ime_) { - if (x != ime_control_x_ || y != ime_control_y_) { - enum ViewHostMsg_ImeControl control = IME_MOVE_WINDOWS; - Send(new ViewHostMsg_ImeUpdateStatus(routing_id(), control, x, y)); + if (caret_rect.x() != ime_control_x_ || + caret_rect.y() != ime_control_y_) { + Send(new ViewHostMsg_ImeUpdateStatus(routing_id(), IME_MOVE_WINDOWS, + caret_rect)); } } } // Save the updated IME status to prevent from sending the same IPC messages. ime_control_updated_ = false; ime_control_enable_ime_ = ime_control_new_state_; - ime_control_x_ = x; - ime_control_y_ = y; + ime_control_x_ = caret_rect.x(); + ime_control_y_ = caret_rect.y(); } void RenderWidget::DidMove(WebWidget* webwidget, |