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

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, 3 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 "base/profiler/scoped_tracker.h" 10 #include "base/profiler/scoped_tracker.h"
10 #include "ui/base/ime/text_input_client.h" 11 #include "ui/base/ime/text_input_client.h"
11 #include "ui/base/ime/win/tsf_input_scope.h" 12 #include "ui/base/ime/win/tsf_input_scope.h"
13 #include "ui/base/ui_base_switches.h"
12 #include "ui/events/event.h" 14 #include "ui/events/event.h"
13 #include "ui/events/event_constants.h" 15 #include "ui/events/event_constants.h"
14 #include "ui/events/event_utils.h" 16 #include "ui/events/event_utils.h"
15 #include "ui/events/keycodes/keyboard_codes.h" 17 #include "ui/events/keycodes/keyboard_codes.h"
16 #include "ui/gfx/win/dpi.h" 18 #include "ui/gfx/win/dpi.h"
17 #include "ui/gfx/win/hwnd_util.h" 19 #include "ui/gfx/win/hwnd_util.h"
18 20
19 namespace ui { 21 namespace ui {
20 namespace { 22 namespace {
21 23
22 // Extra number of chars before and after selection (or composition) range which 24 // Extra number of chars before and after selection (or composition) range which
23 // is returned to IME for improving conversion accuracy. 25 // is returned to IME for improving conversion accuracy.
24 static const size_t kExtraNumberOfChars = 20; 26 static const size_t kExtraNumberOfChars = 20;
25 27
26 } // namespace 28 } // namespace
27 29
28 InputMethodWin::InputMethodWin(internal::InputMethodDelegate* delegate, 30 InputMethodWin::InputMethodWin(internal::InputMethodDelegate* delegate,
29 HWND toplevel_window_handle) 31 HWND toplevel_window_handle)
30 : toplevel_window_handle_(toplevel_window_handle), 32 : toplevel_window_handle_(toplevel_window_handle),
31 pending_requested_direction_(base::i18n::UNKNOWN_DIRECTION), 33 pending_requested_direction_(base::i18n::UNKNOWN_DIRECTION),
32 accept_carriage_return_(false), 34 accept_carriage_return_(false),
33 enabled_(false), 35 enabled_(false),
34 is_candidate_popup_open_(false), 36 is_candidate_popup_open_(false),
35 composing_window_handle_(NULL), 37 composing_window_handle_(NULL) {
36 suppress_next_char_(false) {
37 SetDelegate(delegate); 38 SetDelegate(delegate);
38 } 39 }
39 40
40 void InputMethodWin::OnFocus() { 41 void InputMethodWin::OnFocus() {
41 InputMethodBase::OnFocus(); 42 InputMethodBase::OnFocus();
42 if (GetTextInputClient()) 43 if (GetTextInputClient())
43 UpdateIMEState(); 44 UpdateIMEState();
44 } 45 }
45 46
46 void InputMethodWin::OnBlur() { 47 void InputMethodWin::OnBlur() {
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
98 return !!handled; 99 return !!handled;
99 } 100 }
100 101
101 void InputMethodWin::DispatchKeyEvent(ui::KeyEvent* event) { 102 void InputMethodWin::DispatchKeyEvent(ui::KeyEvent* event) {
102 if (!event->HasNativeEvent()) { 103 if (!event->HasNativeEvent()) {
103 DispatchFabricatedKeyEvent(event); 104 DispatchFabricatedKeyEvent(event);
104 return; 105 return;
105 } 106 }
106 107
107 const base::NativeEvent& native_key_event = event->native_event(); 108 const base::NativeEvent& native_key_event = event->native_event();
109 BOOL handled = FALSE;
108 if (native_key_event.message == WM_CHAR) { 110 if (native_key_event.message == WM_CHAR) {
109 BOOL handled;
110 OnChar(native_key_event.hwnd, native_key_event.message, 111 OnChar(native_key_event.hwnd, native_key_event.message,
111 native_key_event.wParam, native_key_event.lParam, &handled); 112 native_key_event.wParam, native_key_event.lParam, &handled);
112 if (handled) 113 if (handled)
113 event->StopPropagation(); 114 event->StopPropagation();
114 return; 115 return;
115 } 116 }
117
118 std::vector<MSG> char_msgs;
119 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
120 switches::kEnableMergeKeyCharEvents)) {
121 // Combines the WM_KEY* and WM_CHAR messages in the event processing flow
122 // which is necessary to let Chrome IME extension to process the key event
123 // and perform corresponding IME actions.
124 // Chrome IME extension may wants to consume certain key events based on
125 // the character information of WM_CHAR messages. Holding WM_KEY* messages
126 // until WM_CHAR is processed by the IME extension is not feasible because
127 // there is no way to know wether there will or not be a WM_CHAR following
128 // the WM_KEY*.
129 // Chrome never handles dead chars so it is safe to remove/ignore
130 // WM_*DEADCHAR messages.
131 MSG msg;
132 while (::PeekMessage(&msg, native_key_event.hwnd, WM_CHAR, WM_DEADCHAR,
133 PM_REMOVE)) {
134 if (msg.message == WM_CHAR)
135 char_msgs.push_back(msg);
136 }
137 while (::PeekMessage(&msg, native_key_event.hwnd, WM_SYSCHAR,
138 WM_SYSDEADCHAR, PM_REMOVE)) {
139 if (msg.message == WM_SYSCHAR)
140 char_msgs.push_back(msg);
141 }
142 }
143
116 // Handles ctrl-shift key to change text direction and layout alignment. 144 // Handles ctrl-shift key to change text direction and layout alignment.
117 if (ui::IMM32Manager::IsRTLKeyboardLayoutInstalled() && 145 if (ui::IMM32Manager::IsRTLKeyboardLayoutInstalled() &&
118 !IsTextInputTypeNone()) { 146 !IsTextInputTypeNone()) {
119 // TODO: shouldn't need to generate a KeyEvent here. 147 // TODO: shouldn't need to generate a KeyEvent here.
120 const ui::KeyEvent key(native_key_event); 148 const ui::KeyEvent key(native_key_event);
121 ui::KeyboardCode code = key.key_code(); 149 ui::KeyboardCode code = key.key_code();
122 if (key.type() == ui::ET_KEY_PRESSED) { 150 if (key.type() == ui::ET_KEY_PRESSED) {
123 if (code == ui::VKEY_SHIFT) { 151 if (code == ui::VKEY_SHIFT) {
124 base::i18n::TextDirection dir; 152 base::i18n::TextDirection dir;
125 if (ui::IMM32Manager::IsCtrlShiftPressed(&dir)) 153 if (ui::IMM32Manager::IsCtrlShiftPressed(&dir))
126 pending_requested_direction_ = dir; 154 pending_requested_direction_ = dir;
127 } else if (code != ui::VKEY_CONTROL) { 155 } else if (code != ui::VKEY_CONTROL) {
128 pending_requested_direction_ = base::i18n::UNKNOWN_DIRECTION; 156 pending_requested_direction_ = base::i18n::UNKNOWN_DIRECTION;
129 } 157 }
130 } else if (key.type() == ui::ET_KEY_RELEASED && 158 } else if (key.type() == ui::ET_KEY_RELEASED &&
131 (code == ui::VKEY_SHIFT || code == ui::VKEY_CONTROL) && 159 (code == ui::VKEY_SHIFT || code == ui::VKEY_CONTROL) &&
132 pending_requested_direction_ != base::i18n::UNKNOWN_DIRECTION) { 160 pending_requested_direction_ != base::i18n::UNKNOWN_DIRECTION) {
133 GetTextInputClient()->ChangeTextDirectionAndLayoutAlignment( 161 GetTextInputClient()->ChangeTextDirectionAndLayoutAlignment(
134 pending_requested_direction_); 162 pending_requested_direction_);
135 pending_requested_direction_ = base::i18n::UNKNOWN_DIRECTION; 163 pending_requested_direction_ = base::i18n::UNKNOWN_DIRECTION;
136 } 164 }
137 } 165 }
138 166
167 // If only 1 WM_CHAR per the key event, set it as the character of it.
168 if (char_msgs.size() == 1)
169 event->set_character(static_cast<base::char16>(char_msgs[0].wParam));
ananta 2015/09/22 19:27:30 Is this code correct?. The wParams in WM_KEYDOWN a
Shu Chen 2015/09/23 05:21:09 This code is correct. WM_CHAR's wParam carries the
170
139 ui::EventDispatchDetails details = DispatchKeyEventPostIME(event); 171 ui::EventDispatchDetails details = DispatchKeyEventPostIME(event);
140 if (!details.dispatcher_destroyed) 172 if (details.dispatcher_destroyed || details.target_destroyed ||
141 suppress_next_char_ = event->stopped_propagation(); 173 event->stopped_propagation()) {
174 return;
175 }
176
177 for (size_t i = 0; i < char_msgs.size(); ++i) {
178 MSG msg = char_msgs[i];
179 OnChar(msg.hwnd, msg.message, msg.wParam, msg.lParam, &handled);
180 }
142 } 181 }
143 182
144 void InputMethodWin::OnTextInputTypeChanged(const TextInputClient* client) { 183 void InputMethodWin::OnTextInputTypeChanged(const TextInputClient* client) {
145 if (!IsTextInputClientFocused(client) || !IsWindowFocused(client)) 184 if (!IsTextInputClientFocused(client) || !IsWindowFocused(client))
146 return; 185 return;
147 imm32_manager_.CancelIME(toplevel_window_handle_); 186 imm32_manager_.CancelIME(toplevel_window_handle_);
148 UpdateIMEState(); 187 UpdateIMEState();
149 } 188 }
150 189
151 void InputMethodWin::OnCaretBoundsChanged(const TextInputClient* client) { 190 void InputMethodWin::OnCaretBoundsChanged(const TextInputClient* client) {
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
217 UINT message, 256 UINT message,
218 WPARAM wparam, 257 WPARAM wparam,
219 LPARAM lparam, 258 LPARAM lparam,
220 BOOL* handled) { 259 BOOL* handled) {
221 // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed. 260 // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
222 tracked_objects::ScopedTracker tracking_profile( 261 tracked_objects::ScopedTracker tracking_profile(
223 FROM_HERE_WITH_EXPLICIT_FUNCTION("440919 InputMethodWin::OnChar")); 262 FROM_HERE_WITH_EXPLICIT_FUNCTION("440919 InputMethodWin::OnChar"));
224 263
225 *handled = TRUE; 264 *handled = TRUE;
226 265
227 if (suppress_next_char_) {
228 suppress_next_char_ = false;
229 return 0;
230 }
231
232 // We need to send character events to the focused text input client event if 266 // We need to send character events to the focused text input client event if
233 // its text input type is ui::TEXT_INPUT_TYPE_NONE. 267 // its text input type is ui::TEXT_INPUT_TYPE_NONE.
234 if (GetTextInputClient()) { 268 if (GetTextInputClient()) {
235 const base::char16 kCarriageReturn = L'\r'; 269 const base::char16 kCarriageReturn = L'\r';
236 const base::char16 ch = static_cast<base::char16>(wparam); 270 const base::char16 ch = static_cast<base::char16>(wparam);
237 // A mask to determine the previous key state from |lparam|. The value is 1 271 // A mask to determine the previous key state from |lparam|. The value is 1
238 // if the key is down before the message is sent, or it is 0 if the key is 272 // if the key is down before the message is sent, or it is 0 if the key is
239 // up. 273 // up.
240 const uint32 kPrevKeyDownBit = 0x40000000; 274 const uint32 kPrevKeyDownBit = 0x40000000;
241 if (ch == kCarriageReturn && !(lparam & kPrevKeyDownBit)) 275 if (ch == kCarriageReturn && !(lparam & kPrevKeyDownBit))
(...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after
580 // window. So we can safely assume that |attached_window_handle| is ready for 614 // window. So we can safely assume that |attached_window_handle| is ready for
581 // receiving keyboard input as long as it is an active window. This works well 615 // receiving keyboard input as long as it is an active window. This works well
582 // even when the |attached_window_handle| becomes active but has not received 616 // even when the |attached_window_handle| becomes active but has not received
583 // WM_FOCUS yet. 617 // WM_FOCUS yet.
584 return toplevel_window_handle_ && 618 return toplevel_window_handle_ &&
585 GetActiveWindow() == toplevel_window_handle_; 619 GetActiveWindow() == toplevel_window_handle_;
586 } 620 }
587 621
588 void InputMethodWin::DispatchFabricatedKeyEvent(ui::KeyEvent* event) { 622 void InputMethodWin::DispatchFabricatedKeyEvent(ui::KeyEvent* event) {
589 if (event->is_char()) { 623 if (event->is_char()) {
590 if (suppress_next_char_) {
591 suppress_next_char_ = false;
592 return;
593 }
594 if (GetTextInputClient()) { 624 if (GetTextInputClient()) {
595 GetTextInputClient()->InsertChar( 625 GetTextInputClient()->InsertChar(
596 static_cast<base::char16>(event->key_code()), 626 static_cast<base::char16>(event->key_code()),
597 ui::GetModifiersFromKeyState()); 627 ui::GetModifiersFromKeyState());
598 return; 628 return;
599 } 629 }
600 } 630 }
601 ignore_result(DispatchKeyEventPostIME(event)); 631 ignore_result(DispatchKeyEventPostIME(event));
602 } 632 }
603 633
(...skipping 27 matching lines...) Expand all
631 enabled_ = true; 661 enabled_ = true;
632 break; 662 break;
633 } 663 }
634 664
635 imm32_manager_.SetTextInputMode(window_handle, text_input_mode); 665 imm32_manager_.SetTextInputMode(window_handle, text_input_mode);
636 tsf_inputscope::SetInputScopeForTsfUnawareWindow( 666 tsf_inputscope::SetInputScopeForTsfUnawareWindow(
637 window_handle, text_input_type, text_input_mode); 667 window_handle, text_input_type, text_input_mode);
638 } 668 }
639 669
640 } // namespace ui 670 } // 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