summaryrefslogtreecommitdiffstats
path: root/chrome/browser/ime_input.h
blob: 184343b826767ba11871575ad2f29013f8ca809d (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
// Copyright (c) 2010 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 CHROME_BROWSER_IME_INPUT_H_
#define CHROME_BROWSER_IME_INPUT_H_

#include <windows.h>

#include <string>
#include <vector>

#include "base/basictypes.h"
#include "gfx/rect.h"
#include "third_party/WebKit/WebKit/chromium/public/WebCompositionUnderline.h"

// 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 ImeInput class to its window class.
//    (The ImeInput class needs a window handle.)
// 2. Add messages handlers listed in the following subsections, follow the
//    instructions written in each subsection, and use the ImeInput class.
// 2.1. WM_IME_SETCONTEXT (0x0281)
//      Call the functions listed below:
//      - ImeInput::CreateImeWindow();
//      - ImeInput::CleanupComposition(), and;
//      - ImeInput::SetImeWindowStyle().
//      An application MUST prevent from calling ::DefWindowProc().
// 2.2. WM_IME_STARTCOMPOSITION (0x010D)
//      Call the functions listed below:
//      - ImeInput::CreateImeWindow(), and;
//      - ImeInput::ResetComposition().
//      An application MUST prevent from calling ::DefWindowProc().
// 2.3. WM_IME_COMPOSITION (0x010F)
//      Call the functions listed below:
//      - ImeInput::UpdateImeWindow();
//      - ImeInput::GetResult();
//      - ImeInput::GetComposition(), and;
//      - ImeInput::ResetComposition() (optional).
//      An application MUST prevent from calling ::DefWindowProc().
// 2.4. WM_IME_ENDCOMPOSITION (0x010E)
//      Call the functions listed below:
//      - ImeInput::ResetComposition(), and;
//      - ImeInput::DestroyImeWindow().
//      An application CAN call ::DefWindowProc().
// 2.5. WM_INPUTLANGCHANGE (0x0051)
//      Call the functions listed below:
//      - ImeInput::SetInputLanguage().
//      An application CAN call ::DefWindowProc().

// This struct represents the status of an ongoing composition.
struct ImeComposition {
  // Represents the start position of the selection range in the IME
  // composition.
  int selection_start;

  // Represents the end position of the selection range in the IME composition.
  // If |selection_start| and |selection_end| are equal, then it represents the
  // cursor position.
  int selection_end;

  // Represents the type of the string in the 'ime_string' parameter.
  // Its possible values and description are listed bwlow:
  //   Value         Description
  //   0             The parameter is not used.
  //   GCS_RESULTSTR The parameter represents a result string.
  //   GCS_COMPSTR   The parameter represents a composition string.
  int string_type;

  // Represents the string retrieved from IME (Input Method Editor)
  std::wstring ime_string;

  // Contains the underline information of the composition string.
  std::vector<WebKit::WebCompositionUnderline> underlines;
};

// 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 ImeInput {
 public:
  ImeInput();
  ~ImeInput();

  // 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.
  void 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 ImeInput 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,
  //   * composition [out] (ImeComposition)
  //     Represents the struct 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,
                 ImeComposition* composition);

  // 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] (ImeComposition)
  //     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,
                      ImeComposition* 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);

 protected:
  // Retrieves the composition information.
  void GetCompositionInfo(HIMC imm_context, LPARAM lparam,
                          ImeComposition* 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,
                 ImeComposition* composition);

 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_;

  DISALLOW_COPY_AND_ASSIGN(ImeInput);
};

#endif  // CHROME_BROWSER_IME_INPUT_H_