OLD | NEW |
---|---|
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 <stddef.h> | 7 #include <stddef.h> |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 | 9 |
10 #include "base/auto_reset.h" | 10 #include "base/auto_reset.h" |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
93 default: | 93 default: |
94 NOTREACHED() << "Unknown IME message:" << event.message; | 94 NOTREACHED() << "Unknown IME message:" << event.message; |
95 break; | 95 break; |
96 } | 96 } |
97 if (result) | 97 if (result) |
98 *result = original_result; | 98 *result = original_result; |
99 return !!handled; | 99 return !!handled; |
100 } | 100 } |
101 | 101 |
102 void InputMethodWin::DispatchKeyEvent(ui::KeyEvent* event) { | 102 void InputMethodWin::DispatchKeyEvent(ui::KeyEvent* event) { |
103 if (!event->HasNativeEvent()) { | 103 std::vector<MSG> char_msgs; |
104 DispatchFabricatedKeyEvent(event); | 104 if (event->HasNativeEvent()) { |
105 return; | 105 const base::NativeEvent& native_key_event = event->native_event(); |
106 } | 106 BOOL handled = FALSE; |
107 if (native_key_event.message == WM_CHAR) { | |
108 OnChar(native_key_event.hwnd, native_key_event.message, | |
109 native_key_event.wParam, native_key_event.lParam, native_key_event, | |
110 &handled); | |
111 if (handled) | |
112 event->StopPropagation(); | |
113 return; | |
114 } | |
107 | 115 |
108 const base::NativeEvent& native_key_event = event->native_event(); | 116 if (!base::CommandLine::ForCurrentProcess()->HasSwitch( |
109 BOOL handled = FALSE; | 117 switches::kDisableMergeKeyCharEvents)) { |
110 if (native_key_event.message == WM_CHAR) { | 118 // Combines the WM_KEY* and WM_CHAR messages in the event processing flow |
111 OnChar(native_key_event.hwnd, native_key_event.message, | 119 // which is necessary to let Chrome IME extension to process the key event |
112 native_key_event.wParam, native_key_event.lParam, native_key_event, | 120 // and perform corresponding IME actions. |
113 &handled); | 121 // Chrome IME extension may wants to consume certain key events based on |
114 if (handled) | 122 // the character information of WM_CHAR messages. Holding WM_KEY* messages |
115 event->StopPropagation(); | 123 // until WM_CHAR is processed by the IME extension is not feasible because |
116 return; | 124 // there is no way to know wether there will or not be a WM_CHAR following |
117 } | 125 // the WM_KEY*. |
126 // Chrome never handles dead chars so it is safe to remove/ignore | |
127 // WM_*DEADCHAR messages. | |
128 MSG msg; | |
129 while (::PeekMessage(&msg, native_key_event.hwnd, WM_CHAR, WM_DEADCHAR, | |
130 PM_REMOVE)) { | |
131 if (msg.message == WM_CHAR) | |
132 char_msgs.push_back(msg); | |
133 } | |
134 while (::PeekMessage(&msg, native_key_event.hwnd, WM_SYSCHAR, | |
135 WM_SYSDEADCHAR, PM_REMOVE)) { | |
136 if (msg.message == WM_SYSCHAR) | |
137 char_msgs.push_back(msg); | |
138 } | |
139 } | |
118 | 140 |
119 std::vector<MSG> char_msgs; | 141 // Handles ctrl-shift key to change text direction and layout alignment. |
120 if (!base::CommandLine::ForCurrentProcess()->HasSwitch( | 142 if (ui::IMM32Manager::IsRTLKeyboardLayoutInstalled() && |
121 switches::kDisableMergeKeyCharEvents)) { | 143 !IsTextInputTypeNone()) { |
122 // Combines the WM_KEY* and WM_CHAR messages in the event processing flow | 144 // TODO: shouldn't need to generate a KeyEvent here. |
123 // which is necessary to let Chrome IME extension to process the key event | 145 const ui::KeyEvent key(native_key_event); |
124 // and perform corresponding IME actions. | 146 ui::KeyboardCode code = key.key_code(); |
125 // Chrome IME extension may wants to consume certain key events based on | 147 if (key.type() == ui::ET_KEY_PRESSED) { |
126 // the character information of WM_CHAR messages. Holding WM_KEY* messages | 148 if (code == ui::VKEY_SHIFT) { |
127 // until WM_CHAR is processed by the IME extension is not feasible because | 149 base::i18n::TextDirection dir; |
128 // there is no way to know wether there will or not be a WM_CHAR following | 150 if (ui::IMM32Manager::IsCtrlShiftPressed(&dir)) |
129 // the WM_KEY*. | 151 pending_requested_direction_ = dir; |
130 // Chrome never handles dead chars so it is safe to remove/ignore | 152 } else if (code != ui::VKEY_CONTROL) { |
131 // WM_*DEADCHAR messages. | 153 pending_requested_direction_ = base::i18n::UNKNOWN_DIRECTION; |
132 MSG msg; | 154 } |
133 while (::PeekMessage(&msg, native_key_event.hwnd, WM_CHAR, WM_DEADCHAR, | 155 } else if (key.type() == ui::ET_KEY_RELEASED && |
134 PM_REMOVE)) { | 156 (code == ui::VKEY_SHIFT || code == ui::VKEY_CONTROL) && |
135 if (msg.message == WM_CHAR) | 157 pending_requested_direction_ != |
136 char_msgs.push_back(msg); | 158 base::i18n::UNKNOWN_DIRECTION) { |
137 } | 159 GetTextInputClient()->ChangeTextDirectionAndLayoutAlignment( |
138 while (::PeekMessage(&msg, native_key_event.hwnd, WM_SYSCHAR, | 160 pending_requested_direction_); |
139 WM_SYSDEADCHAR, PM_REMOVE)) { | 161 pending_requested_direction_ = base::i18n::UNKNOWN_DIRECTION; |
140 if (msg.message == WM_SYSCHAR) | 162 } |
141 char_msgs.push_back(msg); | |
142 } | 163 } |
143 } | 164 } |
144 | 165 |
145 // Handles ctrl-shift key to change text direction and layout alignment. | |
146 if (ui::IMM32Manager::IsRTLKeyboardLayoutInstalled() && | |
147 !IsTextInputTypeNone()) { | |
148 // TODO: shouldn't need to generate a KeyEvent here. | |
149 const ui::KeyEvent key(native_key_event); | |
150 ui::KeyboardCode code = key.key_code(); | |
151 if (key.type() == ui::ET_KEY_PRESSED) { | |
152 if (code == ui::VKEY_SHIFT) { | |
153 base::i18n::TextDirection dir; | |
154 if (ui::IMM32Manager::IsCtrlShiftPressed(&dir)) | |
155 pending_requested_direction_ = dir; | |
156 } else if (code != ui::VKEY_CONTROL) { | |
157 pending_requested_direction_ = base::i18n::UNKNOWN_DIRECTION; | |
158 } | |
159 } else if (key.type() == ui::ET_KEY_RELEASED && | |
160 (code == ui::VKEY_SHIFT || code == ui::VKEY_CONTROL) && | |
161 pending_requested_direction_ != base::i18n::UNKNOWN_DIRECTION) { | |
162 GetTextInputClient()->ChangeTextDirectionAndLayoutAlignment( | |
163 pending_requested_direction_); | |
164 pending_requested_direction_ = base::i18n::UNKNOWN_DIRECTION; | |
165 } | |
166 } | |
167 | |
168 // If only 1 WM_CHAR per the key event, set it as the character of it. | 166 // If only 1 WM_CHAR per the key event, set it as the character of it. |
169 if (char_msgs.size() == 1) | 167 if (char_msgs.size() == 1) |
170 event->set_character(static_cast<base::char16>(char_msgs[0].wParam)); | 168 event->set_character(static_cast<base::char16>(char_msgs[0].wParam)); |
171 | 169 |
172 // Dispatches the key events to the Chrome IME extension which is listening to | 170 // Dispatches the key events to the Chrome IME extension which is listening to |
173 // key events on the following two situations: | 171 // key events on the following two situations: |
174 // 1) |char_msgs| is empty when the event is non-character key. | 172 // 1) |char_msgs| is empty when the event is non-character key. |
175 // 2) |char_msgs|.size() == 1 when the event is character key and the WM_CHAR | 173 // 2) |char_msgs|.size() == 1 when the event is character key and the WM_CHAR |
176 // messages have been combined in the event processing flow. | 174 // messages have been combined in the event processing flow. |
177 if (!base::CommandLine::ForCurrentProcess()->HasSwitch( | 175 if (!base::CommandLine::ForCurrentProcess()->HasSwitch( |
(...skipping 16 matching lines...) Expand all Loading... | |
194 DCHECK(event); | 192 DCHECK(event); |
195 if (is_handled) | 193 if (is_handled) |
196 return; | 194 return; |
197 | 195 |
198 ui::EventDispatchDetails details = DispatchKeyEventPostIME(event); | 196 ui::EventDispatchDetails details = DispatchKeyEventPostIME(event); |
199 if (details.dispatcher_destroyed || details.target_destroyed || | 197 if (details.dispatcher_destroyed || details.target_destroyed || |
200 event->stopped_propagation()) { | 198 event->stopped_propagation()) { |
201 return; | 199 return; |
202 } | 200 } |
203 | 201 |
202 if (char_msgs->empty() && | |
Shu Chen
2016/03/09 05:50:50
Replaces the condition char_msgs->empty() with eve
| |
203 (event->is_char() || event->GetDomKey().IsCharacter()) && | |
204 event->type() == ui::ET_KEY_PRESSED && GetTextInputClient()) { | |
205 // The key event if from calling input.ime.sendKeyEvent or test. | |
206 GetTextInputClient()->InsertChar(*event); | |
207 return; | |
208 } | |
209 | |
204 BOOL handled; | 210 BOOL handled; |
205 for (const auto& msg : (*char_msgs)) | 211 for (const auto& msg : (*char_msgs)) |
206 OnChar(msg.hwnd, msg.message, msg.wParam, msg.lParam, msg, &handled); | 212 OnChar(msg.hwnd, msg.message, msg.wParam, msg.lParam, msg, &handled); |
207 } | 213 } |
208 | 214 |
209 void InputMethodWin::OnTextInputTypeChanged(const TextInputClient* client) { | 215 void InputMethodWin::OnTextInputTypeChanged(const TextInputClient* client) { |
210 if (!IsTextInputClientFocused(client) || !IsWindowFocused(client)) | 216 if (!IsTextInputClientFocused(client) || !IsWindowFocused(client)) |
211 return; | 217 return; |
212 imm32_manager_.CancelIME(toplevel_window_handle_); | 218 imm32_manager_.CancelIME(toplevel_window_handle_); |
213 UpdateIMEState(); | 219 UpdateIMEState(); |
(...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
611 return false; | 617 return false; |
612 // When Aura is enabled, |attached_window_handle| should always be a top-level | 618 // When Aura is enabled, |attached_window_handle| should always be a top-level |
613 // window. So we can safely assume that |attached_window_handle| is ready for | 619 // window. So we can safely assume that |attached_window_handle| is ready for |
614 // receiving keyboard input as long as it is an active window. This works well | 620 // receiving keyboard input as long as it is an active window. This works well |
615 // even when the |attached_window_handle| becomes active but has not received | 621 // even when the |attached_window_handle| becomes active but has not received |
616 // WM_FOCUS yet. | 622 // WM_FOCUS yet. |
617 return toplevel_window_handle_ && | 623 return toplevel_window_handle_ && |
618 GetActiveWindow() == toplevel_window_handle_; | 624 GetActiveWindow() == toplevel_window_handle_; |
619 } | 625 } |
620 | 626 |
621 void InputMethodWin::DispatchFabricatedKeyEvent(ui::KeyEvent* event) { | |
622 if (event->is_char()) { | |
623 if (GetTextInputClient()) { | |
624 ui::KeyEvent ch_event(*event); | |
625 ch_event.set_character(static_cast<base::char16>(event->key_code())); | |
626 GetTextInputClient()->InsertChar(ch_event); | |
627 return; | |
628 } | |
629 } | |
630 ignore_result(DispatchKeyEventPostIME(event)); | |
631 } | |
632 | |
633 void InputMethodWin::ConfirmCompositionText() { | 627 void InputMethodWin::ConfirmCompositionText() { |
634 if (composing_window_handle_) | 628 if (composing_window_handle_) |
635 imm32_manager_.CleanupComposition(composing_window_handle_); | 629 imm32_manager_.CleanupComposition(composing_window_handle_); |
636 | 630 |
637 // Though above line should confirm the client's composition text by sending a | 631 // Though above line should confirm the client's composition text by sending a |
638 // result text to us, in case the input method and the client are in | 632 // result text to us, in case the input method and the client are in |
639 // inconsistent states, we check the client's composition state again. | 633 // inconsistent states, we check the client's composition state again. |
640 if (!IsTextInputTypeNone() && GetTextInputClient()->HasCompositionText()) { | 634 if (!IsTextInputTypeNone() && GetTextInputClient()->HasCompositionText()) { |
641 GetTextInputClient()->ConfirmCompositionText(); | 635 GetTextInputClient()->ConfirmCompositionText(); |
642 | 636 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
679 ui::IMEEngineHandlerInterface* engine = GetEngine(); | 673 ui::IMEEngineHandlerInterface* engine = GetEngine(); |
680 if (engine) { | 674 if (engine) { |
681 if (old_text_input_type != ui::TEXT_INPUT_TYPE_NONE) | 675 if (old_text_input_type != ui::TEXT_INPUT_TYPE_NONE) |
682 engine->FocusOut(); | 676 engine->FocusOut(); |
683 if (text_input_type != ui::TEXT_INPUT_TYPE_NONE) | 677 if (text_input_type != ui::TEXT_INPUT_TYPE_NONE) |
684 engine->FocusIn(context); | 678 engine->FocusIn(context); |
685 } | 679 } |
686 } | 680 } |
687 | 681 |
688 } // namespace ui | 682 } // namespace ui |
OLD | NEW |