1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef UI_BASE_IME_WIN_IMM32_MANAGER_H 6 #define UI_BASE_IME_WIN_IMM32_MANAGER_H 7 8 #include <windows.h> 9 10 #include <string> 11 #include <vector> 12 13 #include "base/basictypes.h" 14 #include "base/i18n/rtl.h" 15 #include "base/strings/string16.h" 16 #include "ui/base/ime/text_input_mode.h" 17 #include "ui/base/ui_export.h" 18 #include "ui/gfx/rect.h" 19 20 namespace ui { 21 22 struct CompositionText; 23 24 // This header file defines a struct and a class used for encapsulating IMM32 25 // APIs, controls IMEs attached to a window, and enables the 'on-the-spot' 26 // input without deep knowledge about the APIs, i.e. knowledge about the 27 // language-specific and IME-specific behaviors. 28 // The following items enumerates the simplest steps for an (window) 29 // application to control its IMEs with the struct and the class defined 30 // this file. 31 // 1. Add an instance of the IMM32Manager class to its window class. 32 // (The IMM32Manager class needs a window handle.) 33 // 2. Add messages handlers listed in the following subsections, follow the 34 // instructions written in each subsection, and use the IMM32Manager class. 35 // 2.1. WM_IME_SETCONTEXT (0x0281) 36 // Call the functions listed below: 37 // - IMM32Manager::CreateImeWindow(); 38 // - IMM32Manager::CleanupComposition(), and; 39 // - IMM32Manager::SetImeWindowStyle(). 40 // An application MUST prevent from calling ::DefWindowProc(). 41 // 2.2. WM_IME_STARTCOMPOSITION (0x010D) 42 // Call the functions listed below: 43 // - IMM32Manager::CreateImeWindow(), and; 44 // - IMM32Manager::ResetComposition(). 45 // An application MUST prevent from calling ::DefWindowProc(). 46 // 2.3. WM_IME_COMPOSITION (0x010F) 47 // Call the functions listed below: 48 // - IMM32Manager::UpdateImeWindow(); 49 // - IMM32Manager::GetResult(); 50 // - IMM32Manager::GetComposition(), and; 51 // - IMM32Manager::ResetComposition() (optional). 52 // An application MUST prevent from calling ::DefWindowProc(). 53 // 2.4. WM_IME_ENDCOMPOSITION (0x010E) 54 // Call the functions listed below: 55 // - IMM32Manager::ResetComposition(), and; 56 // - IMM32Manager::DestroyImeWindow(). 57 // An application CAN call ::DefWindowProc(). 58 // 2.5. WM_INPUTLANGCHANGE (0x0051) 59 // Call the functions listed below: 60 // - IMM32Manager::SetInputLanguage(). 61 // An application CAN call ::DefWindowProc(). 62 63 // This class controls the IMM (Input Method Manager) through IMM32 APIs and 64 // enables it to retrieve the string being controled by the IMM. (I wrote 65 // a note to describe the reason why I do not use 'IME' but 'IMM' below.) 66 // NOTE(hbono): 67 // Fortunately or unfortunately, TSF (Text Service Framework) and 68 // CUAS (Cicero Unaware Application Support) allows IMM32 APIs for 69 // retrieving not only the inputs from IMEs (Input Method Editors), used 70 // only for inputting East-Asian language texts, but also the ones from 71 // tablets (on Windows XP Tablet PC Edition and Windows Vista), voice 72 // recognizers (e.g. ViaVoice and Microsoft Office), etc. 73 // We can disable TSF and CUAS in Windows XP Tablet PC Edition. On the other 74 // hand, we can NEVER disable either TSF or CUAS in Windows Vista, i.e. 75 // THIS CLASS IS NOT ONLY USED ON THE INPUT CONTEXTS OF EAST-ASIAN 76 // LANGUAGES BUT ALSO USED ON THE INPUT CONTEXTS OF ALL LANGUAGES. 77 class UI_EXPORT IMM32Manager { 78 public: 79 IMM32Manager(); 80 virtual ~IMM32Manager(); 81 82 // Retrieves whether or not there is an ongoing composition. 83 bool is_composing() const { return is_composing_; } 84 85 // Retrieves the input language from Windows and update it. 86 // Return values 87 // * true 88 // The given input language has IMEs. 89 // * false 90 // The given input language does not have IMEs. 91 bool SetInputLanguage(); 92 93 // Creates the IME windows, and allocate required resources for them. 94 // Parameters 95 // * window_handle [in] (HWND) 96 // Represents the window handle of the caller. 97 void CreateImeWindow(HWND window_handle); 98 99 // Updates the style of the IME windows. 100 // Parameters 101 // * window_handle [in] (HWND) 102 // Represents the window handle of the caller. 103 // * message [in] (UINT) 104 // * wparam [in] (WPARAM) 105 // * lparam [in] (LPARAM) 106 // Represent the windows message of the caller. 107 // These parameters are used for verifying if this function is called 108 // in a handler function for WM_IME_SETCONTEXT messages because this 109 // function uses ::DefWindowProc() to update the style. 110 // A caller just has to pass the input parameters for the handler 111 // function without modifications. 112 // * handled [out] (BOOL*) 113 // Returns ::DefWindowProc() is really called in this function. 114 // PLEASE DO NOT CALL ::DefWindowProc() IF THIS VALUE IS TRUE! 115 // All the window styles set in this function are over-written when 116 // calling ::DefWindowProc() after returning this function. 117 // Returns the value returned by DefWindowProc. 118 LRESULT SetImeWindowStyle(HWND window_handle, UINT message, 119 WPARAM wparam, LPARAM lparam, BOOL* handled); 120 121 // Destroys the IME windows and all the resources attached to them. 122 // Parameters 123 // * window_handle [in] (HWND) 124 // Represents the window handle of the caller. 125 void DestroyImeWindow(HWND window_handle); 126 127 // Updates the position of the IME windows. 128 // Parameters 129 // * window_handle [in] (HWND) 130 // Represents the window handle of the caller. 131 void UpdateImeWindow(HWND window_handle); 132 133 // Cleans up the all resources attached to the given IMM32Manager object, and 134 // reset its composition status. 135 // Parameters 136 // * window_handle [in] (HWND) 137 // Represents the window handle of the caller. 138 void CleanupComposition(HWND window_handle); 139 140 // Resets the composition status. 141 // Cancel the ongoing composition if it exists. 142 // NOTE(hbono): This method does not release the allocated resources. 143 // Parameters 144 // * window_handle [in] (HWND) 145 // Represents the window handle of the caller. 146 void ResetComposition(HWND window_handle); 147 148 // Retrieves a composition result of the ongoing composition if it exists. 149 // Parameters 150 // * window_handle [in] (HWND) 151 // Represents the window handle of the caller. 152 // * lparam [in] (LPARAM) 153 // Specifies the updated members of the ongoing composition, and must be 154 // the same parameter of a WM_IME_COMPOSITION message handler. 155 // This parameter is used for checking if the ongoing composition has 156 // its result string, 157 // * result [out] (string16) 158 // Represents the object contains the composition result. 159 // Return values 160 // * true 161 // The ongoing composition has a composition result. 162 // * false 163 // The ongoing composition does not have composition results. 164 // Remarks 165 // This function is designed for being called from WM_IME_COMPOSITION 166 // message handlers. 167 bool GetResult(HWND window_handle, LPARAM lparam, string16* result); 168 169 // Retrieves the current composition status of the ongoing composition. 170 // Parameters 171 // * window_handle [in] (HWND) 172 // Represents the window handle of the caller. 173 // * lparam [in] (LPARAM) 174 // Specifies the updated members of the ongoing composition, and must be 175 // the same parameter of a WM_IME_COMPOSITION message handler. 176 // This parameter is used for checking if the ongoing composition has 177 // its result string, 178 // * composition [out] (Composition) 179 // Represents the struct contains the composition status. 180 // Return values 181 // * true 182 // The status of the ongoing composition is updated. 183 // * false 184 // The status of the ongoing composition is not updated. 185 // Remarks 186 // This function is designed for being called from WM_IME_COMPOSITION 187 // message handlers. 188 bool GetComposition(HWND window_handle, LPARAM lparam, 189 CompositionText* composition); 190 191 // Enables the IME attached to the given window, i.e. allows user-input 192 // events to be dispatched to the IME. 193 // Parameters 194 // * window_handle [in] (HWND) 195 // Represents the window handle of the caller. 196 // * complete [in] (bool) 197 // Represents whether or not to complete the ongoing composition. 198 // + true 199 // After finishing the ongoing composition and close its IME windows, 200 // start another composition and display its IME windows to the given 201 // position. 202 // + false 203 // Just move the IME windows of the ongoing composition to the given 204 // position without finishing it. 205 void EnableIME(HWND window_handle); 206 207 // Disables the IME attached to the given window, i.e. prohibits any 208 // user-input events from being dispatched to the IME. 209 // In Chrome, this function is used when: 210 // * a renreder process sets its input focus to a password input. 211 // Parameters 212 // * window_handle [in] (HWND) 213 // Represents the window handle of the caller. 214 void DisableIME(HWND window_handle); 215 216 // Cancels an ongoing composition of the IME attached to the given window. 217 // Parameters 218 // * window_handle [in] (HWND) 219 // Represents the window handle of the caller. 220 void CancelIME(HWND window_handle); 221 222 // Updates the caret position of the given window. 223 // Parameters 224 // * window_handle [in] (HWND) 225 // Represents the window handle of the caller. 226 // * caret_rect [in] (const gfx::Rect&) 227 // Represent the rectangle of the input caret. 228 // This rectangle is used for controlling the positions of IME windows. 229 void UpdateCaretRect(HWND window_handle, const gfx::Rect& caret_rect); 230 231 // Updates the setting whether we want IME to render composition text. 232 void SetUseCompositionWindow(bool use_composition_window); 233 234 // Returns the current input language id. 235 LANGID input_language_id() const { return input_language_id_; } 236 237 // Returns BCP-47 tag name of the current input language. 238 std::string GetInputLanguageName() const; 239 240 // Returns the text direction of the current input language. 241 base::i18n::TextDirection GetTextDirection() const; 242 243 // Sets conversion status corresponding to |input_mode|. 244 virtual void SetTextInputMode(HWND window_handle, TextInputMode input_mode); 245 246 // Helper functions ---------------------------------------------------------- 247 248 // Checks if there is any RTL keyboard layout installed in the system. 249 static bool IsRTLKeyboardLayoutInstalled(); 250 251 // Checks if the user pressed both Ctrl and right or left Shift keys to 252 // requrest to change the text direction and layout alignment explicitly. 253 // Returns true if only a Ctrl key and a Shift key are down. The desired text 254 // direction will be stored in |*direction|. 255 static bool IsCtrlShiftPressed(base::i18n::TextDirection* direction); 256 257 // Gets parameters for ::ImmSetOpenStatus and ::ImmSetConversionStatus from 258 // |input_mode|. 259 static void ConvertInputModeToImmFlags(TextInputMode input_mode, 260 DWORD initial_conversion_mode, 261 BOOL* open, 262 DWORD* new_conversion_mode); 263 264 265 protected: 266 // Retrieves the composition information. 267 void GetCompositionInfo(HIMC imm_context, LPARAM lparam, 268 CompositionText* composition); 269 270 // Updates the position of the IME windows. 271 void MoveImeWindow(HWND window_handle, HIMC imm_context); 272 273 // Completes the ongoing composition if it exists. 274 void CompleteComposition(HWND window_handle, HIMC imm_context); 275 276 // Retrieves a string from the IMM. 277 bool GetString(HIMC imm_context, WPARAM lparam, int type, string16* result); 278 279 private: 280 // Represents whether or not there is an ongoing composition in a browser 281 // process, i.e. whether or not a browser process is composing a text. 282 bool is_composing_; 283 284 // This value represents whether or not the current input context has IMEs. 285 // The following table shows the list of IME status: 286 // Value Description 287 // false The current input language does not have IMEs. 288 // true The current input language has IMEs. 289 bool ime_status_; 290 291 // The current input Language ID retrieved from Windows, which consists of: 292 // * Primary Language ID (bit 0 to bit 9), which shows a natunal language 293 // (English, Korean, Chinese, Japanese, etc.) and; 294 // * Sub-Language ID (bit 10 to bit 15), which shows a geometrical region 295 // the language is spoken (For English, United States, United Kingdom, 296 // Australia, Canada, etc.) 297 // The following list enumerates some examples for the Language ID: 298 // * "en-US" (0x0409) 299 // MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US); 300 // * "ko-KR" (0x0412) 301 // MAKELANGID(LANG_KOREAN, SUBLANG_KOREAN); 302 // * "zh-TW" (0x0404) 303 // MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL); 304 // * "zh-CN" (0x0804) 305 // MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED); 306 // * "ja-JP" (0x0411) 307 // MAKELANGID(LANG_JAPANESE, SUBLANG_JAPANESE_JAPAN), etc. 308 // (See <winnt.h> for other available values.) 309 // This Language ID is used for processing language-specific operations in 310 // IME functions. 311 LANGID input_language_id_; 312 313 // Represents whether or not the current input context has created a system 314 // caret to set the position of its IME candidate window. 315 // * true: it creates a system caret. 316 // * false: it does not create a system caret. 317 bool system_caret_; 318 319 // The rectangle of the input caret retrieved from a renderer process. 320 gfx::Rect caret_rect_; 321 322 // Indicates whether or not we want IME to render composition text. 323 bool use_composition_window_; 324 325 DISALLOW_COPY_AND_ASSIGN(IMM32Manager); 326 }; 327 328 } // namespace ui 329 330 #endif // UI_BASE_IME_WIN_IMM32_MANAGER_H 331