summaryrefslogtreecommitdiffstats
path: root/ui
diff options
context:
space:
mode:
authorshuchen <shuchen@chromium.org>2015-10-08 11:43:07 -0700
committerCommit bot <commit-bot@chromium.org>2015-10-08 18:44:10 +0000
commitcb0b75575e1ebab71e76aaeb8784c18f95c0c145 (patch)
tree17f3b88d47d90936df443e50c95bfa14a6c6b5e9 /ui
parent2a9e4d1100e6b15d591f193c152bb705774c9c38 (diff)
downloadchromium_src-cb0b75575e1ebab71e76aaeb8784c18f95c0c145.zip
chromium_src-cb0b75575e1ebab71e76aaeb8784c18f95c0c145.tar.gz
chromium_src-cb0b75575e1ebab71e76aaeb8784c18f95c0c145.tar.bz2
Combine the WM_CHAR with WM_KEY* for key event flow.
The combination is required for Chrome IMEs, which can do IME related actions based on the single event. 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*. What's more, with the combination, ui::KeyEvent::is_char() can be removed, can reduce the complexity for key event handling. This cl will change a little for the order of message handling. e.g. Original: - WM_KEYDOWN received in message pump. - TranslateMessage is called from message pump. - WM_KEYDOWN is dispatched to HWNDMessageHandler. - WM_KEYDOWN is dispatched to Chrome by IMF. With this cl: - WM_KEYDOWN received in message pump. - WM_KEYDOWN is dispatched to HWNDMessageHandler. - TranslateMessage is called from IMF. - WM_KEYDOWN is dispatched to Chrome by IMF. Also, this cl makes WM_CHAR messages (generated by WM_KEY*) never hit message pump & HWNDMessageHandler. Note: the behavior changes by this cl is behind the flag merge-key-char-events, and the flag default is "disabled". TBR=isherman@chromium.org BUG=517773 TEST=No regressions for text inputing (including dead keys & CJK IMEs) in Windows 7 and Windows 8 metro. Review URL: https://codereview.chromium.org/1267483003 Cr-Commit-Position: refs/heads/master@{#353106}
Diffstat (limited to 'ui')
-rw-r--r--ui/base/ime/input_method_win.cc58
-rw-r--r--ui/base/ime/input_method_win.h4
-rw-r--r--ui/base/ui_base_switches.cc8
-rw-r--r--ui/base/ui_base_switches.h5
4 files changed, 57 insertions, 18 deletions
diff --git a/ui/base/ime/input_method_win.cc b/ui/base/ime/input_method_win.cc
index df75bb2..e828ae0 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()),
diff --git a/ui/base/ime/input_method_win.h b/ui/base/ime/input_method_win.h
index 4814f26..7cc347a 100644
--- a/ui/base/ime/input_method_win.h
+++ b/ui/base/ime/input_method_win.h
@@ -129,10 +129,6 @@ class UI_BASE_IME_EXPORT InputMethodWin : public InputMethodBase {
// composition.
HWND composing_window_handle_;
- // Set to true to suppress the next WM_CHAR, when the WM_KEYDOWN gets stopped
- // propagation (e.g. triggered an accelerator).
- bool suppress_next_char_;
-
DISALLOW_COPY_AND_ASSIGN(InputMethodWin);
};
diff --git a/ui/base/ui_base_switches.cc b/ui/base/ui_base_switches.cc
index dd98536..db9c274 100644
--- a/ui/base/ui_base_switches.cc
+++ b/ui/base/ui_base_switches.cc
@@ -19,6 +19,14 @@ const char kDisableRemoteCoreAnimation[] = "disable-remote-core-animation";
const char kShowMacOverlayBorders[] = "show-mac-overlay-borders";
#endif
+#if defined(OS_WIN)
+// Disables merging the key event (WM_KEY*) with the char event (WM_CHAR).
+const char kDisableMergeKeyCharEvents[] = "disable-merge-key-char-events";
+
+// Enables merging the key event (WM_KEY*) with the char event (WM_CHAR).
+const char kEnableMergeKeyCharEvents[] = "enable-merge-key-char-events";
+#endif
+
// Disables use of DWM composition for top level windows.
const char kDisableDwmComposition[] = "disable-dwm-composition";
diff --git a/ui/base/ui_base_switches.h b/ui/base/ui_base_switches.h
index 5b55fa7..0c02dbc 100644
--- a/ui/base/ui_base_switches.h
+++ b/ui/base/ui_base_switches.h
@@ -18,6 +18,11 @@ UI_BASE_EXPORT extern const char kDisableRemoteCoreAnimation[];
UI_BASE_EXPORT extern const char kShowMacOverlayBorders[];
#endif
+#if defined(OS_WIN)
+UI_BASE_EXPORT extern const char kDisableMergeKeyCharEvents[];
+UI_BASE_EXPORT extern const char kEnableMergeKeyCharEvents[];
+#endif
+
UI_BASE_EXPORT extern const char kDisableDwmComposition[];
UI_BASE_EXPORT extern const char kDisableIconNtp[];
UI_BASE_EXPORT extern const char kDisableTouchAdjustment[];