Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(513)

Side by Side Diff: ui/base/ime/input_method_win.cc

Issue 1267483003: Combine the WM_CHAR with WM_KEY* for key event flow. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « ui/base/ime/input_method_win.h ('k') | ui/base/ui_base_switches.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/base/ime/input_method_win.h" 5 #include "ui/base/ime/input_method_win.h"
6 6
7 #include "base/auto_reset.h" 7 #include "base/auto_reset.h"
8 #include "base/basictypes.h" 8 #include "base/basictypes.h"
9 #include "base/command_line.h"
9 #include "ui/base/ime/text_input_client.h" 10 #include "ui/base/ime/text_input_client.h"
10 #include "ui/base/ime/win/tsf_input_scope.h" 11 #include "ui/base/ime/win/tsf_input_scope.h"
12 #include "ui/base/ui_base_switches.h"
11 #include "ui/events/event.h" 13 #include "ui/events/event.h"
12 #include "ui/events/event_constants.h" 14 #include "ui/events/event_constants.h"
13 #include "ui/events/event_utils.h" 15 #include "ui/events/event_utils.h"
14 #include "ui/events/keycodes/keyboard_codes.h" 16 #include "ui/events/keycodes/keyboard_codes.h"
15 #include "ui/gfx/win/dpi.h" 17 #include "ui/gfx/win/dpi.h"
16 #include "ui/gfx/win/hwnd_util.h" 18 #include "ui/gfx/win/hwnd_util.h"
17 19
18 namespace ui { 20 namespace ui {
19 namespace { 21 namespace {
20 22
21 // Extra number of chars before and after selection (or composition) range which 23 // Extra number of chars before and after selection (or composition) range which
22 // is returned to IME for improving conversion accuracy. 24 // is returned to IME for improving conversion accuracy.
23 static const size_t kExtraNumberOfChars = 20; 25 static const size_t kExtraNumberOfChars = 20;
24 26
25 } // namespace 27 } // namespace
26 28
27 InputMethodWin::InputMethodWin(internal::InputMethodDelegate* delegate, 29 InputMethodWin::InputMethodWin(internal::InputMethodDelegate* delegate,
28 HWND toplevel_window_handle) 30 HWND toplevel_window_handle)
29 : toplevel_window_handle_(toplevel_window_handle), 31 : toplevel_window_handle_(toplevel_window_handle),
30 pending_requested_direction_(base::i18n::UNKNOWN_DIRECTION), 32 pending_requested_direction_(base::i18n::UNKNOWN_DIRECTION),
31 accept_carriage_return_(false), 33 accept_carriage_return_(false),
32 enabled_(false), 34 enabled_(false),
33 is_candidate_popup_open_(false), 35 is_candidate_popup_open_(false),
34 composing_window_handle_(NULL), 36 composing_window_handle_(NULL) {
35 suppress_next_char_(false) {
36 SetDelegate(delegate); 37 SetDelegate(delegate);
37 } 38 }
38 39
39 void InputMethodWin::OnFocus() { 40 void InputMethodWin::OnFocus() {
40 InputMethodBase::OnFocus(); 41 InputMethodBase::OnFocus();
41 if (GetTextInputClient()) 42 if (GetTextInputClient())
42 UpdateIMEState(); 43 UpdateIMEState();
43 } 44 }
44 45
45 void InputMethodWin::OnBlur() { 46 void InputMethodWin::OnBlur() {
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
97 return !!handled; 98 return !!handled;
98 } 99 }
99 100
100 void InputMethodWin::DispatchKeyEvent(ui::KeyEvent* event) { 101 void InputMethodWin::DispatchKeyEvent(ui::KeyEvent* event) {
101 if (!event->HasNativeEvent()) { 102 if (!event->HasNativeEvent()) {
102 DispatchFabricatedKeyEvent(event); 103 DispatchFabricatedKeyEvent(event);
103 return; 104 return;
104 } 105 }
105 106
106 const base::NativeEvent& native_key_event = event->native_event(); 107 const base::NativeEvent& native_key_event = event->native_event();
108 BOOL handled = FALSE;
107 if (native_key_event.message == WM_CHAR) { 109 if (native_key_event.message == WM_CHAR) {
108 BOOL handled;
109 OnChar(native_key_event.hwnd, native_key_event.message, 110 OnChar(native_key_event.hwnd, native_key_event.message,
110 native_key_event.wParam, native_key_event.lParam, &handled); 111 native_key_event.wParam, native_key_event.lParam, &handled);
111 if (handled) 112 if (handled)
112 event->StopPropagation(); 113 event->StopPropagation();
113 return; 114 return;
114 } 115 }
116
117 std::vector<MSG> char_msgs;
118 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
119 switches::kEnableMergeKeyCharEvents)) {
120 // Combines the WM_KEY* and WM_CHAR messages in the event processing flow
121 // which is necessary to let Chrome IME extension to process the key event
122 // and perform corresponding IME actions.
123 // Chrome IME extension may wants to consume certain key events based on
124 // the character information of WM_CHAR messages. Holding WM_KEY* messages
125 // until WM_CHAR is processed by the IME extension is not feasible because
126 // there is no way to know wether there will or not be a WM_CHAR following
127 // the WM_KEY*.
128 // Chrome never handles dead chars so it is safe to remove/ignore
129 // WM_*DEADCHAR messages.
130 MSG msg;
131 while (::PeekMessage(&msg, native_key_event.hwnd, WM_CHAR, WM_DEADCHAR,
132 PM_REMOVE)) {
133 if (msg.message == WM_CHAR)
134 char_msgs.push_back(msg);
135 }
136 while (::PeekMessage(&msg, native_key_event.hwnd, WM_SYSCHAR,
137 WM_SYSDEADCHAR, PM_REMOVE)) {
138 if (msg.message == WM_SYSCHAR)
139 char_msgs.push_back(msg);
140 }
141 }
142
115 // Handles ctrl-shift key to change text direction and layout alignment. 143 // Handles ctrl-shift key to change text direction and layout alignment.
116 if (ui::IMM32Manager::IsRTLKeyboardLayoutInstalled() && 144 if (ui::IMM32Manager::IsRTLKeyboardLayoutInstalled() &&
117 !IsTextInputTypeNone()) { 145 !IsTextInputTypeNone()) {
118 // TODO: shouldn't need to generate a KeyEvent here. 146 // TODO: shouldn't need to generate a KeyEvent here.
119 const ui::KeyEvent key(native_key_event); 147 const ui::KeyEvent key(native_key_event);
120 ui::KeyboardCode code = key.key_code(); 148 ui::KeyboardCode code = key.key_code();
121 if (key.type() == ui::ET_KEY_PRESSED) { 149 if (key.type() == ui::ET_KEY_PRESSED) {
122 if (code == ui::VKEY_SHIFT) { 150 if (code == ui::VKEY_SHIFT) {
123 base::i18n::TextDirection dir; 151 base::i18n::TextDirection dir;
124 if (ui::IMM32Manager::IsCtrlShiftPressed(&dir)) 152 if (ui::IMM32Manager::IsCtrlShiftPressed(&dir))
125 pending_requested_direction_ = dir; 153 pending_requested_direction_ = dir;
126 } else if (code != ui::VKEY_CONTROL) { 154 } else if (code != ui::VKEY_CONTROL) {
127 pending_requested_direction_ = base::i18n::UNKNOWN_DIRECTION; 155 pending_requested_direction_ = base::i18n::UNKNOWN_DIRECTION;
128 } 156 }
129 } else if (key.type() == ui::ET_KEY_RELEASED && 157 } else if (key.type() == ui::ET_KEY_RELEASED &&
130 (code == ui::VKEY_SHIFT || code == ui::VKEY_CONTROL) && 158 (code == ui::VKEY_SHIFT || code == ui::VKEY_CONTROL) &&
131 pending_requested_direction_ != base::i18n::UNKNOWN_DIRECTION) { 159 pending_requested_direction_ != base::i18n::UNKNOWN_DIRECTION) {
132 GetTextInputClient()->ChangeTextDirectionAndLayoutAlignment( 160 GetTextInputClient()->ChangeTextDirectionAndLayoutAlignment(
133 pending_requested_direction_); 161 pending_requested_direction_);
134 pending_requested_direction_ = base::i18n::UNKNOWN_DIRECTION; 162 pending_requested_direction_ = base::i18n::UNKNOWN_DIRECTION;
135 } 163 }
136 } 164 }
137 165
166 // If only 1 WM_CHAR per the key event, set it as the character of it.
167 if (char_msgs.size() == 1)
168 event->set_character(static_cast<base::char16>(char_msgs[0].wParam));
169
138 ui::EventDispatchDetails details = DispatchKeyEventPostIME(event); 170 ui::EventDispatchDetails details = DispatchKeyEventPostIME(event);
139 if (!details.dispatcher_destroyed) 171 if (details.dispatcher_destroyed || details.target_destroyed ||
140 suppress_next_char_ = event->stopped_propagation(); 172 event->stopped_propagation()) {
173 return;
174 }
175
176 for (size_t i = 0; i < char_msgs.size(); ++i) {
177 MSG msg = char_msgs[i];
178 OnChar(msg.hwnd, msg.message, msg.wParam, msg.lParam, &handled);
179 }
141 } 180 }
142 181
143 void InputMethodWin::OnTextInputTypeChanged(const TextInputClient* client) { 182 void InputMethodWin::OnTextInputTypeChanged(const TextInputClient* client) {
144 if (!IsTextInputClientFocused(client) || !IsWindowFocused(client)) 183 if (!IsTextInputClientFocused(client) || !IsWindowFocused(client))
145 return; 184 return;
146 imm32_manager_.CancelIME(toplevel_window_handle_); 185 imm32_manager_.CancelIME(toplevel_window_handle_);
147 UpdateIMEState(); 186 UpdateIMEState();
148 } 187 }
149 188
150 void InputMethodWin::OnCaretBoundsChanged(const TextInputClient* client) { 189 void InputMethodWin::OnCaretBoundsChanged(const TextInputClient* client) {
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
212 accept_carriage_return_ = false; 251 accept_carriage_return_ = false;
213 } 252 }
214 253
215 LRESULT InputMethodWin::OnChar(HWND window_handle, 254 LRESULT InputMethodWin::OnChar(HWND window_handle,
216 UINT message, 255 UINT message,
217 WPARAM wparam, 256 WPARAM wparam,
218 LPARAM lparam, 257 LPARAM lparam,
219 BOOL* handled) { 258 BOOL* handled) {
220 *handled = TRUE; 259 *handled = TRUE;
221 260
222 if (suppress_next_char_) {
223 suppress_next_char_ = false;
224 return 0;
225 }
226
227 // We need to send character events to the focused text input client event if 261 // We need to send character events to the focused text input client event if
228 // its text input type is ui::TEXT_INPUT_TYPE_NONE. 262 // its text input type is ui::TEXT_INPUT_TYPE_NONE.
229 if (GetTextInputClient()) { 263 if (GetTextInputClient()) {
230 const base::char16 kCarriageReturn = L'\r'; 264 const base::char16 kCarriageReturn = L'\r';
231 const base::char16 ch = static_cast<base::char16>(wparam); 265 const base::char16 ch = static_cast<base::char16>(wparam);
232 // A mask to determine the previous key state from |lparam|. The value is 1 266 // A mask to determine the previous key state from |lparam|. The value is 1
233 // if the key is down before the message is sent, or it is 0 if the key is 267 // if the key is down before the message is sent, or it is 0 if the key is
234 // up. 268 // up.
235 const uint32 kPrevKeyDownBit = 0x40000000; 269 const uint32 kPrevKeyDownBit = 0x40000000;
236 if (ch == kCarriageReturn && !(lparam & kPrevKeyDownBit)) 270 if (ch == kCarriageReturn && !(lparam & kPrevKeyDownBit))
(...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after
547 // window. So we can safely assume that |attached_window_handle| is ready for 581 // window. So we can safely assume that |attached_window_handle| is ready for
548 // receiving keyboard input as long as it is an active window. This works well 582 // receiving keyboard input as long as it is an active window. This works well
549 // even when the |attached_window_handle| becomes active but has not received 583 // even when the |attached_window_handle| becomes active but has not received
550 // WM_FOCUS yet. 584 // WM_FOCUS yet.
551 return toplevel_window_handle_ && 585 return toplevel_window_handle_ &&
552 GetActiveWindow() == toplevel_window_handle_; 586 GetActiveWindow() == toplevel_window_handle_;
553 } 587 }
554 588
555 void InputMethodWin::DispatchFabricatedKeyEvent(ui::KeyEvent* event) { 589 void InputMethodWin::DispatchFabricatedKeyEvent(ui::KeyEvent* event) {
556 if (event->is_char()) { 590 if (event->is_char()) {
557 if (suppress_next_char_) {
558 suppress_next_char_ = false;
559 return;
560 }
561 if (GetTextInputClient()) { 591 if (GetTextInputClient()) {
562 GetTextInputClient()->InsertChar( 592 GetTextInputClient()->InsertChar(
563 static_cast<base::char16>(event->key_code()), 593 static_cast<base::char16>(event->key_code()),
564 ui::GetModifiersFromKeyState()); 594 ui::GetModifiersFromKeyState());
565 return; 595 return;
566 } 596 }
567 } 597 }
568 ignore_result(DispatchKeyEventPostIME(event)); 598 ignore_result(DispatchKeyEventPostIME(event));
569 } 599 }
570 600
(...skipping 27 matching lines...) Expand all
598 enabled_ = true; 628 enabled_ = true;
599 break; 629 break;
600 } 630 }
601 631
602 imm32_manager_.SetTextInputMode(window_handle, text_input_mode); 632 imm32_manager_.SetTextInputMode(window_handle, text_input_mode);
603 tsf_inputscope::SetInputScopeForTsfUnawareWindow( 633 tsf_inputscope::SetInputScopeForTsfUnawareWindow(
604 window_handle, text_input_type, text_input_mode); 634 window_handle, text_input_type, text_input_mode);
605 } 635 }
606 636
607 } // namespace ui 637 } // namespace ui
OLDNEW
« no previous file with comments | « ui/base/ime/input_method_win.h ('k') | ui/base/ui_base_switches.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698