ClangFormat: apply to source, most of intern
[blender.git] / intern / ghost / intern / GHOST_ImeWin32.h
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (c) 2010 The Chromium Authors. All rights reserved.
17  * All rights reserved.
18  *
19  * The Original Code is: some of this file.
20 */
21
22 /** \file
23  * \ingroup GHOST
24  */
25
26 #ifndef __GHOST_IME_H__
27 #define __GHOST_IME_H__
28
29 #ifdef WITH_INPUT_IME
30
31 #  define WIN32_LEAN_AND_MEAN
32 #  include <windows.h>
33
34 #  include <string>
35
36 #  include "GHOST_Event.h"
37 #  include "GHOST_Rect.h"
38 #  include <vector>
39
40 class GHOST_EventIME : public GHOST_Event {
41  public:
42   /**
43    * Constructor.
44    * \param msec  The time this event was generated.
45    * \param type  The type of key event.
46    * \param key   The key code of the key.
47    */
48   GHOST_EventIME(GHOST_TUns64 msec, GHOST_TEventType type, GHOST_IWindow *window, void *customdata)
49       : GHOST_Event(msec, type, window)
50   {
51     this->m_data = customdata;
52   }
53 };
54
55 /**
56  * This header file defines a struct and a class used for encapsulating IMM32
57  * APIs, controls IMEs attached to a window, and enables the 'on-the-spot'
58  * input without deep knowledge about the APIs, i.e. knowledge about the
59  * language-specific and IME-specific behaviors.
60  * The following items enumerates the simplest steps for an (window)
61  * application to control its IMEs with the struct and the class defined
62  * this file.
63  * 1. Add an instance of the GHOST_ImeWin32 class to its window class.
64  *    (The GHOST_ImeWin32 class needs a window handle.)
65  * 2. Add messages handlers listed in the following subsections, follow the
66  *    instructions written in each subsection, and use the GHOST_ImeWin32 class.
67  * 2.1. WM_IME_SETCONTEXT (0x0281)
68  *      Call the functions listed below:
69  *      - GHOST_ImeWin32::CreateImeWindow();
70  *      - GHOST_ImeWin32::CleanupComposition(), and;
71  *      - GHOST_ImeWin32::SetImeWindowStyle().
72  *      An application MUST prevent from calling ::DefWindowProc().
73  * 2.2. WM_IME_STARTCOMPOSITION (0x010D)
74  *      Call the functions listed below:
75  *      - GHOST_ImeWin32::CreateImeWindow(), and;
76  *      - GHOST_ImeWin32::ResetComposition().
77  *      An application MUST prevent from calling ::DefWindowProc().
78  * 2.3. WM_IME_COMPOSITION (0x010F)
79  *      Call the functions listed below:
80  *      - GHOST_ImeWin32::UpdateImeWindow();
81  *      - GHOST_ImeWin32::GetResult();
82  *      - GHOST_ImeWin32::GetComposition(), and;
83  *      - GHOST_ImeWin32::ResetComposition() (optional).
84  *      An application MUST prevent from calling ::DefWindowProc().
85  * 2.4. WM_IME_ENDCOMPOSITION (0x010E)
86  *      Call the functions listed below:
87  *      - GHOST_ImeWin32::ResetComposition(), and;
88  *      - GHOST_ImeWin32::DestroyImeWindow().
89  *      An application CAN call ::DefWindowProc().
90  * 2.5. WM_INPUTLANGCHANGE (0x0051)
91  *      Call the functions listed below:
92  *      - GHOST_ImeWin32::SetInputLanguage().
93  *      An application CAN call ::DefWindowProc().
94  */
95
96 /* This struct represents the status of an ongoing composition. */
97 struct ImeComposition {
98   /* Represents the cursor position in the IME composition. */
99   int cursor_position;
100
101   /* Represents the position of the beginning of the selection */
102   int target_start;
103
104   /* Represents the position of the end of the selection */
105   int target_end;
106
107   /**
108    * Represents the type of the string in the 'ime_string' parameter.
109    * Its possible values and description are listed below:
110    *   Value         Description
111    *   0             The parameter is not used.
112    *   GCS_RESULTSTR The parameter represents a result string.
113    *   GCS_COMPSTR   The parameter represents a composition string.
114    */
115   int string_type;
116
117   /* Represents the string retrieved from IME (Input Method Editor) */
118   std::wstring ime_string;
119   std::vector<char> utf8_buf;
120   std::vector<unsigned char> format;
121 };
122
123 /**
124  * This class controls the IMM (Input Method Manager) through IMM32 APIs and
125  * enables it to retrieve the string being controled by the IMM. (I wrote
126  * a note to describe the reason why I do not use 'IME' but 'IMM' below.)
127  * NOTE(hbono):
128  *   Fortunately or unfortunately, TSF (Text Service Framework) and
129  *   CUAS (Cicero Unaware Application Support) allows IMM32 APIs for
130  *   retrieving not only the inputs from IMEs (Input Method Editors), used
131  *   only for inputting East-Asian language texts, but also the ones from
132  *   tablets (on Windows XP Tablet PC Edition and Windows Vista), voice
133  *   recognizers (e.g. ViaVoice and Microsoft Office), etc.
134  *   We can disable TSF and CUAS in Windows XP Tablet PC Edition. On the other
135  *   hand, we can NEVER disable either TSF or CUAS in Windows Vista, i.e.
136  *   THIS CLASS IS NOT ONLY USED ON THE INPUT CONTEXTS OF EAST-ASIAN
137  *   LANGUAGES BUT ALSO USED ON THE INPUT CONTEXTS OF ALL LANGUAGES.
138  */
139 class GHOST_ImeWin32 {
140  public:
141   GHOST_ImeWin32();
142   ~GHOST_ImeWin32();
143
144   /* Retrieves whether or not there is an ongoing composition. */
145   bool is_composing() const
146   {
147     return is_composing_;
148   }
149
150   /**
151    * Retrieves the input language from Windows and update it.
152    * Return values
153    *   * true
154    *     The given input language has IMEs.
155    *   * false
156    *     The given input language does not have IMEs.
157    */
158   bool SetInputLanguage();
159
160   /**
161    * Create the IME windows, and allocate required resources for them.
162    * Parameters
163    *   * window_handle [in] (HWND)
164    *     Represents the window handle of the caller.
165    */
166   void CreateImeWindow(HWND window_handle);
167
168   /**
169    * Update the style of the IME windows.
170    * Parameters
171    *   * window_handle [in] (HWND)
172    *     Represents the window handle of the caller.
173    *   * message [in] (UINT)
174    *   * wparam [in] (WPARAM)
175    *   * lparam [in] (LPARAM)
176    *     Represent the windows message of the caller.
177    *     These parameters are used for verifying if this function is called
178    *     in a handler function for WM_IME_SETCONTEXT messages because this
179    *     function uses ::DefWindowProc() to update the style.
180    *     A caller just has to pass the input parameters for the handler
181    *     function without modifications.
182    *   * handled [out] (BOOL*)
183    *     Returns ::DefWindowProc() is really called in this function.
184    *     PLEASE DO NOT CALL ::DefWindowProc() IF THIS VALUE IS TRUE!
185    *     All the window styles set in this function are over-written when
186    *     calling ::DefWindowProc() after returning this function.
187    */
188   void SetImeWindowStyle(
189       HWND window_handle, UINT message, WPARAM wparam, LPARAM lparam, BOOL *handled);
190
191   /**
192    * Destroy the IME windows and all the resources attached to them.
193    * Parameters
194    *   * window_handle [in] (HWND)
195    *     Represents the window handle of the caller.
196    */
197   void DestroyImeWindow(HWND window_handle);
198
199   /**
200    * Update the position of the IME windows.
201    * Parameters
202    *   * window_handle [in] (HWND)
203    *     Represents the window handle of the caller.
204    */
205   void UpdateImeWindow(HWND window_handle);
206
207   /**
208    * Clean up the all resources attached to the given GHOST_ImeWin32 object, and
209    * reset its composition status.
210    * Parameters
211    *   * window_handle [in] (HWND)
212    *     Represents the window handle of the caller.
213    */
214   void CleanupComposition(HWND window_handle);
215
216   /**
217    * Reset the composition status.
218    * Cancel the ongoing composition if it exists.
219    * NOTE(hbono): This method does not release the allocated resources.
220    * Parameters
221    *   * window_handle [in] (HWND)
222    *     Represents the window handle of the caller.
223    */
224   void ResetComposition(HWND window_handle);
225
226   /**
227    * Retrieve a composition result of the ongoing composition if it exists.
228    * Parameters
229    *   * window_handle [in] (HWND)
230    *     Represents the window handle of the caller.
231    *   * lparam [in] (LPARAM)
232    *     Specifies the updated members of the ongoing composition, and must be
233    *     the same parameter of a WM_IME_COMPOSITION message handler.
234    *     This parameter is used for checking if the ongoing composition has
235    *     its result string,
236    *   * composition [out] (ImeComposition)
237    *     Represents the struct contains the composition result.
238    * Return values
239    *   * true
240    *     The ongoing composition has a composition result.
241    *   * false
242    *     The ongoing composition does not have composition results.
243    * Remarks
244    *   This function is designed for being called from WM_IME_COMPOSITION
245    *   message handlers.
246    */
247   bool GetResult(HWND window_handle, LPARAM lparam, ImeComposition *composition);
248
249   /**
250    * Retrieve the current composition status of the ongoing composition.
251    * Parameters
252    *   * window_handle [in] (HWND)
253    *     Represents the window handle of the caller.
254    *   * lparam [in] (LPARAM)
255    *     Specifies the updated members of the ongoing composition, and must be
256    *     the same parameter of a WM_IME_COMPOSITION message handler.
257    *     This parameter is used for checking if the ongoing composition has
258    *     its result string,
259    *   * composition [out] (ImeComposition)
260    *     Represents the struct contains the composition status.
261    * Return values
262    *   * true
263    *     The status of the ongoing composition is updated.
264    *   * false
265    *     The status of the ongoing composition is not updated.
266    * Remarks
267    *   This function is designed for being called from WM_IME_COMPOSITION
268    *   message handlers.
269    */
270   bool GetComposition(HWND window_handle, LPARAM lparam, ImeComposition *composition);
271
272   /**
273    * Enable the IME attached to the given window, i.e. allows user-input
274    * events to be dispatched to the IME.
275    * In Chrome, this function is used when:
276    *   * a renderer process moves its input focus to another edit control, or;
277    *   * a renrerer process moves the position of the focused edit control.
278    * Parameters
279    *   * window_handle [in] (HWND)
280    *     Represents the window handle of the caller.
281    *   * caret_rect [in] (const gfx::Rect&)
282    *     Represent the rectangle of the input caret.
283    *     This rectangle is used for controlling the positions of IME windows.
284    *   * complete [in] (bool)
285    *     Represents whether or not to complete the ongoing composition.
286    *     + true
287    *       After finishing the ongoing composition and close its IME windows,
288    *       start another composition and display its IME windows to the given
289    *       position.
290    *     + false
291    *       Just move the IME windows of the ongoing composition to the given
292    *       position without finishing it.
293    */
294   void BeginIME(HWND window_handle, const GHOST_Rect &caret_rect, bool complete);
295
296   /**
297    * Disable the IME attached to the given window, i.e. prohibits any user-input
298    * events from being dispatched to the IME.
299    * In Chrome, this function is used when:
300    *   * a renreder process sets its input focus to a password input.
301    * Parameters
302    *   * window_handle [in] (HWND)
303    *     Represents the window handle of the caller.
304    */
305   void EndIME(HWND window_handle);
306
307   /* Updatg resultInfo and compInfo */
308   void UpdateInfo(HWND window_handle);
309
310   /* disable ime when start up */
311   void CheckFirst(HWND window_handle);
312
313   ImeComposition resultInfo, compInfo;
314   GHOST_TEventImeData eventImeData;
315
316  protected:
317   /* Determines whether or not the given attribute represents a target (a.k.a. a selection). */
318   bool IsTargetAttribute(char attribute) const
319   {
320     return (attribute == ATTR_TARGET_CONVERTED || attribute == ATTR_TARGET_NOTCONVERTED);
321   }
322
323   /* Retrieve the target area. */
324   void GetCaret(HIMC imm_context, LPARAM lparam, ImeComposition *composition);
325
326   /* Update the position of the IME windows. */
327   void MoveImeWindow(HWND window_handle, HIMC imm_context);
328
329   /* Complete the ongoing composition if it exists. */
330   void CompleteComposition(HWND window_handle, HIMC imm_context);
331
332   /* Retrieve a string from the IMM. */
333   bool GetString(HIMC imm_context, WPARAM lparam, int type, ImeComposition *composition);
334
335  private:
336   /**
337    * Represents whether or not there is an ongoing composition in a browser
338    * process, i.e. whether or not a browser process is composing a text.
339    */
340   bool is_composing_;
341
342   /**
343    * This value represents whether or not the current input context has IMEs.
344    * The following table shows the list of IME status:
345    *   Value  Description
346    *   false  The current input language does not have IMEs.
347    *   true   The current input language has IMEs.
348    */
349   bool ime_status_;
350
351   /**
352    * The current input Language ID retrieved from Windows, which consists of:
353    *   * Primary Language ID (bit 0 to bit 9), which shows a natunal language
354    *     (English, Korean, Chinese, Japanese, etc.) and;
355    *   * Sub-Language ID (bit 10 to bit 15), which shows a geometrical region
356    *     the language is spoken (For English, United States, United Kingdom,
357    *     Australia, Canada, etc.)
358    * The following list enumerates some examples for the Language ID:
359    *   * "en-US" (0x0409)
360    *     MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
361    *   * "ko-KR" (0x0412)
362    *     MAKELANGID(LANG_KOREAN,  SUBLANG_KOREAN);
363    *   * "zh-TW" (0x0404)
364    *     MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL);
365    *   * "zh-CN" (0x0804)
366    *     MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED);
367    *   * "ja-JP" (0x0411)
368    *     MAKELANGID(LANG_JAPANESE, SUBLANG_JAPANESE_JAPAN), etc.
369    *   (See <winnt.h> for other available values.)
370    * This Language ID is used for processing language-specific operations in
371    * IME functions.
372    */
373   LANGID input_language_id_;
374
375   /**
376    * Represents whether or not the current input context has created a system
377    * caret to set the position of its IME candidate window.
378    *   * true: it creates a system caret.
379    *   * false: it does not create a system caret.
380    */
381   bool system_caret_;
382
383   /* The rectangle of the input caret retrieved from a renderer process. */
384   GHOST_Rect caret_rect_;
385
386   /* used for disable ime when start up */
387   bool is_first, is_enable;
388 };
389
390 #endif  // WITH_INPUT_IME
391 #endif  // __GHOST_IME_H__