summaryrefslogtreecommitdiffstats
path: root/ui/base/ime/win/imm32_manager.h
blob: d82c460d0c236d773ed266f22ed4b3ca17bc6b85 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef UI_BASE_IME_WIN_IMM32_MANAGER_H
#define UI_BASE_IME_WIN_IMM32_MANAGER_H

#include <windows.h>

#include <string>
#include <vector>

#include "base/basictypes.h"
#include "base/i18n/rtl.h"
#include "base/strings/string16.h"
#include "ui/base/ime/text_input_mode.h"
#include "ui/base/ui_export.h"
#include "ui/gfx/rect.h"

namespace ui {

struct CompositionText;

// This header file defines a struct and a class used for encapsulating IMM32
// APIs, controls IMEs attached to a window, and enables the 'on-the-spot'
// input without deep knowledge about the APIs, i.e. knowledge about the
// language-specific and IME-specific behaviors.
// The following items enumerates the simplest steps for an (window)
// application to control its IMEs with the struct and the class defined
// this file.
// 1. Add an instance of the IMM32Manager class to its window class.
//    (The IMM32Manager class needs a window handle.)
// 2. Add messages handlers listed in the following subsections, follow the
//    instructions written in each subsection, and use the IMM32Manager class.
// 2.1. WM_IME_SETCONTEXT (0x0281)
//      Call the functions listed below:
//      - IMM32Manager::CreateImeWindow();
//      - IMM32Manager::CleanupComposition(), and;
//      - IMM32Manager::SetImeWindowStyle().
//      An application MUST prevent from calling ::DefWindowProc().
// 2.2. WM_IME_STARTCOMPOSITION (0x010D)
//      Call the functions listed below:
//      - IMM32Manager::CreateImeWindow(), and;
//      - IMM32Manager::ResetComposition().
//      An application MUST prevent from calling ::DefWindowProc().
// 2.3. WM_IME_COMPOSITION (0x010F)
//      Call the functions listed below:
//      - IMM32Manager::UpdateImeWindow();
//      - IMM32Manager::GetResult();
//      - IMM32Manager::GetComposition(), and;
//      - IMM32Manager::ResetComposition() (optional).
//      An application MUST prevent from calling ::DefWindowProc().
// 2.4. WM_IME_ENDCOMPOSITION (0x010E)
//      Call the functions listed below:
//      - IMM32Manager::ResetComposition(), and;
//      - IMM32Manager::DestroyImeWindow().
//      An application CAN call ::DefWindowProc().
// 2.5. WM_INPUTLANGCHANGE (0x0051)
//      Call the functions listed below:
//      - IMM32Manager::SetInputLanguage().
//      An application CAN call ::DefWindowProc().

// This class controls the IMM (Input Method Manager) through IMM32 APIs and
// enables it to retrieve the string being controled by the IMM. (I wrote
// a note to describe the reason why I do not use 'IME' but 'IMM' below.)
// NOTE(hbono):
//   Fortunately or unfortunately, TSF (Text Service Framework) and
//   CUAS (Cicero Unaware Application Support) allows IMM32 APIs for
//   retrieving not only the inputs from IMEs (Input Method Editors), used
//   only for inputting East-Asian language texts, but also the ones from
//   tablets (on Windows XP Tablet PC Edition and Windows Vista), voice
//   recognizers (e.g. ViaVoice and Microsoft Office), etc.
//   We can disable TSF and CUAS in Windows XP Tablet PC Edition. On the other
//   hand, we can NEVER disable either TSF or CUAS in Windows Vista, i.e.
//   THIS CLASS IS NOT ONLY USED ON THE INPUT CONTEXTS OF EAST-ASIAN
//   LANGUAGES BUT ALSO USED ON THE INPUT CONTEXTS OF ALL LANGUAGES.
class UI_EXPORT IMM32Manager {
 public:
  IMM32Manager();
  virtual ~IMM32Manager();

  // Retrieves whether or not there is an ongoing composition.
  bool is_composing() const { return is_composing_; }

  // Retrieves the input language from Windows and update it.
  // Return values
  //   * true
  //     The given input language has IMEs.
  //   * false
  //     The given input language does not have IMEs.
  bool SetInputLanguage();

  // Creates the IME windows, and allocate required resources for them.
  // Parameters
  //   * window_handle [in] (HWND)
  //     Represents the window handle of the caller.
  void CreateImeWindow(HWND window_handle);

  // Updates the style of the IME windows.
  // Parameters
  //   * window_handle [in] (HWND)
  //     Represents the window handle of the caller.
  //   * message [in] (UINT)
  //   * wparam [in] (WPARAM)
  //   * lparam [in] (LPARAM)
  //     Represent the windows message of the caller.
  //     These parameters are used for verifying if this function is called
  //     in a handler function for WM_IME_SETCONTEXT messages because this
  //     function uses ::DefWindowProc() to update the style.
  //     A caller just has to pass the input parameters for the handler
  //     function without modifications.
  //   * handled [out] (BOOL*)
  //     Returns ::DefWindowProc() is really called in this function.
  //     PLEASE DO NOT CALL ::DefWindowProc() IF THIS VALUE IS TRUE!
  //     All the window styles set in this function are over-written when
  //     calling ::DefWindowProc() after returning this function.
  // Returns the value returned by DefWindowProc.
  LRESULT SetImeWindowStyle(HWND window_handle, UINT message,
                            WPARAM wparam, LPARAM lparam, BOOL* handled);

  // Destroys the IME windows and all the resources attached to them.
  // Parameters
  //   * window_handle [in] (HWND)
  //     Represents the window handle of the caller.
  void DestroyImeWindow(HWND window_handle);

  // Updates the position of the IME windows.
  // Parameters
  //   * window_handle [in] (HWND)
  //     Represents the window handle of the caller.
  void UpdateImeWindow(HWND window_handle);

  // Cleans up the all resources attached to the given IMM32Manager object, and
  // reset its composition status.
  // Parameters
  //   * window_handle [in] (HWND)
  //     Represents the window handle of the caller.
  void CleanupComposition(HWND window_handle);

  // Resets the composition status.
  // Cancel the ongoing composition if it exists.
  // NOTE(hbono): This method does not release the allocated resources.
  // Parameters
  //   * window_handle [in] (HWND)
  //     Represents the window handle of the caller.
  void ResetComposition(HWND window_handle);

  // Retrieves a composition result of the ongoing composition if it exists.
  // Parameters
  //   * window_handle [in] (HWND)
  //     Represents the window handle of the caller.
  //   * lparam [in] (LPARAM)
  //     Specifies the updated members of the ongoing composition, and must be
  //     the same parameter of a WM_IME_COMPOSITION message handler.
  //     This parameter is used for checking if the ongoing composition has
  //     its result string,
  //   * result [out] (base::string16)
  //     Represents the object contains the composition result.
  // Return values
  //   * true
  //     The ongoing composition has a composition result.
  //   * false
  //     The ongoing composition does not have composition results.
  // Remarks
  //   This function is designed for being called from WM_IME_COMPOSITION
  //   message handlers.
  bool GetResult(HWND window_handle, LPARAM lparam, base::string16* result);

  // Retrieves the current composition status of the ongoing composition.
  // Parameters
  //   * window_handle [in] (HWND)
  //     Represents the window handle of the caller.
  //   * lparam [in] (LPARAM)
  //     Specifies the updated members of the ongoing composition, and must be
  //     the same parameter of a WM_IME_COMPOSITION message handler.
  //     This parameter is used for checking if the ongoing composition has
  //     its result string,
  //   * composition [out] (Composition)
  //     Represents the struct contains the composition status.
  // Return values
  //   * true
  //     The status of the ongoing composition is updated.
  //   * false
  //     The status of the ongoing composition is not updated.
  // Remarks
  //   This function is designed for being called from WM_IME_COMPOSITION
  //   message handlers.
  bool GetComposition(HWND window_handle, LPARAM lparam,
                      CompositionText* composition);

  // Enables the IME attached to the given window, i.e. allows user-input
  // events to be dispatched to the IME.
  // Parameters
  //   * window_handle [in] (HWND)
  //     Represents the window handle of the caller.
  //   * complete [in] (bool)
  //     Represents whether or not to complete the ongoing composition.
  //     + true
  //       After finishing the ongoing composition and close its IME windows,
  //       start another composition and display its IME windows to the given
  //       position.
  //     + false
  //       Just move the IME windows of the ongoing composition to the given
  //       position without finishing it.
  void EnableIME(HWND window_handle);

  // Disables the IME attached to the given window, i.e. prohibits any
  // user-input events from being dispatched to the IME.
  // In Chrome, this function is used when:
  //   * a renreder process sets its input focus to a password input.
  // Parameters
  //   * window_handle [in] (HWND)
  //     Represents the window handle of the caller.
  void DisableIME(HWND window_handle);

  // Cancels an ongoing composition of the IME attached to the given window.
  // Parameters
  //   * window_handle [in] (HWND)
  //     Represents the window handle of the caller.
  void CancelIME(HWND window_handle);

  // Updates the caret position of the given window.
  // Parameters
  //   * window_handle [in] (HWND)
  //     Represents the window handle of the caller.
  //   * caret_rect [in] (const gfx::Rect&)
  //     Represent the rectangle of the input caret.
  //     This rectangle is used for controlling the positions of IME windows.
  void UpdateCaretRect(HWND window_handle, const gfx::Rect& caret_rect);

  // Updates the setting whether we want IME to render composition text.
  void SetUseCompositionWindow(bool use_composition_window);

  // Returns the current input language id.
  LANGID input_language_id() const { return input_language_id_; }

  // Returns BCP-47 tag name of the current input language.
  std::string GetInputLanguageName() const;

  // Returns the text direction of the current input language.
  base::i18n::TextDirection GetTextDirection() const;

  // Sets conversion status corresponding to |input_mode|.
  virtual void SetTextInputMode(HWND window_handle, TextInputMode input_mode);

  // Helper functions ----------------------------------------------------------

  // Checks if there is any RTL keyboard layout installed in the system.
  static bool IsRTLKeyboardLayoutInstalled();

  // Checks if the user pressed both Ctrl and right or left Shift keys to
  // requrest to change the text direction and layout alignment explicitly.
  // Returns true if only a Ctrl key and a Shift key are down. The desired text
  // direction will be stored in |*direction|.
  static bool IsCtrlShiftPressed(base::i18n::TextDirection* direction);

  // Gets parameters for ::ImmSetOpenStatus and ::ImmSetConversionStatus from
  // |input_mode|.
  static void ConvertInputModeToImmFlags(TextInputMode input_mode,
                                         DWORD initial_conversion_mode,
                                         BOOL* open,
                                         DWORD* new_conversion_mode);


 protected:
  // Retrieves the composition information.
  void GetCompositionInfo(HIMC imm_context, LPARAM lparam,
                          CompositionText* composition);

  // Updates the position of the IME windows.
  void MoveImeWindow(HWND window_handle, HIMC imm_context);

  // Completes the ongoing composition if it exists.
  void CompleteComposition(HWND window_handle, HIMC imm_context);

  // Retrieves a string from the IMM.
  bool GetString(HIMC imm_context,
                 WPARAM lparam,
                 int type,
                 base::string16* result);

 private:
  // Represents whether or not there is an ongoing composition in a browser
  // process, i.e. whether or not a browser process is composing a text.
  bool is_composing_;

  // This value represents whether or not the current input context has IMEs.
  // The following table shows the list of IME status:
  //   Value  Description
  //   false  The current input language does not have IMEs.
  //   true   The current input language has IMEs.
  bool ime_status_;

  // The current input Language ID retrieved from Windows, which consists of:
  //   * Primary Language ID (bit 0 to bit 9), which shows a natunal language
  //     (English, Korean, Chinese, Japanese, etc.) and;
  //   * Sub-Language ID (bit 10 to bit 15), which shows a geometrical region
  //     the language is spoken (For English, United States, United Kingdom,
  //     Australia, Canada, etc.)
  // The following list enumerates some examples for the Language ID:
  //   * "en-US" (0x0409)
  //     MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
  //   * "ko-KR" (0x0412)
  //     MAKELANGID(LANG_KOREAN,  SUBLANG_KOREAN);
  //   * "zh-TW" (0x0404)
  //     MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL);
  //   * "zh-CN" (0x0804)
  //     MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED);
  //   * "ja-JP" (0x0411)
  //     MAKELANGID(LANG_JAPANESE, SUBLANG_JAPANESE_JAPAN), etc.
  //   (See <winnt.h> for other available values.)
  // This Language ID is used for processing language-specific operations in
  // IME functions.
  LANGID input_language_id_;

  // Represents whether or not the current input context has created a system
  // caret to set the position of its IME candidate window.
  //   * true: it creates a system caret.
  //   * false: it does not create a system caret.
  bool system_caret_;

  // The rectangle of the input caret retrieved from a renderer process.
  gfx::Rect caret_rect_;

  // Indicates whether or not we want IME to render composition text.
  bool use_composition_window_;

  DISALLOW_COPY_AND_ASSIGN(IMM32Manager);
};

}  // namespace ui

#endif  // UI_BASE_IME_WIN_IMM32_MANAGER_H