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

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

Issue 1257603006: Refactoring for the InputMethod & InputMethodDelegate interfaces. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 4 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_auralinux.h ('k') | ui/base/ime/input_method_auralinux_unittest.cc » ('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 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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_auralinux.h" 5 #include "ui/base/ime/input_method_auralinux.h"
6 6
7 #include "base/auto_reset.h" 7 #include "base/auto_reset.h"
8 #include "base/environment.h" 8 #include "base/environment.h"
9 #include "ui/base/ime/linux/linux_input_method_context_factory.h" 9 #include "ui/base/ime/linux/linux_input_method_context_factory.h"
10 #include "ui/base/ime/text_input_client.h" 10 #include "ui/base/ime/text_input_client.h"
11 #include "ui/events/event.h" 11 #include "ui/events/event.h"
12 12
13 namespace ui { 13 namespace ui {
14 14
15 InputMethodAuraLinux::InputMethodAuraLinux( 15 InputMethodAuraLinux::InputMethodAuraLinux(
16 internal::InputMethodDelegate* delegate) 16 internal::InputMethodDelegate* delegate)
17 : text_input_type_(TEXT_INPUT_TYPE_NONE), 17 : text_input_type_(TEXT_INPUT_TYPE_NONE),
18 is_sync_mode_(false), 18 is_sync_mode_(false),
19 composition_changed_(false), 19 composition_changed_(false),
20 suppress_next_result_(false), 20 suppress_next_result_(false) {
21 destroyed_ptr_(nullptr) {
22 SetDelegate(delegate); 21 SetDelegate(delegate);
23 context_ = 22 context_ =
24 LinuxInputMethodContextFactory::instance()->CreateInputMethodContext( 23 LinuxInputMethodContextFactory::instance()->CreateInputMethodContext(
25 this, false); 24 this, false);
26 context_simple_ = 25 context_simple_ =
27 LinuxInputMethodContextFactory::instance()->CreateInputMethodContext( 26 LinuxInputMethodContextFactory::instance()->CreateInputMethodContext(
28 this, true); 27 this, true);
29 } 28 }
30 29
31 InputMethodAuraLinux::~InputMethodAuraLinux() { 30 InputMethodAuraLinux::~InputMethodAuraLinux() {
32 if (destroyed_ptr_)
33 *destroyed_ptr_ = true;
34 } 31 }
35 32
36 LinuxInputMethodContext* InputMethodAuraLinux::GetContextForTesting( 33 LinuxInputMethodContext* InputMethodAuraLinux::GetContextForTesting(
37 bool is_simple) { 34 bool is_simple) {
38 return is_simple ? context_simple_.get() : context_.get(); 35 return is_simple ? context_simple_.get() : context_.get();
39 } 36 }
40 37
41 // Overriden from InputMethod. 38 // Overriden from InputMethod.
42 39
43 bool InputMethodAuraLinux::OnUntranslatedIMEMessage( 40 bool InputMethodAuraLinux::OnUntranslatedIMEMessage(
44 const base::NativeEvent& event, 41 const base::NativeEvent& event,
45 NativeEventResult* result) { 42 NativeEventResult* result) {
46 return false; 43 return false;
47 } 44 }
48 45
49 bool InputMethodAuraLinux::DispatchKeyEvent(const ui::KeyEvent& event) { 46 void InputMethodAuraLinux::DispatchKeyEvent(ui::KeyEvent* event) {
50 DCHECK(event.type() == ET_KEY_PRESSED || event.type() == ET_KEY_RELEASED); 47 DCHECK(event->type() == ET_KEY_PRESSED || event->type() == ET_KEY_RELEASED);
51 DCHECK(system_toplevel_window_focused()); 48 DCHECK(system_toplevel_window_focused());
52 49
53 // If no text input client, do nothing. 50 // If no text input client, do nothing.
54 if (!GetTextInputClient()) 51 if (!GetTextInputClient()) {
55 return DispatchKeyEventPostIME(event); 52 ignore_result(DispatchKeyEventPostIME(event));
53 return;
54 }
56 55
57 suppress_next_result_ = false; 56 suppress_next_result_ = false;
58 composition_changed_ = false; 57 composition_changed_ = false;
59 result_text_.clear(); 58 result_text_.clear();
60 59
61 bool filtered = false; 60 bool filtered = false;
62 { 61 {
63 base::AutoReset<bool> flipper(&is_sync_mode_, true); 62 base::AutoReset<bool> flipper(&is_sync_mode_, true);
64 if (text_input_type_ != TEXT_INPUT_TYPE_NONE && 63 if (text_input_type_ != TEXT_INPUT_TYPE_NONE &&
65 text_input_type_ != TEXT_INPUT_TYPE_PASSWORD) { 64 text_input_type_ != TEXT_INPUT_TYPE_PASSWORD) {
66 filtered = context_->DispatchKeyEvent(event); 65 filtered = context_->DispatchKeyEvent(*event);
67 } else { 66 } else {
68 filtered = context_simple_->DispatchKeyEvent(event); 67 filtered = context_simple_->DispatchKeyEvent(*event);
69 } 68 }
70 } 69 }
71 70
72 bool destroyed = false; 71 ui::EventDispatchDetails details;
73 bool handled = false; 72 if (event->type() == ui::ET_KEY_PRESSED && filtered) {
74 if (event.type() == ui::ET_KEY_PRESSED && filtered) { 73 if (NeedInsertChar())
75 { 74 details = DispatchKeyEventPostIME(event);
76 base::AutoReset<bool*> auto_reset(&destroyed_ptr_, &destroyed); 75 else if (HasInputMethodResult())
77 if (NeedInsertChar()) 76 details = SendFakeProcessKeyEvent(event);
78 handled = DispatchKeyEventPostIME(event); 77 if (details.dispatcher_destroyed)
79 else if (HasInputMethodResult()) 78 return;
80 handled = SendFakeProcessKeyEvent(event.flags());
81 if (destroyed)
82 return true;
83 }
84 // If the KEYDOWN is stopped propagation (e.g. triggered an accelerator), 79 // If the KEYDOWN is stopped propagation (e.g. triggered an accelerator),
85 // don't InsertChar/InsertText to the input field. 80 // don't InsertChar/InsertText to the input field.
86 if (handled) { 81 if (event->stopped_propagation() || details.target_destroyed) {
87 ResetContext(); 82 ResetContext();
88 return true; 83 return;
89 } 84 }
90 85
91 // Don't send VKEY_PROCESSKEY event if there is no result text or 86 // Don't send VKEY_PROCESSKEY event if there is no result text or
92 // composition. This is to workaround the weird behavior of IBus with US 87 // composition. This is to workaround the weird behavior of IBus with US
93 // keyboard, which mutes the keydown and later fake a new keydown with IME 88 // keyboard, which mutes the keydown and later fake a new keydown with IME
94 // result in sync mode. In that case, user would expect only 89 // result in sync mode. In that case, user would expect only
95 // keydown/keypress/keyup event without an initial 229 keydown event. 90 // keydown/keypress/keyup event without an initial 229 keydown event.
96 } 91 }
97 92
98 TextInputClient* client = GetTextInputClient(); 93 TextInputClient* client = GetTextInputClient();
99 // Processes the result text before composition for sync mode. 94 // Processes the result text before composition for sync mode.
100 if (!result_text_.empty()) { 95 if (!result_text_.empty()) {
101 if (filtered && NeedInsertChar()) { 96 if (filtered && NeedInsertChar()) {
102 for (const auto ch : result_text_) 97 for (const auto ch : result_text_)
103 client->InsertChar(ch, event.flags()); 98 client->InsertChar(ch, event->flags());
104 } else { 99 } else {
105 // If |filtered| is false, that means the IME wants to commit some text 100 // If |filtered| is false, that means the IME wants to commit some text
106 // but still release the key to the application. For example, Korean IME 101 // but still release the key to the application. For example, Korean IME
107 // handles ENTER key to confirm its composition but still release it for 102 // handles ENTER key to confirm its composition but still release it for
108 // the default behavior (e.g. trigger search, etc.) 103 // the default behavior (e.g. trigger search, etc.)
109 // In such case, don't do InsertChar because a key should only trigger the 104 // In such case, don't do InsertChar because a key should only trigger the
110 // keydown event once. 105 // keydown event once.
111 client->InsertText(result_text_); 106 client->InsertText(result_text_);
112 } 107 }
108 event->StopPropagation();
113 } 109 }
114 110
115 if (composition_changed_ && !IsTextInputTypeNone()) { 111 if (composition_changed_ && !IsTextInputTypeNone()) {
116 // If composition changed, does SetComposition if composition is not empty. 112 // If composition changed, does SetComposition if composition is not empty.
117 // And ClearComposition if composition is empty. 113 // And ClearComposition if composition is empty.
118 if (!composition_.text.empty()) 114 if (!composition_.text.empty())
119 client->SetCompositionText(composition_); 115 client->SetCompositionText(composition_);
120 else if (result_text_.empty()) 116 else if (result_text_.empty())
121 client->ClearCompositionText(); 117 client->ClearCompositionText();
118 event->StopPropagation();
122 } 119 }
123 120
124 // Makes sure the cached composition is cleared after committing any text or 121 // Makes sure the cached composition is cleared after committing any text or
125 // cleared composition. 122 // cleared composition.
126 if (!client->HasCompositionText()) 123 if (!client->HasCompositionText())
127 composition_.Clear(); 124 composition_.Clear();
128 125
129 if (!filtered) { 126 if (!filtered) {
130 { 127 details = DispatchKeyEventPostIME(event);
131 base::AutoReset<bool*> auto_reset(&destroyed_ptr_, &destroyed); 128 if (details.dispatcher_destroyed)
132 handled = DispatchKeyEventPostIME(event); 129 return;
133 if (destroyed) 130 if (event->stopped_propagation() || details.target_destroyed) {
134 return true; 131 ResetContext();
132 return;
135 } 133 }
136 if (handled) { 134 if (event->type() == ui::ET_KEY_PRESSED) {
137 ResetContext();
138 return true;
139 }
140 if (event.type() == ui::ET_KEY_PRESSED) {
141 // If a key event was not filtered by |context_| or |context_simple_|, 135 // If a key event was not filtered by |context_| or |context_simple_|,
142 // then it means the key event didn't generate any result text. For some 136 // then it means the key event didn't generate any result text. For some
143 // cases, the key event may still generate a valid character, eg. a 137 // cases, the key event may still generate a valid character, eg. a
144 // control-key event (ctrl-a, return, tab, etc.). We need to send the 138 // control-key event (ctrl-a, return, tab, etc.). We need to send the
145 // character to the focused text input client by calling 139 // character to the focused text input client by calling
146 // TextInputClient::InsertChar(). 140 // TextInputClient::InsertChar().
147 // Note: don't use |client| and use GetTextInputClient() here because 141 // Note: don't use |client| and use GetTextInputClient() here because
148 // DispatchKeyEventPostIME may cause the current text input client change. 142 // DispatchKeyEventPostIME may cause the current text input client change.
149 base::char16 ch = event.GetCharacter(); 143 base::char16 ch = event->GetCharacter();
150 if (ch && GetTextInputClient()) 144 if (ch && GetTextInputClient())
151 GetTextInputClient()->InsertChar(ch, event.flags()); 145 GetTextInputClient()->InsertChar(ch, event->flags());
146 event->StopPropagation();
James Su 2015/08/03 06:58:55 why this line is moved into this if block?
Shu Chen 2015/08/03 07:03:54 Event is StopPropagation'ed only when TextInputCli
152 } 147 }
153 } 148 }
154
155 return true;
156 } 149 }
157 150
158 void InputMethodAuraLinux::UpdateContextFocusState() { 151 void InputMethodAuraLinux::UpdateContextFocusState() {
159 bool old_text_input_type = text_input_type_; 152 bool old_text_input_type = text_input_type_;
160 text_input_type_ = GetTextInputType(); 153 text_input_type_ = GetTextInputType();
161 154
162 // We only focus in |context_| when the focus is in a textfield. 155 // We only focus in |context_| when the focus is in a textfield.
163 if (old_text_input_type != TEXT_INPUT_TYPE_NONE && 156 if (old_text_input_type != TEXT_INPUT_TYPE_NONE &&
164 text_input_type_ == TEXT_INPUT_TYPE_NONE) { 157 text_input_type_ == TEXT_INPUT_TYPE_NONE) {
165 context_->Blur(); 158 context_->Blur();
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
241 return; 234 return;
242 } 235 }
243 236
244 if (is_sync_mode_) { 237 if (is_sync_mode_) {
245 // Append the text to the buffer, because commit signal might be fired 238 // Append the text to the buffer, because commit signal might be fired
246 // multiple times when processing a key event. 239 // multiple times when processing a key event.
247 result_text_.append(text); 240 result_text_.append(text);
248 } else if (!IsTextInputTypeNone()) { 241 } else if (!IsTextInputTypeNone()) {
249 // If we are not handling key event, do not bother sending text result if 242 // If we are not handling key event, do not bother sending text result if
250 // the focused text input client does not support text input. 243 // the focused text input client does not support text input.
251 SendFakeProcessKeyEvent(0); 244 ui::KeyEvent event(ui::ET_KEY_PRESSED, ui::VKEY_PROCESSKEY, 0);
252 GetTextInputClient()->InsertText(text); 245 ui::EventDispatchDetails details = SendFakeProcessKeyEvent(&event);
246 if (details.dispatcher_destroyed)
247 return;
248 if (!event.stopped_propagation())
James Su 2015/08/03 06:58:55 check target_destroyed?
Shu Chen 2015/08/03 07:03:54 Done.
249 GetTextInputClient()->InsertText(text);
253 composition_.Clear(); 250 composition_.Clear();
254 } 251 }
255 } 252 }
256 253
257 void InputMethodAuraLinux::OnPreeditChanged( 254 void InputMethodAuraLinux::OnPreeditChanged(
258 const CompositionText& composition_text) { 255 const CompositionText& composition_text) {
259 if (suppress_next_result_ || IsTextInputTypeNone()) 256 if (suppress_next_result_ || IsTextInputTypeNone())
260 return; 257 return;
261 258
262 if (is_sync_mode_) { 259 if (is_sync_mode_) {
263 if (!composition_.text.empty() || !composition_text.text.empty()) 260 if (!composition_.text.empty() || !composition_text.text.empty())
264 composition_changed_ = true; 261 composition_changed_ = true;
265 } else { 262 } else {
266 SendFakeProcessKeyEvent(0); 263 ui::KeyEvent event(ui::ET_KEY_PRESSED, ui::VKEY_PROCESSKEY, 0);
267 GetTextInputClient()->SetCompositionText(composition_text); 264 ui::EventDispatchDetails details = SendFakeProcessKeyEvent(&event);
265 if (details.dispatcher_destroyed)
266 return;
267 if (!event.stopped_propagation())
James Su 2015/08/03 06:58:55 ditto.
Shu Chen 2015/08/03 07:03:54 Done.
268 GetTextInputClient()->SetCompositionText(composition_text);
268 } 269 }
269 270
270 composition_ = composition_text; 271 composition_ = composition_text;
271 } 272 }
272 273
273 void InputMethodAuraLinux::OnPreeditEnd() { 274 void InputMethodAuraLinux::OnPreeditEnd() {
274 if (suppress_next_result_ || IsTextInputTypeNone()) 275 if (suppress_next_result_ || IsTextInputTypeNone())
275 return; 276 return;
276 277
277 if (is_sync_mode_) { 278 if (is_sync_mode_) {
278 if (!composition_.text.empty()) { 279 if (!composition_.text.empty()) {
279 composition_.Clear(); 280 composition_.Clear();
280 composition_changed_ = true; 281 composition_changed_ = true;
281 } 282 }
282 } else { 283 } else {
283 TextInputClient* client = GetTextInputClient(); 284 TextInputClient* client = GetTextInputClient();
284 if (client && client->HasCompositionText()) { 285 if (client && client->HasCompositionText()) {
285 SendFakeProcessKeyEvent(0); 286 ui::KeyEvent event(ui::ET_KEY_PRESSED, ui::VKEY_PROCESSKEY, 0);
286 client->ClearCompositionText(); 287 ui::EventDispatchDetails details = SendFakeProcessKeyEvent(&event);
288 if (details.dispatcher_destroyed)
289 return;
290 if (!event.stopped_propagation())
James Su 2015/08/03 06:58:55 ditto
Shu Chen 2015/08/03 07:03:54 Done.
291 client->ClearCompositionText();
287 } 292 }
288 composition_.Clear(); 293 composition_.Clear();
289 } 294 }
290 } 295 }
291 296
292 // Overridden from InputMethodBase. 297 // Overridden from InputMethodBase.
293 298
294 void InputMethodAuraLinux::OnFocus() { 299 void InputMethodAuraLinux::OnFocus() {
295 InputMethodBase::OnFocus(); 300 InputMethodBase::OnFocus();
296 UpdateContextFocusState(); 301 UpdateContextFocusState();
(...skipping 29 matching lines...) Expand all
326 bool InputMethodAuraLinux::HasInputMethodResult() { 331 bool InputMethodAuraLinux::HasInputMethodResult() {
327 return !result_text_.empty() || composition_changed_; 332 return !result_text_.empty() || composition_changed_;
328 } 333 }
329 334
330 bool InputMethodAuraLinux::NeedInsertChar() const { 335 bool InputMethodAuraLinux::NeedInsertChar() const {
331 return IsTextInputTypeNone() || 336 return IsTextInputTypeNone() ||
332 (!composition_changed_ && composition_.text.empty() && 337 (!composition_changed_ && composition_.text.empty() &&
333 result_text_.length() == 1); 338 result_text_.length() == 1);
334 } 339 }
335 340
336 bool InputMethodAuraLinux::SendFakeProcessKeyEvent(int flags) const { 341 ui::EventDispatchDetails InputMethodAuraLinux::SendFakeProcessKeyEvent(
337 return DispatchKeyEventPostIME( 342 ui::KeyEvent* event) const {
338 KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_PROCESSKEY, flags)); 343 KeyEvent key_event(ui::ET_KEY_PRESSED, ui::VKEY_PROCESSKEY, event->flags());
344 ui::EventDispatchDetails details = DispatchKeyEventPostIME(&key_event);
345 if (key_event.stopped_propagation())
346 event->StopPropagation();
347 return details;
339 } 348 }
340 349
341 void InputMethodAuraLinux::ConfirmCompositionText() { 350 void InputMethodAuraLinux::ConfirmCompositionText() {
342 TextInputClient* client = GetTextInputClient(); 351 TextInputClient* client = GetTextInputClient();
343 if (client && client->HasCompositionText()) 352 if (client && client->HasCompositionText())
344 client->ConfirmCompositionText(); 353 client->ConfirmCompositionText();
345 354
346 ResetContext(); 355 ResetContext();
347 } 356 }
348 357
349 } // namespace ui 358 } // namespace ui
OLDNEW
« no previous file with comments | « ui/base/ime/input_method_auralinux.h ('k') | ui/base/ime/input_method_auralinux_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698