19ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// Copyright 2013 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 59ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "ui/base/ime/win/imm32_manager.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <msctf.h> 890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/string16.h" 127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/string_util.h" 13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 1490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/win/scoped_comptr.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/skia/include/core/SkColor.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/ime/composition_text.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "imm32.lib" is required by IMM32 APIs used in this file. 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// NOTE(hbono): To comply with a comment from Darin, I have added 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// this #pragma directive instead of adding "imm32.lib" to a project file. 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma comment(lib, "imm32.lib") 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Following code requires wchar_t to be same as char16. It should always be 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// true on Windows. 255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)COMPILE_ASSERT(sizeof(wchar_t) == sizeof(base::char16), wchar_t__char16_diff); 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/////////////////////////////////////////////////////////////////////////////// 289ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// IMM32Manager 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Determines whether or not the given attribute represents a target 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (a.k.a. a selection). 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsTargetAttribute(char attribute) { 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (attribute == ATTR_TARGET_CONVERTED || 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) attribute == ATTR_TARGET_NOTCONVERTED); 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 399ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// Helper function for IMM32Manager::GetCompositionInfo() method, to get the 409ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// target range that's selected by the user in the current composition string. 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GetCompositionTargetRange(HIMC imm_context, int* target_start, 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* target_end) { 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int attribute_size = ::ImmGetCompositionString(imm_context, GCS_COMPATTR, 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, 0); 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (attribute_size > 0) { 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int start = 0; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int end = 0; 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<char[]> attribute_data(new char[attribute_size]); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (attribute_data.get()) { 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::ImmGetCompositionString(imm_context, GCS_COMPATTR, 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) attribute_data.get(), attribute_size); 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (start = 0; start < attribute_size; ++start) { 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsTargetAttribute(attribute_data[start])) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (end = start; end < attribute_size; ++end) { 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!IsTargetAttribute(attribute_data[end])) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *target_start = start; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *target_end = end; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 669ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// Helper function for IMM32Manager::GetCompositionInfo() method, to get 679ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// underlines information of the current composition string. 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GetCompositionUnderlines(HIMC imm_context, 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int target_start, 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int target_end, 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::CompositionUnderlines* underlines) { 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int clause_size = ::ImmGetCompositionString(imm_context, GCS_COMPCLAUSE, 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, 0); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int clause_length = clause_size / sizeof(uint32); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (clause_length) { 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<uint32[]> clause_data(new uint32[clause_length]); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (clause_data.get()) { 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::ImmGetCompositionString(imm_context, GCS_COMPCLAUSE, 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) clause_data.get(), clause_size); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < clause_length - 1; ++i) { 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::CompositionUnderline underline; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) underline.start_offset = clause_data[i]; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) underline.end_offset = clause_data[i+1]; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) underline.color = SK_ColorBLACK; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) underline.thick = false; 866d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) underline.background_color = SK_ColorTRANSPARENT; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Use thick underline for the target clause. 896d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if (underline.start_offset >= static_cast<uint32>(target_start) && 906d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) underline.end_offset <= static_cast<uint32>(target_end)) { 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) underline.thick = true; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) underlines->push_back(underline); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Checks if a given primary language ID is a RTL language. 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsRTLPrimaryLangID(LANGID lang) { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (lang) { 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case LANG_ARABIC: 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case LANG_HEBREW: 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case LANG_PERSIAN: 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case LANG_SYRIAC: 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case LANG_UIGHUR: 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case LANG_URDU: 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ui { 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1189ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben MurdochIMM32Manager::IMM32Manager() 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : ime_status_(false), 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) input_language_id_(LANG_USER_DEFAULT), 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_composing_(false), 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) system_caret_(false), 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) caret_rect_(-1, -1, 0, 0), 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) use_composition_window_(false) { 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1279ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben MurdochIMM32Manager::~IMM32Manager() { 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1309ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochbool IMM32Manager::SetInputLanguage() { 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Retrieve the current keyboard layout from Windows and determine whether 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // or not the current input context has IMEs. 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Also save its input language for language-specific operations required 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // while composing a text. 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HKL keyboard_layout = ::GetKeyboardLayout(0); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) input_language_id_ = reinterpret_cast<LANGID>(keyboard_layout); 13790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 13890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Check TSF Input Processor first. 13990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // If the active profile is TSF INPUTPROCESSOR, this is IME. 14090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::win::ScopedComPtr<ITfInputProcessorProfileMgr> prof_mgr; 14190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) TF_INPUTPROCESSORPROFILE prof; 14290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (SUCCEEDED(prof_mgr.CreateInstance(CLSID_TF_InputProcessorProfiles)) && 14390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SUCCEEDED(prof_mgr->GetActiveProfile(GUID_TFCAT_TIP_KEYBOARD, &prof)) && 14490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) prof.hkl == NULL && 14590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) prof.dwProfileType == TF_PROFILETYPE_INPUTPROCESSOR) { 14690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ime_status_ = true; 14790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } else { 14890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // If the curent language is not using TSF, check IMM32 based IMEs. 14990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // As ImmIsIME always returns non-0 value on Vista+, use ImmGetIMEFileName 15090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // instead to check if this HKL has any associated IME file. 15190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ime_status_ = (ImmGetIMEFileName(keyboard_layout, NULL, 0) != 0); 15290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 15390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ime_status_; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1579ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochvoid IMM32Manager::CreateImeWindow(HWND window_handle) { 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When a user disables TSF (Text Service Framework) and CUAS (Cicero 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Unaware Application Support), Chinese IMEs somehow ignore function calls 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to ::ImmSetCandidateWindow(), i.e. they do not move their candidate 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // window to the position given as its parameters, and use the position 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // of the current system caret instead, i.e. it uses ::GetCaretPos() to 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // retrieve the position of their IME candidate window. 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Therefore, we create a temporary system caret for Chinese IMEs and use 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // it during this input context. 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Since some third-party Japanese IME also uses ::GetCaretPos() to determine 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // their window position, we also create a caret for Japanese IMEs. 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (PRIMARYLANGID(input_language_id_) == LANG_CHINESE || 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PRIMARYLANGID(input_language_id_) == LANG_JAPANESE) { 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!system_caret_) { 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (::CreateCaret(window_handle, NULL, 1, 1)) { 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) system_caret_ = true; 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Restore the positions of the IME windows. 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateImeWindow(window_handle); 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1809ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben MurdochLRESULT IMM32Manager::SetImeWindowStyle(HWND window_handle, UINT message, 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WPARAM wparam, LPARAM lparam, 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BOOL* handled) { 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // To prevent the IMM (Input Method Manager) from displaying the IME 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // composition window, Update the styles of the IME windows and EXPLICITLY 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // call ::DefWindowProc() here. 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NOTE(hbono): We can NEVER let WTL call ::DefWindowProc() when we update 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the styles of IME windows because the 'lparam' variable is a local one 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and all its updates disappear in returning from this function, i.e. WTL 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // does not call ::DefWindowProc() with our updated 'lparam' value but call 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the function with its original value and over-writes our window styles. 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *handled = TRUE; 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lparam &= ~ISC_SHOWUICOMPOSITIONWINDOW; 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ::DefWindowProc(window_handle, message, wparam, lparam); 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1969ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochvoid IMM32Manager::DestroyImeWindow(HWND window_handle) { 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Destroy the system caret if we have created for this IME input context. 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (system_caret_) { 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::DestroyCaret(); 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) system_caret_ = false; 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2049ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochvoid IMM32Manager::MoveImeWindow(HWND window_handle, HIMC imm_context) { 20590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Does nothing when the target window has no input focus. This is important 20690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // because the renderer may issue SelectionBoundsChanged event even when it 20790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // has no input focus. (e.g. the page update caused by incremental search.) 20890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // So this event should be ignored when the |window_handle| no longer has the 20990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // input focus. 21090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (GetFocus() != window_handle) 21190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return; 21290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int x = caret_rect_.x(); 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int y = caret_rect_.y(); 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kCaretMargin = 1; 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!use_composition_window_ && 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PRIMARYLANGID(input_language_id_) == LANG_CHINESE) { 2199ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // As written in a comment in IMM32Manager::CreateImeWindow(), 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Chinese IMEs ignore function calls to ::ImmSetCandidateWindow() 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // when a user disables TSF (Text Service Framework) and CUAS (Cicero 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Unaware Application Support). 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // On the other hand, when a user enables TSF and CUAS, Chinese IMEs 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ignore the position of the current system caret and uses the 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // parameters given to ::ImmSetCandidateWindow() with its 'dwStyle' 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // parameter CFS_CANDIDATEPOS. 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Therefore, we do not only call ::ImmSetCandidateWindow() but also 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // set the positions of the temporary system caret if it exists. 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CANDIDATEFORM candidate_position = {0, CFS_CANDIDATEPOS, {x, y}, 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) {0, 0, 0, 0}}; 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::ImmSetCandidateWindow(imm_context, &candidate_position); 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (system_caret_) { 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (PRIMARYLANGID(input_language_id_)) { 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case LANG_JAPANESE: 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::SetCaretPos(x, y + caret_rect_.height()); 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::SetCaretPos(x, y); 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (use_composition_window_) { 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Moves the composition text window. 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) COMPOSITIONFORM cf = {CFS_POINT, {x, y}}; 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::ImmSetCompositionWindow(imm_context, &cf); 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Don't need to set the position of candidate window. 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (PRIMARYLANGID(input_language_id_) == LANG_KOREAN) { 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Chinese IMEs and Japanese IMEs require the upper-left corner of 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the caret to move the position of their candidate windows. 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // On the other hand, Korean IMEs require the lower-left corner of the 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // caret to move their candidate windows. 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) y += kCaretMargin; 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Japanese IMEs and Korean IMEs also use the rectangle given to 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ::ImmSetCandidateWindow() with its 'dwStyle' parameter CFS_EXCLUDE 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to move their candidate windows when a user disables TSF and CUAS. 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Therefore, we also set this parameter here. 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CANDIDATEFORM exclude_rectangle = {0, CFS_EXCLUDE, {x, y}, 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) {x, y, x + caret_rect_.width(), y + caret_rect_.height()}}; 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::ImmSetCandidateWindow(imm_context, &exclude_rectangle); 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2679ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochvoid IMM32Manager::UpdateImeWindow(HWND window_handle) { 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Just move the IME window attached to the given window. 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (caret_rect_.x() >= 0 && caret_rect_.y() >= 0) { 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HIMC imm_context = ::ImmGetContext(window_handle); 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (imm_context) { 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MoveImeWindow(window_handle, imm_context); 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::ImmReleaseContext(window_handle, imm_context); 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2789ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochvoid IMM32Manager::CleanupComposition(HWND window_handle) { 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Notify the IMM attached to the given window to complete the ongoing 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // composition, (this case happens when the given window is de-activated 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // while composing a text and re-activated), and reset the omposition status. 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (is_composing_) { 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HIMC imm_context = ::ImmGetContext(window_handle); 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (imm_context) { 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::ImmNotifyIME(imm_context, NI_COMPOSITIONSTR, CPS_COMPLETE, 0); 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::ImmReleaseContext(window_handle, imm_context); 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResetComposition(window_handle); 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2929ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochvoid IMM32Manager::ResetComposition(HWND window_handle) { 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Currently, just reset the composition status. 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_composing_ = false; 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2979ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochvoid IMM32Manager::CompleteComposition(HWND window_handle, HIMC imm_context) { 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We have to confirm there is an ongoing composition before completing it. 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is for preventing some IMEs from getting confused while completing an 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ongoing composition even if they do not have any ongoing compositions.) 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (is_composing_) { 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::ImmNotifyIME(imm_context, NI_COMPOSITIONSTR, CPS_COMPLETE, 0); 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResetComposition(window_handle); 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3079ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochvoid IMM32Manager::GetCompositionInfo(HIMC imm_context, LPARAM lparam, 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CompositionText* composition) { 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We only care about GCS_COMPATTR, GCS_COMPCLAUSE and GCS_CURSORPOS, and 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // convert them into underlines and selection range respectively. 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) composition->underlines.clear(); 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int length = static_cast<int>(composition->text.length()); 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Find out the range selected by the user. 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int target_start = length; 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int target_end = length; 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (lparam & GCS_COMPATTR) 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetCompositionTargetRange(imm_context, &target_start, &target_end); 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Retrieve the selection range information. If CS_NOMOVECARET is specified, 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that means the cursor should not be moved, then we just place the caret at 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the beginning of the composition string. Otherwise we should honour the 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // GCS_CURSORPOS value if it's available. 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(suzhe): due to a bug of webkit, we currently can't use selection range 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // with composition string. See: https://bugs.webkit.org/show_bug.cgi?id=40805 32790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!(lparam & CS_NOMOVECARET) && (lparam & GCS_CURSORPOS)) { 32890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // IMM32 does not support non-zero-width selection in a composition. So 32990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // always use the caret position as selection range. 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int cursor = ::ImmGetCompositionString(imm_context, GCS_CURSORPOS, NULL, 0); 33158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) composition->selection = gfx::Range(cursor); 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 33358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) composition->selection = gfx::Range(0); 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Retrieve the clause segmentations and convert them to underlines. 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (lparam & GCS_COMPCLAUSE) { 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetCompositionUnderlines(imm_context, target_start, target_end, 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &composition->underlines); 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set default underlines in case there is no clause information. 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!composition->underlines.size()) { 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CompositionUnderline underline; 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) underline.color = SK_ColorBLACK; 3466d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) underline.background_color = SK_ColorTRANSPARENT; 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (target_start > 0) { 3486d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) underline.start_offset = 0U; 3496d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) underline.end_offset = static_cast<uint32>(target_start); 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) underline.thick = false; 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) composition->underlines.push_back(underline); 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (target_end > target_start) { 3546d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) underline.start_offset = static_cast<uint32>(target_start); 3556d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) underline.end_offset = static_cast<uint32>(target_end); 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) underline.thick = true; 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) composition->underlines.push_back(underline); 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (target_end < length) { 3606d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) underline.start_offset = static_cast<uint32>(target_end); 3616d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) underline.end_offset = static_cast<uint32>(length); 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) underline.thick = false; 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) composition->underlines.push_back(underline); 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3689ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochbool IMM32Manager::GetString(HIMC imm_context, 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WPARAM lparam, 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int type, 3715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::string16* result) { 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!(lparam & type)) 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LONG string_size = ::ImmGetCompositionString(imm_context, type, NULL, 0); 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (string_size <= 0) 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(0u, string_size % sizeof(wchar_t)); 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::ImmGetCompositionString(imm_context, type, 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteInto(result, (string_size / sizeof(wchar_t)) + 1), string_size); 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3839ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochbool IMM32Manager::GetResult( 3845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) HWND window_handle, LPARAM lparam, base::string16* result) { 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool ret = false; 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HIMC imm_context = ::ImmGetContext(window_handle); 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (imm_context) { 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = GetString(imm_context, lparam, GCS_RESULTSTR, result); 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::ImmReleaseContext(window_handle, imm_context); 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ret; 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3949ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochbool IMM32Manager::GetComposition(HWND window_handle, LPARAM lparam, 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CompositionText* composition) { 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool ret = false; 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HIMC imm_context = ::ImmGetContext(window_handle); 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (imm_context) { 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Copy the composition string to the CompositionText object. 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = GetString(imm_context, lparam, GCS_COMPSTR, &composition->text); 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ret) { 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is a dirty workaround for facebook. Facebook deletes the 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // placeholder character (U+3000) used by Traditional-Chinese IMEs at the 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // beginning of composition text. This prevents WebKit from replacing this 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // placeholder character with a Traditional-Chinese character, i.e. we 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // cannot input any characters in a comment box of facebook with 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Traditional-Chinese IMEs. As a workaround, we replace U+3000 at the 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // beginning of composition text with U+FF3F, a placeholder character used 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // by Japanese IMEs. 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (input_language_id_ == MAKELANGID(LANG_CHINESE, 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SUBLANG_CHINESE_TRADITIONAL) && 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) composition->text[0] == 0x3000) { 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) composition->text[0] = 0xFF3F; 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Retrieve the composition underlines and selection range information. 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetCompositionInfo(imm_context, lparam, composition); 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Mark that there is an ongoing composition. 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_composing_ = true; 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::ImmReleaseContext(window_handle, imm_context); 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ret; 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4299ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochvoid IMM32Manager::DisableIME(HWND window_handle) { 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // A renderer process have moved its input focus to a password input 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // when there is an ongoing composition, e.g. a user has clicked a 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // mouse button and selected a password input while composing a text. 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For this case, we have to complete the ongoing composition and 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // clean up the resources attached to this object BEFORE DISABLING THE IME. 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CleanupComposition(window_handle); 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::ImmAssociateContextEx(window_handle, NULL, 0); 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4399ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochvoid IMM32Manager::CancelIME(HWND window_handle) { 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (is_composing_) { 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HIMC imm_context = ::ImmGetContext(window_handle); 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (imm_context) { 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::ImmNotifyIME(imm_context, NI_COMPOSITIONSTR, CPS_CANCEL, 0); 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::ImmReleaseContext(window_handle, imm_context); 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResetComposition(window_handle); 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4509ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochvoid IMM32Manager::EnableIME(HWND window_handle) { 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Load the default IME context. 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NOTE(hbono) 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // IMM ignores this call if the IME context is loaded. Therefore, we do 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // not have to check whether or not the IME context is loaded. 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::ImmAssociateContextEx(window_handle, NULL, IACE_DEFAULT); 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4589ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochvoid IMM32Manager::UpdateCaretRect(HWND window_handle, 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Rect& caret_rect) { 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Save the caret position, and Update the position of the IME window. 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This update is used for moving an IME window when a renderer process 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // resize/moves the input caret. 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (caret_rect_ != caret_rect) { 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) caret_rect_ = caret_rect; 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Move the IME windows. 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HIMC imm_context = ::ImmGetContext(window_handle); 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (imm_context) { 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MoveImeWindow(window_handle, imm_context); 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::ImmReleaseContext(window_handle, imm_context); 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4749ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochvoid IMM32Manager::SetUseCompositionWindow(bool use_composition_window) { 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) use_composition_window_ = use_composition_window; 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4789ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochstd::string IMM32Manager::GetInputLanguageName() const { 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const LCID locale_id = MAKELCID(input_language_id_, SORT_DEFAULT); 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // max size for LOCALE_SISO639LANGNAME and LOCALE_SISO3166CTRYNAME is 9. 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wchar_t buffer[9]; 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get language id. 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int length = ::GetLocaleInfo(locale_id, LOCALE_SISO639LANGNAME, &buffer[0], 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) arraysize(buffer)); 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (length <= 1) 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return std::string(); 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string language; 4905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::WideToUTF8(buffer, length - 1, &language); 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (SUBLANGID(input_language_id_) == SUBLANG_NEUTRAL) 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return language; 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get region id. 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) length = ::GetLocaleInfo(locale_id, LOCALE_SISO3166CTRYNAME, &buffer[0], 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) arraysize(buffer)); 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (length <= 1) 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return language; 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string region; 5015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::WideToUTF8(buffer, length - 1, ®ion); 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return language.append(1, '-').append(region); 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void IMM32Manager::SetTextInputMode(HWND window_handle, 506a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) TextInputMode input_mode) { 507a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (input_mode == ui::TEXT_INPUT_MODE_DEFAULT) 508a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return; 509a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 510a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const HIMC imm_context = ::ImmGetContext(window_handle); 511a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (!imm_context) 512a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return; 513a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 514a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) DWORD conversion_mode = 0; 515a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) DWORD sentence_mode = 0; 516a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (::ImmGetConversionStatus(imm_context, &conversion_mode, &sentence_mode) 517a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) == FALSE) { 518a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return; 519a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 520a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 521a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) BOOL open = FALSE; 522a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) ConvertInputModeToImmFlags(input_mode, conversion_mode, &open, 523a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) &conversion_mode), 524a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 525a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) ::ImmSetOpenStatus(imm_context, open); 526a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (open) 527a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) ::ImmSetConversionStatus(imm_context, conversion_mode, sentence_mode); 528a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) ::ImmReleaseContext(window_handle, imm_context); 529a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 530a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 5329ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochbool IMM32Manager::IsRTLKeyboardLayoutInstalled() { 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static enum { 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RTL_KEYBOARD_LAYOUT_NOT_INITIALIZED, 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RTL_KEYBOARD_LAYOUT_INSTALLED, 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RTL_KEYBOARD_LAYOUT_NOT_INSTALLED, 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RTL_KEYBOARD_LAYOUT_ERROR, 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } layout = RTL_KEYBOARD_LAYOUT_NOT_INITIALIZED; 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Cache the result value. 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (layout != RTL_KEYBOARD_LAYOUT_NOT_INITIALIZED) 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return layout == RTL_KEYBOARD_LAYOUT_INSTALLED; 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Retrieve the number of layouts installed in this system. 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int size = GetKeyboardLayoutList(0, NULL); 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (size <= 0) { 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) layout = RTL_KEYBOARD_LAYOUT_ERROR; 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Retrieve the keyboard layouts in an array and check if there is an RTL 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // layout in it. 5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<HKL[]> layouts(new HKL[size]); 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::GetKeyboardLayoutList(size, layouts.get()); 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < size; ++i) { 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsRTLPrimaryLangID(PRIMARYLANGID(layouts[i]))) { 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) layout = RTL_KEYBOARD_LAYOUT_INSTALLED; 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) layout = RTL_KEYBOARD_LAYOUT_NOT_INSTALLED; 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5669ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochbool IMM32Manager::IsCtrlShiftPressed(base::i18n::TextDirection* direction) { 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8_t keystate[256]; 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!::GetKeyboardState(&keystate[0])) 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // To check if a user is pressing only a control key and a right-shift key 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (or a left-shift key), we use the steps below: 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 1. Check if a user is pressing a control key and a right-shift key (or 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a left-shift key). 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 2. If the condition 1 is true, we should check if there are any other 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // keys pressed at the same time. 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // To ignore the keys checked in 1, we set their status to 0 before 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // checking the key status. 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kKeyDownMask = 0x80; 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((keystate[VK_CONTROL] & kKeyDownMask) == 0) 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (keystate[VK_RSHIFT] & kKeyDownMask) { 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) keystate[VK_RSHIFT] = 0; 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *direction = base::i18n::RIGHT_TO_LEFT; 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (keystate[VK_LSHIFT] & kKeyDownMask) { 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) keystate[VK_LSHIFT] = 0; 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *direction = base::i18n::LEFT_TO_RIGHT; 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Scan the key status to find pressed keys. We should abandon changing the 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // text direction when there are other pressed keys. 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This code is executed only when a user is pressing a control key and a 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // right-shift key (or a left-shift key), i.e. we should ignore the status of 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the keys: VK_SHIFT, VK_CONTROL, VK_RCONTROL, and VK_LCONTROL. 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // So, we reset their status to 0 and ignore them. 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) keystate[VK_SHIFT] = 0; 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) keystate[VK_CONTROL] = 0; 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) keystate[VK_RCONTROL] = 0; 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) keystate[VK_LCONTROL] = 0; 603f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Oddly, pressing F10 in another application seemingly breaks all subsequent 604f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // calls to GetKeyboardState regarding the state of the F22 key. Perhaps this 605f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // defect is limited to my keyboard driver, but ignoring F22 should be okay. 606f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) keystate[VK_F22] = 0; 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i <= VK_PACKET; ++i) { 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (keystate[i] & kKeyDownMask) 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 614a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void IMM32Manager::ConvertInputModeToImmFlags(TextInputMode input_mode, 615a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) DWORD initial_conversion_mode, 616a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) BOOL* open, 617a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) DWORD* new_conversion_mode) { 618a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) *open = TRUE; 619a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) *new_conversion_mode = initial_conversion_mode; 620a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) switch (input_mode) { 621a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) case ui::TEXT_INPUT_MODE_FULL_WIDTH_LATIN: 622a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) *new_conversion_mode |= IME_CMODE_FULLSHAPE; 623a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) *new_conversion_mode &= ~(IME_CMODE_NATIVE 624a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) | IME_CMODE_KATAKANA); 625a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) break; 626a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) case ui::TEXT_INPUT_MODE_KANA: 627a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) *new_conversion_mode |= (IME_CMODE_NATIVE 628a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) | IME_CMODE_FULLSHAPE); 629a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) *new_conversion_mode &= ~IME_CMODE_KATAKANA; 630a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) break; 631a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) case ui::TEXT_INPUT_MODE_KATAKANA: 632a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) *new_conversion_mode |= (IME_CMODE_NATIVE 633a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) | IME_CMODE_KATAKANA 634a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) | IME_CMODE_FULLSHAPE); 635a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) break; 636a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) default: 637a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) *open = FALSE; 638a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) break; 639a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 640a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 641a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace ui 643