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

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

Issue 1771173002: Implement input.ime.sendKeyEvents API. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Added Windows-specific implementation. Created 4 years, 9 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') | no next file » | 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 <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
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
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
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
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
OLDNEW
« no previous file with comments | « ui/base/ime/input_method_win.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698