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: */