1eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Copyright (c) 2013 The Chromium Authors. All rights reserved. 27d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 37d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// found in the LICENSE file. 47d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 57d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "ui/base/ime/input_method_imm32.h" 67d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 77d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/basictypes.h" 87d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "ui/base/ime/composition_text.h" 97d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "ui/base/ime/text_input_client.h" 1068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ui/base/ime/win/tsf_input_scope.h" 117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)namespace ui { 147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)InputMethodIMM32::InputMethodIMM32(internal::InputMethodDelegate* delegate, 167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) HWND toplevel_window_handle) 177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) : InputMethodWin(delegate, toplevel_window_handle), 18eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch enabled_(false), is_candidate_popup_open_(false), 19eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch composing_window_handle_(NULL) { 20eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // In non-Aura environment, appropriate callbacks to OnFocus() and OnBlur() 21eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // are not implemented yet. To work around this limitation, here we use 22eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // "always focused" model. 23eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // TODO(ime): Fix the caller of OnFocus() and OnBlur() so that appropriate 24eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // focus event will be passed. 25eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch InputMethodWin::OnFocus(); 267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void InputMethodIMM32::OnFocus() { 29eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Ignore OnFocus event for "always focused" model. See the comment in the 30eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // constructor. 31eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // TODO(ime): Implement OnFocus once the callers are fixed. 327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void InputMethodIMM32::OnBlur() { 35eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Ignore OnBlur event for "always focused" model. See the comment in the 36eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // constructor. 37eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // TODO(ime): Implement OnFocus once the callers are fixed. 387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)bool InputMethodIMM32::OnUntranslatedIMEMessage( 417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const base::NativeEvent& event, InputMethod::NativeEventResult* result) { 427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) LRESULT original_result = 0; 437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) BOOL handled = FALSE; 447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) switch (event.message) { 457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) case WM_IME_SETCONTEXT: 467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) original_result = OnImeSetContext( 47eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch event.hwnd, event.message, event.wParam, event.lParam, &handled); 487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) break; 497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) case WM_IME_STARTCOMPOSITION: 507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) original_result = OnImeStartComposition( 51eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch event.hwnd, event.message, event.wParam, event.lParam, &handled); 527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) break; 537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) case WM_IME_COMPOSITION: 547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) original_result = OnImeComposition( 55eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch event.hwnd, event.message, event.wParam, event.lParam, &handled); 567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) break; 577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) case WM_IME_ENDCOMPOSITION: 587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) original_result = OnImeEndComposition( 59eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch event.hwnd, event.message, event.wParam, event.lParam, &handled); 607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) break; 617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) case WM_IME_REQUEST: 627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) original_result = OnImeRequest( 637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) event.message, event.wParam, event.lParam, &handled); 647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) break; 657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) case WM_CHAR: 667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) case WM_SYSCHAR: 677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) original_result = OnChar( 68558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch event.hwnd, event.message, event.wParam, event.lParam, &handled); 697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) break; 707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) case WM_DEADCHAR: 717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) case WM_SYSDEADCHAR: 727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) original_result = OnDeadChar( 737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) event.message, event.wParam, event.lParam, &handled); 747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) break; 75eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch case WM_IME_NOTIFY: 76eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch original_result = OnImeNotify( 77eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch event.message, event.wParam, event.lParam, &handled); 78eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch break; 797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) default: 807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) NOTREACHED() << "Unknown IME message:" << event.message; 817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) break; 827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (result) 847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) *result = original_result; 857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return !!handled; 867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void InputMethodIMM32::OnTextInputTypeChanged(const TextInputClient* client) { 89eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (IsTextInputClientFocused(client) && IsWindowFocused(client)) { 909ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch imm32_manager_.CancelIME(GetAttachedWindowHandle(client)); 917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) UpdateIMEState(); 927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) InputMethodWin::OnTextInputTypeChanged(client); 947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void InputMethodIMM32::OnCaretBoundsChanged(const TextInputClient* client) { 97f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!enabled_ || !IsTextInputClientFocused(client) || 98f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) !IsWindowFocused(client)) { 99f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return; 1001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 101f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // The current text input type should not be NONE if |client| is focused. 102f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(!IsTextInputTypeNone()); 103f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) gfx::Rect screen_bounds(GetTextInputClient()->GetCaretBounds()); 104f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 105f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) HWND attached_window = GetAttachedWindowHandle(client); 106f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // TODO(ime): see comment in TextInputClient::GetCaretBounds(), this 107f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // conversion shouldn't be necessary. 108f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) RECT r = {}; 109f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) GetClientRect(attached_window, &r); 110f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) POINT window_point = { screen_bounds.x(), screen_bounds.y() }; 111f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ScreenToClient(attached_window, &window_point); 112f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) gfx::Rect caret_rect(gfx::Point(window_point.x, window_point.y), 113f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) screen_bounds.size()); 114f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) imm32_manager_.UpdateCaretRect(attached_window, caret_rect); 1157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 1167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 1177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void InputMethodIMM32::CancelComposition(const TextInputClient* client) { 1187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (enabled_ && IsTextInputClientFocused(client)) 1199ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch imm32_manager_.CancelIME(GetAttachedWindowHandle(client)); 1207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 1217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 122eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool InputMethodIMM32::IsCandidatePopupOpen() const { 123eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return is_candidate_popup_open_; 124eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 125eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void InputMethodIMM32::OnWillChangeFocusedClient( 1277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) TextInputClient* focused_before, 1287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) TextInputClient* focused) { 129eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (IsWindowFocused(focused_before)) { 130eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ConfirmCompositionText(); 131eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 1327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 1337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 1347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void InputMethodIMM32::OnDidChangeFocusedClient(TextInputClient* focused_before, 1357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) TextInputClient* focused) { 136eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (IsWindowFocused(focused)) { 137eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Force to update the input type since client's TextInputStateChanged() 138eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // function might not be called if text input types before the client loses 139eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // focus and after it acquires focus again are the same. 140eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch OnTextInputTypeChanged(focused); 1417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 142eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch UpdateIMEState(); 1437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 144eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Force to update caret bounds, in case the client thinks that the caret 145eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // bounds has not changed. 146eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch OnCaretBoundsChanged(focused); 147eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 148f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) InputMethodWin::OnDidChangeFocusedClient(focused_before, focused); 1497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 1507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 151eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochLRESULT InputMethodIMM32::OnImeSetContext(HWND window_handle, 152eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch UINT message, 1537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) WPARAM wparam, 1547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) LPARAM lparam, 1557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) BOOL* handled) { 15668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (!!wparam) 1579ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch imm32_manager_.CreateImeWindow(window_handle); 1587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 1597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) OnInputMethodChanged(); 1609ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch return imm32_manager_.SetImeWindowStyle( 161eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch window_handle, message, wparam, lparam, handled); 1627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 1637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 164eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochLRESULT InputMethodIMM32::OnImeStartComposition(HWND window_handle, 165eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch UINT message, 1667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) WPARAM wparam, 1677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) LPARAM lparam, 1687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) BOOL* handled) { 1697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // We have to prevent WTL from calling ::DefWindowProc() because the function 1707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // calls ::ImmSetCompositionWindow() and ::ImmSetCandidateWindow() to 1717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // over-write the position of IME windows. 1727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) *handled = TRUE; 1737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 1747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Reset the composition status and create IME windows. 175eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch composing_window_handle_ = window_handle; 1769ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch imm32_manager_.CreateImeWindow(window_handle); 1779ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch imm32_manager_.ResetComposition(window_handle); 1787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return 0; 1797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 1807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 181eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochLRESULT InputMethodIMM32::OnImeComposition(HWND window_handle, 182eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch UINT message, 1837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) WPARAM wparam, 1847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) LPARAM lparam, 1857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) BOOL* handled) { 1867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // We have to prevent WTL from calling ::DefWindowProc() because we do not 1877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // want for the IMM (Input Method Manager) to send WM_IME_CHAR messages. 1887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) *handled = TRUE; 1897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 1907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // At first, update the position of the IME window. 1919ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch imm32_manager_.UpdateImeWindow(window_handle); 1927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 1937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Retrieve the result string and its attributes of the ongoing composition 1947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // and send it to a renderer process. 1957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) ui::CompositionText composition; 1969ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch if (imm32_manager_.GetResult(window_handle, lparam, &composition.text)) { 197eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!IsTextInputTypeNone()) 198eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch GetTextInputClient()->InsertText(composition.text); 1999ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch imm32_manager_.ResetComposition(window_handle); 2007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Fall though and try reading the composition string. 2017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Japanese IMEs send a message containing both GCS_RESULTSTR and 2027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // GCS_COMPSTR, which means an ongoing composition has been finished 2037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // by the start of another composition. 2047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 2057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Retrieve the composition string and its attributes of the ongoing 2067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // composition and send it to a renderer process. 2079ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch if (imm32_manager_.GetComposition(window_handle, lparam, &composition) && 208eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch !IsTextInputTypeNone()) 2097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) GetTextInputClient()->SetCompositionText(composition); 2107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 2117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return 0; 2127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 2137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 214eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochLRESULT InputMethodIMM32::OnImeEndComposition(HWND window_handle, 215eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch UINT message, 2167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) WPARAM wparam, 2177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) LPARAM lparam, 2187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) BOOL* handled) { 2197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Let WTL call ::DefWindowProc() and release its resources. 2207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) *handled = FALSE; 2217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 222eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch composing_window_handle_ = NULL; 2237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 224eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!IsTextInputTypeNone() && GetTextInputClient()->HasCompositionText()) 2257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) GetTextInputClient()->ClearCompositionText(); 2267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 2279ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch imm32_manager_.ResetComposition(window_handle); 2289ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch imm32_manager_.DestroyImeWindow(window_handle); 229eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return 0; 230eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 231eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 232eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochLRESULT InputMethodIMM32::OnImeNotify(UINT message, 233eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch WPARAM wparam, 234eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch LPARAM lparam, 235eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch BOOL* handled) { 236eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch *handled = FALSE; 237eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 238a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool previous_state = is_candidate_popup_open_; 239a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 240eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Update |is_candidate_popup_open_|, whether a candidate window is open. 241eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch switch (wparam) { 242eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch case IMN_OPENCANDIDATE: 243eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch is_candidate_popup_open_ = true; 244a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!previous_state) 245a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) OnCandidateWindowShown(); 246eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch break; 247eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch case IMN_CLOSECANDIDATE: 248eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch is_candidate_popup_open_ = false; 249a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (previous_state) 250a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) OnCandidateWindowHidden(); 251a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) break; 252a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) case IMN_CHANGECANDIDATE: 253a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // TODO(kochi): The IME API expects this event to notify window size change, 254a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // while this may fire more often without window resize. There is no generic 255a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // way to get bounds of candidate window. 256a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) OnCandidateWindowUpdated(); 257eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch break; 258eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 259eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return 0; 2617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 2627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 2637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void InputMethodIMM32::ConfirmCompositionText() { 264eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (composing_window_handle_) 2659ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch imm32_manager_.CleanupComposition(composing_window_handle_); 2667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 267eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!IsTextInputTypeNone()) { 2687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Though above line should confirm the client's composition text by sending 2697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // a result text to us, in case the input method and the client are in 2707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // inconsistent states, we check the client's composition state again. 2717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (GetTextInputClient()->HasCompositionText()) 2727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) GetTextInputClient()->ConfirmCompositionText(); 2737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 2747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 2757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 2767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void InputMethodIMM32::UpdateIMEState() { 2777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Use switch here in case we are going to add more text input types. 2787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // We disable input method in password field. 27958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const HWND window_handle = GetAttachedWindowHandle(GetTextInputClient()); 28068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const TextInputType text_input_type = GetTextInputType(); 28168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const TextInputMode text_input_mode = GetTextInputMode(); 28268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) switch (text_input_type) { 2837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) case ui::TEXT_INPUT_TYPE_NONE: 2847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) case ui::TEXT_INPUT_TYPE_PASSWORD: 28558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) imm32_manager_.DisableIME(window_handle); 2867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) enabled_ = false; 2877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) break; 2887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) default: 28958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) imm32_manager_.EnableIME(window_handle); 2907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) enabled_ = true; 2917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) break; 2927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 2937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 29468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) imm32_manager_.SetTextInputMode(window_handle, text_input_mode); 29568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) tsf_inputscope::SetInputScopeForTsfUnawareWindow( 29668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) window_handle, text_input_type, text_input_mode); 297eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 298eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} // namespace ui 300