Index: ui/base/ime/input_method_win.cc |
diff --git a/ui/base/ime/input_method_win.cc b/ui/base/ime/input_method_win.cc |
index df75bb2ff90f40f332ab08c1a00964ae334a753e..e828ae08562d6ed44e118c758438701dd272c262 100644 |
--- a/ui/base/ime/input_method_win.cc |
+++ b/ui/base/ime/input_method_win.cc |
@@ -6,8 +6,10 @@ |
#include "base/auto_reset.h" |
#include "base/basictypes.h" |
+#include "base/command_line.h" |
#include "ui/base/ime/text_input_client.h" |
#include "ui/base/ime/win/tsf_input_scope.h" |
+#include "ui/base/ui_base_switches.h" |
#include "ui/events/event.h" |
#include "ui/events/event_constants.h" |
#include "ui/events/event_utils.h" |
@@ -31,8 +33,7 @@ InputMethodWin::InputMethodWin(internal::InputMethodDelegate* delegate, |
accept_carriage_return_(false), |
enabled_(false), |
is_candidate_popup_open_(false), |
- composing_window_handle_(NULL), |
- suppress_next_char_(false) { |
+ composing_window_handle_(NULL) { |
SetDelegate(delegate); |
} |
@@ -104,14 +105,41 @@ void InputMethodWin::DispatchKeyEvent(ui::KeyEvent* event) { |
} |
const base::NativeEvent& native_key_event = event->native_event(); |
+ BOOL handled = FALSE; |
if (native_key_event.message == WM_CHAR) { |
- BOOL handled; |
OnChar(native_key_event.hwnd, native_key_event.message, |
native_key_event.wParam, native_key_event.lParam, &handled); |
if (handled) |
event->StopPropagation(); |
return; |
} |
+ |
+ std::vector<MSG> char_msgs; |
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
+ switches::kEnableMergeKeyCharEvents)) { |
+ // Combines the WM_KEY* and WM_CHAR messages in the event processing flow |
+ // which is necessary to let Chrome IME extension to process the key event |
+ // and perform corresponding IME actions. |
+ // Chrome IME extension may wants to consume certain key events based on |
+ // the character information of WM_CHAR messages. Holding WM_KEY* messages |
+ // until WM_CHAR is processed by the IME extension is not feasible because |
+ // there is no way to know wether there will or not be a WM_CHAR following |
+ // the WM_KEY*. |
+ // Chrome never handles dead chars so it is safe to remove/ignore |
+ // WM_*DEADCHAR messages. |
+ MSG msg; |
+ while (::PeekMessage(&msg, native_key_event.hwnd, WM_CHAR, WM_DEADCHAR, |
+ PM_REMOVE)) { |
+ if (msg.message == WM_CHAR) |
+ char_msgs.push_back(msg); |
+ } |
+ while (::PeekMessage(&msg, native_key_event.hwnd, WM_SYSCHAR, |
+ WM_SYSDEADCHAR, PM_REMOVE)) { |
+ if (msg.message == WM_SYSCHAR) |
+ char_msgs.push_back(msg); |
+ } |
+ } |
+ |
// Handles ctrl-shift key to change text direction and layout alignment. |
if (ui::IMM32Manager::IsRTLKeyboardLayoutInstalled() && |
!IsTextInputTypeNone()) { |
@@ -135,9 +163,20 @@ void InputMethodWin::DispatchKeyEvent(ui::KeyEvent* event) { |
} |
} |
+ // If only 1 WM_CHAR per the key event, set it as the character of it. |
+ if (char_msgs.size() == 1) |
+ event->set_character(static_cast<base::char16>(char_msgs[0].wParam)); |
+ |
ui::EventDispatchDetails details = DispatchKeyEventPostIME(event); |
- if (!details.dispatcher_destroyed) |
- suppress_next_char_ = event->stopped_propagation(); |
+ if (details.dispatcher_destroyed || details.target_destroyed || |
+ event->stopped_propagation()) { |
+ return; |
+ } |
+ |
+ for (size_t i = 0; i < char_msgs.size(); ++i) { |
+ MSG msg = char_msgs[i]; |
+ OnChar(msg.hwnd, msg.message, msg.wParam, msg.lParam, &handled); |
+ } |
} |
void InputMethodWin::OnTextInputTypeChanged(const TextInputClient* client) { |
@@ -219,11 +258,6 @@ LRESULT InputMethodWin::OnChar(HWND window_handle, |
BOOL* handled) { |
*handled = TRUE; |
- if (suppress_next_char_) { |
- suppress_next_char_ = false; |
- return 0; |
- } |
- |
// We need to send character events to the focused text input client event if |
// its text input type is ui::TEXT_INPUT_TYPE_NONE. |
if (GetTextInputClient()) { |
@@ -554,10 +588,6 @@ bool InputMethodWin::IsWindowFocused(const TextInputClient* client) const { |
void InputMethodWin::DispatchFabricatedKeyEvent(ui::KeyEvent* event) { |
if (event->is_char()) { |
- if (suppress_next_char_) { |
- suppress_next_char_ = false; |
- return; |
- } |
if (GetTextInputClient()) { |
GetTextInputClient()->InsertChar( |
static_cast<base::char16>(event->key_code()), |