summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorhbono@chromium.org <hbono@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2008-11-06 07:40:53 +0000
committerhbono@chromium.org <hbono@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2008-11-06 07:40:53 +0000
commit34f6bc1937fe617875e8f5e95485904569cca582 (patch)
tree94f201b6bb78ff601a8a97783f4ac0134423af48 /chrome
parent576d8bff4e6778c6de60b8a7269a78c5e8bf602a (diff)
downloadchromium_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.cc37
-rw-r--r--chrome/browser/ime_input.h16
-rw-r--r--chrome/browser/render_widget_host.cc4
-rw-r--r--chrome/browser/render_widget_host.h3
-rw-r--r--chrome/browser/render_widget_host_view.h3
-rw-r--r--chrome/browser/render_widget_host_view_win.cc5
-rw-r--r--chrome/browser/render_widget_host_view_win.h3
-rw-r--r--chrome/browser/web_contents_unittest.cc3
-rw-r--r--chrome/common/render_messages_internal.h14
-rw-r--r--chrome/renderer/render_widget.cc42
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,