Chromium Code Reviews| 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 |