Drive: Add BatchableRequest subclass.
[chromium-blink-merge.git] / ui / base / ime / input_method_win.cc
blob69616839b92c249f64fef0d11af8f935050bc75e
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
3 // found in the LICENSE file.
5 #include "ui/base/ime/input_method_win.h"
7 #include "base/basictypes.h"
8 #include "base/profiler/scoped_tracker.h"
9 #include "ui/base/ime/text_input_client.h"
10 #include "ui/base/ime/win/tsf_input_scope.h"
11 #include "ui/events/event.h"
12 #include "ui/events/event_constants.h"
13 #include "ui/events/event_utils.h"
14 #include "ui/events/keycodes/keyboard_codes.h"
15 #include "ui/gfx/win/dpi.h"
16 #include "ui/gfx/win/hwnd_util.h"
18 namespace ui {
19 namespace {
21 // Extra number of chars before and after selection (or composition) range which
22 // is returned to IME for improving conversion accuracy.
23 static const size_t kExtraNumberOfChars = 20;
25 } // namespace
27 InputMethodWin::InputMethodWin(internal::InputMethodDelegate* delegate,
28 HWND toplevel_window_handle)
29 : toplevel_window_handle_(toplevel_window_handle),
30 pending_requested_direction_(base::i18n::UNKNOWN_DIRECTION),
31 accept_carriage_return_(false),
32 active_(false),
33 enabled_(false),
34 is_candidate_popup_open_(false),
35 composing_window_handle_(NULL),
36 default_input_language_initialized_(false) {
37 SetDelegate(delegate);
38 // In non-Aura environment, appropriate callbacks to OnFocus() and OnBlur()
39 // are not implemented yet. To work around this limitation, here we use
40 // "always focused" model.
41 // TODO(ime): Fix the caller of OnFocus() and OnBlur() so that appropriate
42 // focus event will be passed.
43 InputMethodBase::OnFocus();
46 void InputMethodWin::Init(bool focused) {
47 InputMethodBase::Init(focused);
50 void InputMethodWin::OnFocus() {
51 // Ignore OnFocus event for "always focused" model. See the comment in the
52 // constructor.
53 // TODO(ime): Implement OnFocus once the callers are fixed.
56 void InputMethodWin::OnBlur() {
57 // Ignore OnBlur event for "always focused" model. See the comment in the
58 // constructor.
59 // TODO(ime): Implement OnFocus once the callers are fixed.
62 bool InputMethodWin::OnUntranslatedIMEMessage(
63 const base::NativeEvent& event,
64 InputMethod::NativeEventResult* result) {
65 LRESULT original_result = 0;
66 BOOL handled = FALSE;
68 if (!default_input_language_initialized_) {
69 // Gets the initial input locale.
70 OnInputLocaleChanged();
73 switch (event.message) {
74 case WM_IME_SETCONTEXT:
75 original_result = OnImeSetContext(
76 event.hwnd, event.message, event.wParam, event.lParam, &handled);
77 break;
78 case WM_IME_STARTCOMPOSITION:
79 original_result = OnImeStartComposition(
80 event.hwnd, event.message, event.wParam, event.lParam, &handled);
81 break;
82 case WM_IME_COMPOSITION:
83 original_result = OnImeComposition(
84 event.hwnd, event.message, event.wParam, event.lParam, &handled);
85 break;
86 case WM_IME_ENDCOMPOSITION:
87 original_result = OnImeEndComposition(
88 event.hwnd, event.message, event.wParam, event.lParam, &handled);
89 break;
90 case WM_IME_REQUEST:
91 original_result = OnImeRequest(
92 event.message, event.wParam, event.lParam, &handled);
93 break;
94 case WM_CHAR:
95 case WM_SYSCHAR:
96 original_result = OnChar(
97 event.hwnd, event.message, event.wParam, event.lParam, &handled);
98 break;
99 case WM_IME_NOTIFY:
100 original_result = OnImeNotify(
101 event.message, event.wParam, event.lParam, &handled);
102 break;
103 default:
104 NOTREACHED() << "Unknown IME message:" << event.message;
105 break;
107 if (result)
108 *result = original_result;
109 return !!handled;
112 bool InputMethodWin::DispatchKeyEvent(const ui::KeyEvent& event) {
113 if (!event.HasNativeEvent())
114 return DispatchFabricatedKeyEvent(event);
116 const base::NativeEvent& native_key_event = event.native_event();
117 if (native_key_event.message == WM_CHAR) {
118 BOOL handled;
119 OnChar(native_key_event.hwnd, native_key_event.message,
120 native_key_event.wParam, native_key_event.lParam, &handled);
121 return !!handled; // Don't send WM_CHAR for post event processing.
123 // Handles ctrl-shift key to change text direction and layout alignment.
124 if (ui::IMM32Manager::IsRTLKeyboardLayoutInstalled() &&
125 !IsTextInputTypeNone()) {
126 // TODO: shouldn't need to generate a KeyEvent here.
127 const ui::KeyEvent key(native_key_event);
128 ui::KeyboardCode code = key.key_code();
129 if (key.type() == ui::ET_KEY_PRESSED) {
130 if (code == ui::VKEY_SHIFT) {
131 base::i18n::TextDirection dir;
132 if (ui::IMM32Manager::IsCtrlShiftPressed(&dir))
133 pending_requested_direction_ = dir;
134 } else if (code != ui::VKEY_CONTROL) {
135 pending_requested_direction_ = base::i18n::UNKNOWN_DIRECTION;
137 } else if (key.type() == ui::ET_KEY_RELEASED &&
138 (code == ui::VKEY_SHIFT || code == ui::VKEY_CONTROL) &&
139 pending_requested_direction_ != base::i18n::UNKNOWN_DIRECTION) {
140 GetTextInputClient()->ChangeTextDirectionAndLayoutAlignment(
141 pending_requested_direction_);
142 pending_requested_direction_ = base::i18n::UNKNOWN_DIRECTION;
146 return DispatchKeyEventPostIME(event);
149 void InputMethodWin::OnTextInputTypeChanged(const TextInputClient* client) {
150 if (!IsTextInputClientFocused(client) || !IsWindowFocused(client))
151 return;
152 imm32_manager_.CancelIME(GetAttachedWindowHandle(client));
153 UpdateIMEState();
156 void InputMethodWin::OnCaretBoundsChanged(const TextInputClient* client) {
157 if (!enabled_ || !IsTextInputClientFocused(client) ||
158 !IsWindowFocused(client)) {
159 return;
161 // The current text input type should not be NONE if |client| is focused.
162 DCHECK(!IsTextInputTypeNone());
163 // Tentatively assume that the returned value is DIP (Density Independent
164 // Pixel). See the comment in text_input_client.h and http://crbug.com/360334.
165 const gfx::Rect dip_screen_bounds(GetTextInputClient()->GetCaretBounds());
166 const gfx::Rect screen_bounds = gfx::win::DIPToScreenRect(dip_screen_bounds);
168 HWND attached_window = GetAttachedWindowHandle(client);
169 // TODO(ime): see comment in TextInputClient::GetCaretBounds(), this
170 // conversion shouldn't be necessary.
171 RECT r = {};
172 GetClientRect(attached_window, &r);
173 POINT window_point = { screen_bounds.x(), screen_bounds.y() };
174 ScreenToClient(attached_window, &window_point);
175 gfx::Rect caret_rect(gfx::Point(window_point.x, window_point.y),
176 screen_bounds.size());
177 imm32_manager_.UpdateCaretRect(attached_window, caret_rect);
180 void InputMethodWin::CancelComposition(const TextInputClient* client) {
181 if (enabled_ && IsTextInputClientFocused(client))
182 imm32_manager_.CancelIME(GetAttachedWindowHandle(client));
185 void InputMethodWin::OnInputLocaleChanged() {
186 default_input_language_initialized_ = true;
187 active_ = imm32_manager_.SetInputLanguage();
188 locale_ = imm32_manager_.GetInputLanguageName();
189 OnInputMethodChanged();
192 std::string InputMethodWin::GetInputLocale() {
193 return locale_;
196 bool InputMethodWin::IsActive() {
197 return active_;
200 bool InputMethodWin::IsCandidatePopupOpen() const {
201 return is_candidate_popup_open_;
204 void InputMethodWin::OnWillChangeFocusedClient(TextInputClient* focused_before,
205 TextInputClient* focused) {
206 if (IsWindowFocused(focused_before))
207 ConfirmCompositionText();
210 void InputMethodWin::OnDidChangeFocusedClient(
211 TextInputClient* focused_before,
212 TextInputClient* focused) {
213 if (IsWindowFocused(focused)) {
214 // Force to update the input type since client's TextInputStateChanged()
215 // function might not be called if text input types before the client loses
216 // focus and after it acquires focus again are the same.
217 OnTextInputTypeChanged(focused);
219 UpdateIMEState();
221 // Force to update caret bounds, in case the client thinks that the caret
222 // bounds has not changed.
223 OnCaretBoundsChanged(focused);
225 if (focused_before != focused)
226 accept_carriage_return_ = false;
229 LRESULT InputMethodWin::OnChar(HWND window_handle,
230 UINT message,
231 WPARAM wparam,
232 LPARAM lparam,
233 BOOL* handled) {
234 // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
235 tracked_objects::ScopedTracker tracking_profile(
236 FROM_HERE_WITH_EXPLICIT_FUNCTION("440919 InputMethodWin::OnChar"));
238 *handled = TRUE;
240 // We need to send character events to the focused text input client event if
241 // its text input type is ui::TEXT_INPUT_TYPE_NONE.
242 if (GetTextInputClient()) {
243 const base::char16 kCarriageReturn = L'\r';
244 const base::char16 ch = static_cast<base::char16>(wparam);
245 // A mask to determine the previous key state from |lparam|. The value is 1
246 // if the key is down before the message is sent, or it is 0 if the key is
247 // up.
248 const uint32 kPrevKeyDownBit = 0x40000000;
249 if (ch == kCarriageReturn && !(lparam & kPrevKeyDownBit))
250 accept_carriage_return_ = true;
251 // Conditionally ignore '\r' events to work around crbug.com/319100.
252 // TODO(yukawa, IME): Figure out long-term solution.
253 if (ch != kCarriageReturn || accept_carriage_return_)
254 GetTextInputClient()->InsertChar(ch, ui::GetModifiersFromKeyState());
257 // Explicitly show the system menu at a good location on [Alt]+[Space].
258 // Note: Setting |handled| to FALSE for DefWindowProc triggering of the system
259 // menu causes undesirable titlebar artifacts in the classic theme.
260 if (message == WM_SYSCHAR && wparam == VK_SPACE)
261 gfx::ShowSystemMenu(window_handle);
263 return 0;
266 LRESULT InputMethodWin::OnImeSetContext(HWND window_handle,
267 UINT message,
268 WPARAM wparam,
269 LPARAM lparam,
270 BOOL* handled) {
271 // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
272 tracked_objects::ScopedTracker tracking_profile(
273 FROM_HERE_WITH_EXPLICIT_FUNCTION(
274 "440919 InputMethodWin::OnImeSetContext"));
276 if (!!wparam)
277 imm32_manager_.CreateImeWindow(window_handle);
279 OnInputMethodChanged();
280 return imm32_manager_.SetImeWindowStyle(
281 window_handle, message, wparam, lparam, handled);
284 LRESULT InputMethodWin::OnImeStartComposition(HWND window_handle,
285 UINT message,
286 WPARAM wparam,
287 LPARAM lparam,
288 BOOL* handled) {
289 // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
290 tracked_objects::ScopedTracker tracking_profile(
291 FROM_HERE_WITH_EXPLICIT_FUNCTION(
292 "440919 InputMethodWin::OnImeStartComposition"));
294 // We have to prevent WTL from calling ::DefWindowProc() because the function
295 // calls ::ImmSetCompositionWindow() and ::ImmSetCandidateWindow() to
296 // over-write the position of IME windows.
297 *handled = TRUE;
299 // Reset the composition status and create IME windows.
300 composing_window_handle_ = window_handle;
301 imm32_manager_.CreateImeWindow(window_handle);
302 imm32_manager_.ResetComposition(window_handle);
303 return 0;
306 LRESULT InputMethodWin::OnImeComposition(HWND window_handle,
307 UINT message,
308 WPARAM wparam,
309 LPARAM lparam,
310 BOOL* handled) {
311 // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
312 tracked_objects::ScopedTracker tracking_profile(
313 FROM_HERE_WITH_EXPLICIT_FUNCTION(
314 "440919 InputMethodWin::OnImeComposition"));
316 // We have to prevent WTL from calling ::DefWindowProc() because we do not
317 // want for the IMM (Input Method Manager) to send WM_IME_CHAR messages.
318 *handled = TRUE;
320 // At first, update the position of the IME window.
321 imm32_manager_.UpdateImeWindow(window_handle);
323 // Retrieve the result string and its attributes of the ongoing composition
324 // and send it to a renderer process.
325 ui::CompositionText composition;
326 if (imm32_manager_.GetResult(window_handle, lparam, &composition.text)) {
327 if (!IsTextInputTypeNone())
328 GetTextInputClient()->InsertText(composition.text);
329 imm32_manager_.ResetComposition(window_handle);
330 // Fall though and try reading the composition string.
331 // Japanese IMEs send a message containing both GCS_RESULTSTR and
332 // GCS_COMPSTR, which means an ongoing composition has been finished
333 // by the start of another composition.
335 // Retrieve the composition string and its attributes of the ongoing
336 // composition and send it to a renderer process.
337 if (imm32_manager_.GetComposition(window_handle, lparam, &composition) &&
338 !IsTextInputTypeNone())
339 GetTextInputClient()->SetCompositionText(composition);
341 return 0;
344 LRESULT InputMethodWin::OnImeEndComposition(HWND window_handle,
345 UINT message,
346 WPARAM wparam,
347 LPARAM lparam,
348 BOOL* handled) {
349 // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
350 tracked_objects::ScopedTracker tracking_profile(
351 FROM_HERE_WITH_EXPLICIT_FUNCTION(
352 "440919 InputMethodWin::OnImeEndComposition"));
354 // Let WTL call ::DefWindowProc() and release its resources.
355 *handled = FALSE;
357 composing_window_handle_ = NULL;
359 if (!IsTextInputTypeNone() && GetTextInputClient()->HasCompositionText())
360 GetTextInputClient()->ClearCompositionText();
362 imm32_manager_.ResetComposition(window_handle);
363 imm32_manager_.DestroyImeWindow(window_handle);
364 return 0;
367 LRESULT InputMethodWin::OnImeNotify(UINT message,
368 WPARAM wparam,
369 LPARAM lparam,
370 BOOL* handled) {
371 // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
372 tracked_objects::ScopedTracker tracking_profile(
373 FROM_HERE_WITH_EXPLICIT_FUNCTION("440919 InputMethodWin::OnImeNotify"));
375 *handled = FALSE;
377 bool previous_state = is_candidate_popup_open_;
379 // Update |is_candidate_popup_open_|, whether a candidate window is open.
380 switch (wparam) {
381 case IMN_OPENCANDIDATE:
382 is_candidate_popup_open_ = true;
383 if (!previous_state)
384 OnCandidateWindowShown();
385 break;
386 case IMN_CLOSECANDIDATE:
387 is_candidate_popup_open_ = false;
388 if (previous_state)
389 OnCandidateWindowHidden();
390 break;
391 case IMN_CHANGECANDIDATE:
392 // TODO(kochi): The IME API expects this event to notify window size change,
393 // while this may fire more often without window resize. There is no generic
394 // way to get bounds of candidate window.
395 OnCandidateWindowUpdated();
396 break;
399 return 0;
402 LRESULT InputMethodWin::OnImeRequest(UINT message,
403 WPARAM wparam,
404 LPARAM lparam,
405 BOOL* handled) {
406 // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
407 tracked_objects::ScopedTracker tracking_profile(
408 FROM_HERE_WITH_EXPLICIT_FUNCTION("440919 InputMethodWin::OnImeRequest"));
410 *handled = FALSE;
412 // Should not receive WM_IME_REQUEST message, if IME is disabled.
413 const ui::TextInputType type = GetTextInputType();
414 if (type == ui::TEXT_INPUT_TYPE_NONE ||
415 type == ui::TEXT_INPUT_TYPE_PASSWORD) {
416 return 0;
419 switch (wparam) {
420 case IMR_RECONVERTSTRING:
421 *handled = TRUE;
422 return OnReconvertString(reinterpret_cast<RECONVERTSTRING*>(lparam));
423 case IMR_DOCUMENTFEED:
424 *handled = TRUE;
425 return OnDocumentFeed(reinterpret_cast<RECONVERTSTRING*>(lparam));
426 case IMR_QUERYCHARPOSITION:
427 *handled = TRUE;
428 return OnQueryCharPosition(reinterpret_cast<IMECHARPOSITION*>(lparam));
429 default:
430 return 0;
434 LRESULT InputMethodWin::OnDocumentFeed(RECONVERTSTRING* reconv) {
435 ui::TextInputClient* client = GetTextInputClient();
436 if (!client)
437 return 0;
439 gfx::Range text_range;
440 if (!client->GetTextRange(&text_range) || text_range.is_empty())
441 return 0;
443 bool result = false;
444 gfx::Range target_range;
445 if (client->HasCompositionText())
446 result = client->GetCompositionTextRange(&target_range);
448 if (!result || target_range.is_empty()) {
449 if (!client->GetSelectionRange(&target_range) ||
450 !target_range.IsValid()) {
451 return 0;
455 if (!text_range.Contains(target_range))
456 return 0;
458 if (target_range.GetMin() - text_range.start() > kExtraNumberOfChars)
459 text_range.set_start(target_range.GetMin() - kExtraNumberOfChars);
461 if (text_range.end() - target_range.GetMax() > kExtraNumberOfChars)
462 text_range.set_end(target_range.GetMax() + kExtraNumberOfChars);
464 size_t len = text_range.length();
465 size_t need_size = sizeof(RECONVERTSTRING) + len * sizeof(WCHAR);
467 if (!reconv)
468 return need_size;
470 if (reconv->dwSize < need_size)
471 return 0;
473 base::string16 text;
474 if (!GetTextInputClient()->GetTextFromRange(text_range, &text))
475 return 0;
476 DCHECK_EQ(text_range.length(), text.length());
478 reconv->dwVersion = 0;
479 reconv->dwStrLen = len;
480 reconv->dwStrOffset = sizeof(RECONVERTSTRING);
481 reconv->dwCompStrLen =
482 client->HasCompositionText() ? target_range.length() : 0;
483 reconv->dwCompStrOffset =
484 (target_range.GetMin() - text_range.start()) * sizeof(WCHAR);
485 reconv->dwTargetStrLen = target_range.length();
486 reconv->dwTargetStrOffset = reconv->dwCompStrOffset;
488 memcpy((char*)reconv + sizeof(RECONVERTSTRING),
489 text.c_str(), len * sizeof(WCHAR));
491 // According to Microsoft API document, IMR_RECONVERTSTRING and
492 // IMR_DOCUMENTFEED should return reconv, but some applications return
493 // need_size.
494 return reinterpret_cast<LRESULT>(reconv);
497 LRESULT InputMethodWin::OnReconvertString(RECONVERTSTRING* reconv) {
498 ui::TextInputClient* client = GetTextInputClient();
499 if (!client)
500 return 0;
502 // If there is a composition string already, we don't allow reconversion.
503 if (client->HasCompositionText())
504 return 0;
506 gfx::Range text_range;
507 if (!client->GetTextRange(&text_range) || text_range.is_empty())
508 return 0;
510 gfx::Range selection_range;
511 if (!client->GetSelectionRange(&selection_range) ||
512 selection_range.is_empty()) {
513 return 0;
516 DCHECK(text_range.Contains(selection_range));
518 size_t len = selection_range.length();
519 size_t need_size = sizeof(RECONVERTSTRING) + len * sizeof(WCHAR);
521 if (!reconv)
522 return need_size;
524 if (reconv->dwSize < need_size)
525 return 0;
527 // TODO(penghuang): Return some extra context to help improve IME's
528 // reconversion accuracy.
529 base::string16 text;
530 if (!GetTextInputClient()->GetTextFromRange(selection_range, &text))
531 return 0;
532 DCHECK_EQ(selection_range.length(), text.length());
534 reconv->dwVersion = 0;
535 reconv->dwStrLen = len;
536 reconv->dwStrOffset = sizeof(RECONVERTSTRING);
537 reconv->dwCompStrLen = len;
538 reconv->dwCompStrOffset = 0;
539 reconv->dwTargetStrLen = len;
540 reconv->dwTargetStrOffset = 0;
542 memcpy(reinterpret_cast<char*>(reconv) + sizeof(RECONVERTSTRING),
543 text.c_str(), len * sizeof(WCHAR));
545 // According to Microsoft API document, IMR_RECONVERTSTRING and
546 // IMR_DOCUMENTFEED should return reconv, but some applications return
547 // need_size.
548 return reinterpret_cast<LRESULT>(reconv);
551 LRESULT InputMethodWin::OnQueryCharPosition(IMECHARPOSITION* char_positon) {
552 if (!char_positon)
553 return 0;
555 if (char_positon->dwSize < sizeof(IMECHARPOSITION))
556 return 0;
558 ui::TextInputClient* client = GetTextInputClient();
559 if (!client)
560 return 0;
562 // Tentatively assume that the returned value from |client| is DIP (Density
563 // Independent Pixel). See the comment in text_input_client.h and
564 // http://crbug.com/360334.
565 gfx::Rect dip_rect;
566 if (client->HasCompositionText()) {
567 if (!client->GetCompositionCharacterBounds(char_positon->dwCharPos,
568 &dip_rect)) {
569 return 0;
571 } else {
572 // If there is no composition and the first character is queried, returns
573 // the caret bounds. This behavior is the same to that of RichEdit control.
574 if (char_positon->dwCharPos != 0)
575 return 0;
576 dip_rect = client->GetCaretBounds();
578 const gfx::Rect rect = gfx::win::DIPToScreenRect(dip_rect);
580 char_positon->pt.x = rect.x();
581 char_positon->pt.y = rect.y();
582 char_positon->cLineHeight = rect.height();
583 return 1; // returns non-zero value when succeeded.
586 HWND InputMethodWin::GetAttachedWindowHandle(
587 const TextInputClient* text_input_client) const {
588 // On Aura environment, we can assume that |toplevel_window_handle_| always
589 // represents the valid top-level window handle because each top-level window
590 // is responsible for lifecycle management of corresponding InputMethod
591 // instance.
592 return toplevel_window_handle_;
595 bool InputMethodWin::IsWindowFocused(const TextInputClient* client) const {
596 if (!client)
597 return false;
598 HWND attached_window_handle = GetAttachedWindowHandle(client);
599 // When Aura is enabled, |attached_window_handle| should always be a top-level
600 // window. So we can safely assume that |attached_window_handle| is ready for
601 // receiving keyboard input as long as it is an active window. This works well
602 // even when the |attached_window_handle| becomes active but has not received
603 // WM_FOCUS yet.
604 return attached_window_handle && GetActiveWindow() == attached_window_handle;
607 bool InputMethodWin::DispatchFabricatedKeyEvent(const ui::KeyEvent& event) {
608 if (event.is_char()) {
609 if (GetTextInputClient()) {
610 GetTextInputClient()->InsertChar(
611 static_cast<base::char16>(event.key_code()),
612 ui::GetModifiersFromKeyState());
613 return true;
616 return DispatchKeyEventPostIME(event);
619 void InputMethodWin::ConfirmCompositionText() {
620 if (composing_window_handle_)
621 imm32_manager_.CleanupComposition(composing_window_handle_);
623 if (!IsTextInputTypeNone()) {
624 // Though above line should confirm the client's composition text by sending
625 // a result text to us, in case the input method and the client are in
626 // inconsistent states, we check the client's composition state again.
627 if (GetTextInputClient()->HasCompositionText())
628 GetTextInputClient()->ConfirmCompositionText();
632 void InputMethodWin::UpdateIMEState() {
633 // Use switch here in case we are going to add more text input types.
634 // We disable input method in password field.
635 const HWND window_handle = GetAttachedWindowHandle(GetTextInputClient());
636 const TextInputType text_input_type = GetTextInputType();
637 const TextInputMode text_input_mode = GetTextInputMode();
638 switch (text_input_type) {
639 case ui::TEXT_INPUT_TYPE_NONE:
640 case ui::TEXT_INPUT_TYPE_PASSWORD:
641 imm32_manager_.DisableIME(window_handle);
642 enabled_ = false;
643 break;
644 default:
645 imm32_manager_.EnableIME(window_handle);
646 enabled_ = true;
647 break;
650 imm32_manager_.SetTextInputMode(window_handle, text_input_mode);
651 tsf_inputscope::SetInputScopeForTsfUnawareWindow(
652 window_handle, text_input_type, text_input_mode);
655 } // namespace ui