Mercurial > sdl-ios-xcode
comparison src/video/win32/SDL_win32keyboard.c @ 4752:dc7bdcf06367
Initial IMM implementation.
IME input should now work fairly well.
author | dewyatt |
---|---|
date | Mon, 12 Jul 2010 11:33:27 -0400 |
parents | f3908cd80b10 |
children | 11b0a6a3eb4d |
comparison
equal
deleted
inserted
replaced
4751:f3908cd80b10 | 4752:dc7bdcf06367 |
---|---|
23 | 23 |
24 #include "SDL_win32video.h" | 24 #include "SDL_win32video.h" |
25 | 25 |
26 #include "../../events/SDL_keyboard_c.h" | 26 #include "../../events/SDL_keyboard_c.h" |
27 #include "../../events/scancodes_win32.h" | 27 #include "../../events/scancodes_win32.h" |
28 | |
29 #include <msctf.h> | |
30 #include <imm.h> | |
28 | 31 |
29 #ifndef MAPVK_VK_TO_VSC | 32 #ifndef MAPVK_VK_TO_VSC |
30 #define MAPVK_VK_TO_VSC 0 | 33 #define MAPVK_VK_TO_VSC 0 |
31 #endif | 34 #endif |
32 #ifndef MAPVK_VSC_TO_VK | 35 #ifndef MAPVK_VSC_TO_VK |
44 | 47 |
45 BYTE keypad_scancodes[10] = { | 48 BYTE keypad_scancodes[10] = { |
46 82, 79, 80, 81, 75, 76, 77, 71, 72, 73 | 49 82, 79, 80, 81, 75, 76, 77, 71, 72, 73 |
47 }; | 50 }; |
48 | 51 |
52 void IME_Disable(SDL_VideoData *videodata, HWND hwnd); | |
53 void IME_Enable(SDL_VideoData *videodata, HWND hwnd); | |
54 void IME_Init(SDL_VideoData *videodata, HWND hwnd); | |
55 void IME_Quit(SDL_VideoData *videodata); | |
56 | |
49 void | 57 void |
50 WIN_InitKeyboard(_THIS) | 58 WIN_InitKeyboard(_THIS) |
51 { | 59 { |
52 SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; | 60 SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; |
53 int i; | 61 int i; |
78 #endif | 86 #endif |
79 } | 87 } |
80 } | 88 } |
81 | 89 |
82 data->key_layout = win32_scancode_table; | 90 data->key_layout = win32_scancode_table; |
91 | |
92 data->ime_com_initialized = SDL_FALSE; | |
93 data->ime_thread_mgr = 0; | |
94 data->ime_initialized = SDL_FALSE; | |
95 data->ime_enabled = SDL_FALSE; | |
96 data->ime_available = SDL_FALSE; | |
97 data->ime_hwnd_main = 0; | |
98 data->ime_hwnd_current = 0; | |
99 data->ime_himc = 0; | |
83 | 100 |
84 WIN_UpdateKeymap(); | 101 WIN_UpdateKeymap(); |
85 | 102 |
86 SDL_SetScancodeName(SDL_SCANCODE_APPLICATION, "Menu"); | 103 SDL_SetScancodeName(SDL_SCANCODE_APPLICATION, "Menu"); |
87 SDL_SetScancodeName(SDL_SCANCODE_LGUI, "Left Windows"); | 104 SDL_SetScancodeName(SDL_SCANCODE_LGUI, "Left Windows"); |
118 } | 135 } |
119 | 136 |
120 void | 137 void |
121 WIN_QuitKeyboard(_THIS) | 138 WIN_QuitKeyboard(_THIS) |
122 { | 139 { |
140 IME_Quit((SDL_VideoData *)_this->driverdata); | |
123 } | 141 } |
124 | 142 |
125 void | 143 void |
126 WIN_StartTextInput(_THIS, SDL_Window *window) | 144 WIN_StartTextInput(_THIS, SDL_Window *window) |
127 { | 145 { |
128 HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd; | 146 HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd; |
129 | 147 SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata; |
148 IME_Init(videodata, hwnd); | |
149 IME_Enable(videodata, hwnd); | |
130 } | 150 } |
131 | 151 |
132 void | 152 void |
133 WIN_StopTextInput(_THIS, SDL_Window *window) | 153 WIN_StopTextInput(_THIS, SDL_Window *window) |
134 { | 154 { |
135 | 155 HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd; |
156 SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata; | |
157 IME_Init(videodata, hwnd); | |
158 IME_Disable(videodata, hwnd); | |
136 } | 159 } |
137 | 160 |
138 void | 161 void |
139 WIN_SetTextInputRect(_THIS, SDL_Rect *rect) | 162 WIN_SetTextInputRect(_THIS, SDL_Rect *rect) |
140 { | 163 { |
141 | 164 |
142 } | 165 } |
143 | 166 |
167 void | |
168 IME_Disable(SDL_VideoData *videodata, HWND hwnd) | |
169 { | |
170 if (!videodata->ime_initialized || !videodata->ime_hwnd_current) | |
171 return; | |
172 | |
173 if (videodata->ime_hwnd_current == videodata->ime_hwnd_main) | |
174 ImmAssociateContext(videodata->ime_hwnd_current, NULL); | |
175 | |
176 videodata->ime_enabled = SDL_FALSE; | |
177 } | |
178 | |
179 void | |
180 IME_Enable(SDL_VideoData *videodata, HWND hwnd) | |
181 { | |
182 if (!videodata->ime_initialized || !videodata->ime_hwnd_current) | |
183 return; | |
184 | |
185 if (!videodata->ime_available) { | |
186 IME_Disable(videodata, hwnd); | |
187 return; | |
188 } | |
189 if (videodata->ime_hwnd_current == videodata->ime_hwnd_main) | |
190 ImmAssociateContext(videodata->ime_hwnd_current, videodata->ime_himc); | |
191 | |
192 videodata->ime_enabled = SDL_TRUE; | |
193 } | |
194 | |
195 void | |
196 IME_Init(SDL_VideoData *videodata, HWND hwnd) | |
197 { | |
198 if (videodata->ime_initialized) | |
199 return; | |
200 | |
201 videodata->ime_hwnd_main = hwnd; | |
202 if (SUCCEEDED(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED))) { | |
203 videodata->ime_com_initialized = SDL_TRUE; | |
204 CoCreateInstance(&CLSID_TF_ThreadMgr, NULL, CLSCTX_INPROC_SERVER, &IID_ITfThreadMgr, &videodata->ime_thread_mgr); | |
205 } | |
206 videodata->ime_initialized = SDL_TRUE; | |
207 videodata->ime_hwnd_current = videodata->ime_hwnd_main; | |
208 if (videodata->ime_thread_mgr) { | |
209 struct ITfDocumentMgr *document_mgr = 0; | |
210 if (SUCCEEDED(videodata->ime_thread_mgr->lpVtbl->AssociateFocus(videodata->ime_thread_mgr, hwnd, NULL, &document_mgr))) { | |
211 if (document_mgr) | |
212 document_mgr->lpVtbl->Release(document_mgr); | |
213 } | |
214 } | |
215 videodata->ime_himc = ImmGetContext(hwnd); | |
216 ImmReleaseContext(hwnd, videodata->ime_himc); | |
217 if (!videodata->ime_himc) { | |
218 videodata->ime_available = SDL_FALSE; | |
219 IME_Disable(videodata, hwnd); | |
220 return; | |
221 } | |
222 videodata->ime_available = SDL_TRUE; | |
223 IME_Disable(videodata, hwnd); | |
224 } | |
225 | |
226 void | |
227 IME_Quit(SDL_VideoData *videodata) | |
228 { | |
229 if (!videodata->ime_initialized) | |
230 return; | |
231 | |
232 if (videodata->ime_hwnd_main) | |
233 ImmAssociateContext(videodata->ime_hwnd_main, videodata->ime_himc); | |
234 | |
235 videodata->ime_hwnd_main = 0; | |
236 videodata->ime_himc = 0; | |
237 if (videodata->ime_thread_mgr) | |
238 { | |
239 videodata->ime_thread_mgr->lpVtbl->Release(videodata->ime_thread_mgr); | |
240 videodata->ime_thread_mgr = 0; | |
241 } | |
242 if (videodata->ime_com_initialized) | |
243 { | |
244 CoUninitialize(); | |
245 videodata->ime_com_initialized = SDL_FALSE; | |
246 } | |
247 videodata->ime_initialized = SDL_FALSE; | |
248 } | |
249 | |
250 SDL_bool | |
251 IME_HandleMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM *lParam, SDL_VideoData *videodata) | |
252 { | |
253 SDL_bool trap = SDL_FALSE; | |
254 HIMC himc = 0; | |
255 WCHAR Buffer[SDL_TEXTINPUTEVENT_TEXT_SIZE / 2]; | |
256 if (!videodata->ime_initialized || !videodata->ime_available || !videodata->ime_enabled) | |
257 return SDL_FALSE; | |
258 | |
259 switch (msg) | |
260 { | |
261 case WM_INPUTLANGCHANGE: | |
262 break; | |
263 case WM_IME_SETCONTEXT: | |
264 *lParam = 0; | |
265 break; | |
266 case WM_IME_STARTCOMPOSITION: | |
267 trap = SDL_TRUE; | |
268 break; | |
269 case WM_IME_COMPOSITION: | |
270 trap = SDL_TRUE; | |
271 himc = ImmGetContext(hwnd); | |
272 if (*lParam & GCS_RESULTSTR) | |
273 { | |
274 LONG Length = 0; | |
275 char *s = 0; | |
276 Length = ImmGetCompositionStringW(himc, GCS_RESULTSTR, Buffer, sizeof(Buffer) * sizeof(Buffer[0])); | |
277 Buffer[Length / sizeof(Buffer[0])] = 0; | |
278 s = WIN_StringToUTF8(Buffer); | |
279 SDL_SendKeyboardText(s); | |
280 SDL_free(s); | |
281 } | |
282 if (*lParam & GCS_COMPSTR) | |
283 { | |
284 LONG Length = 0; | |
285 DWORD Cursor = 0; | |
286 char *s = 0; | |
287 Length = ImmGetCompositionStringW(himc, GCS_COMPSTR, Buffer, sizeof(Buffer) * sizeof(Buffer[0])); | |
288 Buffer[Length / sizeof(Buffer[0])] = 0; | |
289 s = WIN_StringToUTF8(Buffer); | |
290 Cursor = LOWORD(ImmGetCompositionStringW(himc, GCS_CURSORPOS, 0, 0)); | |
291 SDL_SendEditingText(s, Cursor, 0); | |
292 SDL_free(s); | |
293 } | |
294 ImmReleaseContext(hwnd, himc); | |
295 break; | |
296 case WM_IME_ENDCOMPOSITION: | |
297 SDL_SendKeyboardText(""); | |
298 break; | |
299 case WM_IME_NOTIFY: | |
300 switch (wParam) | |
301 { | |
302 case IMN_SETCONVERSIONMODE: | |
303 break; | |
304 case IMN_SETOPENSTATUS: | |
305 break; | |
306 case IMN_OPENCANDIDATE: | |
307 case IMN_CHANGECANDIDATE: | |
308 trap = SDL_TRUE; | |
309 break; | |
310 case IMN_CLOSECANDIDATE: | |
311 trap = SDL_TRUE; | |
312 break; | |
313 case IMN_PRIVATE: | |
314 break; | |
315 default: | |
316 trap = SDL_TRUE; | |
317 break; | |
318 } | |
319 break; | |
320 } | |
321 return trap; | |
322 } | |
323 | |
144 /* vi: set ts=4 sw=4 expandtab: */ | 324 /* vi: set ts=4 sw=4 expandtab: */ |