--- a/src/video/win32/SDL_win32keyboard.c Sat Jul 10 13:15:47 2010 -0400
+++ b/src/video/win32/SDL_win32keyboard.c Mon Jul 12 11:33:27 2010 -0400
@@ -26,6 +26,9 @@
#include "../../events/SDL_keyboard_c.h"
#include "../../events/scancodes_win32.h"
+#include <msctf.h>
+#include <imm.h>
+
#ifndef MAPVK_VK_TO_VSC
#define MAPVK_VK_TO_VSC 0
#endif
@@ -46,6 +49,11 @@
82, 79, 80, 81, 75, 76, 77, 71, 72, 73
};
+void IME_Disable(SDL_VideoData *videodata, HWND hwnd);
+void IME_Enable(SDL_VideoData *videodata, HWND hwnd);
+void IME_Init(SDL_VideoData *videodata, HWND hwnd);
+void IME_Quit(SDL_VideoData *videodata);
+
void
WIN_InitKeyboard(_THIS)
{
@@ -81,6 +89,15 @@
data->key_layout = win32_scancode_table;
+ data->ime_com_initialized = SDL_FALSE;
+ data->ime_thread_mgr = 0;
+ data->ime_initialized = SDL_FALSE;
+ data->ime_enabled = SDL_FALSE;
+ data->ime_available = SDL_FALSE;
+ data->ime_hwnd_main = 0;
+ data->ime_hwnd_current = 0;
+ data->ime_himc = 0;
+
WIN_UpdateKeymap();
SDL_SetScancodeName(SDL_SCANCODE_APPLICATION, "Menu");
@@ -120,19 +137,25 @@
void
WIN_QuitKeyboard(_THIS)
{
+ IME_Quit((SDL_VideoData *)_this->driverdata);
}
void
WIN_StartTextInput(_THIS, SDL_Window *window)
{
- HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
-
+ HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
+ SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata;
+ IME_Init(videodata, hwnd);
+ IME_Enable(videodata, hwnd);
}
void
WIN_StopTextInput(_THIS, SDL_Window *window)
{
-
+ HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
+ SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata;
+ IME_Init(videodata, hwnd);
+ IME_Disable(videodata, hwnd);
}
void
@@ -141,4 +164,161 @@
}
+void
+IME_Disable(SDL_VideoData *videodata, HWND hwnd)
+{
+ if (!videodata->ime_initialized || !videodata->ime_hwnd_current)
+ return;
+
+ if (videodata->ime_hwnd_current == videodata->ime_hwnd_main)
+ ImmAssociateContext(videodata->ime_hwnd_current, NULL);
+
+ videodata->ime_enabled = SDL_FALSE;
+}
+
+void
+IME_Enable(SDL_VideoData *videodata, HWND hwnd)
+{
+ if (!videodata->ime_initialized || !videodata->ime_hwnd_current)
+ return;
+
+ if (!videodata->ime_available) {
+ IME_Disable(videodata, hwnd);
+ return;
+ }
+ if (videodata->ime_hwnd_current == videodata->ime_hwnd_main)
+ ImmAssociateContext(videodata->ime_hwnd_current, videodata->ime_himc);
+
+ videodata->ime_enabled = SDL_TRUE;
+}
+
+void
+IME_Init(SDL_VideoData *videodata, HWND hwnd)
+{
+ if (videodata->ime_initialized)
+ return;
+
+ videodata->ime_hwnd_main = hwnd;
+ if (SUCCEEDED(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED))) {
+ videodata->ime_com_initialized = SDL_TRUE;
+ CoCreateInstance(&CLSID_TF_ThreadMgr, NULL, CLSCTX_INPROC_SERVER, &IID_ITfThreadMgr, &videodata->ime_thread_mgr);
+ }
+ videodata->ime_initialized = SDL_TRUE;
+ videodata->ime_hwnd_current = videodata->ime_hwnd_main;
+ if (videodata->ime_thread_mgr) {
+ struct ITfDocumentMgr *document_mgr = 0;
+ if (SUCCEEDED(videodata->ime_thread_mgr->lpVtbl->AssociateFocus(videodata->ime_thread_mgr, hwnd, NULL, &document_mgr))) {
+ if (document_mgr)
+ document_mgr->lpVtbl->Release(document_mgr);
+ }
+ }
+ videodata->ime_himc = ImmGetContext(hwnd);
+ ImmReleaseContext(hwnd, videodata->ime_himc);
+ if (!videodata->ime_himc) {
+ videodata->ime_available = SDL_FALSE;
+ IME_Disable(videodata, hwnd);
+ return;
+ }
+ videodata->ime_available = SDL_TRUE;
+ IME_Disable(videodata, hwnd);
+}
+
+void
+IME_Quit(SDL_VideoData *videodata)
+{
+ if (!videodata->ime_initialized)
+ return;
+
+ if (videodata->ime_hwnd_main)
+ ImmAssociateContext(videodata->ime_hwnd_main, videodata->ime_himc);
+
+ videodata->ime_hwnd_main = 0;
+ videodata->ime_himc = 0;
+ if (videodata->ime_thread_mgr)
+ {
+ videodata->ime_thread_mgr->lpVtbl->Release(videodata->ime_thread_mgr);
+ videodata->ime_thread_mgr = 0;
+ }
+ if (videodata->ime_com_initialized)
+ {
+ CoUninitialize();
+ videodata->ime_com_initialized = SDL_FALSE;
+ }
+ videodata->ime_initialized = SDL_FALSE;
+}
+
+SDL_bool
+IME_HandleMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM *lParam, SDL_VideoData *videodata)
+{
+ SDL_bool trap = SDL_FALSE;
+ HIMC himc = 0;
+ WCHAR Buffer[SDL_TEXTINPUTEVENT_TEXT_SIZE / 2];
+ if (!videodata->ime_initialized || !videodata->ime_available || !videodata->ime_enabled)
+ return SDL_FALSE;
+
+ switch (msg)
+ {
+ case WM_INPUTLANGCHANGE:
+ break;
+ case WM_IME_SETCONTEXT:
+ *lParam = 0;
+ break;
+ case WM_IME_STARTCOMPOSITION:
+ trap = SDL_TRUE;
+ break;
+ case WM_IME_COMPOSITION:
+ trap = SDL_TRUE;
+ himc = ImmGetContext(hwnd);
+ if (*lParam & GCS_RESULTSTR)
+ {
+ LONG Length = 0;
+ char *s = 0;
+ Length = ImmGetCompositionStringW(himc, GCS_RESULTSTR, Buffer, sizeof(Buffer) * sizeof(Buffer[0]));
+ Buffer[Length / sizeof(Buffer[0])] = 0;
+ s = WIN_StringToUTF8(Buffer);
+ SDL_SendKeyboardText(s);
+ SDL_free(s);
+ }
+ if (*lParam & GCS_COMPSTR)
+ {
+ LONG Length = 0;
+ DWORD Cursor = 0;
+ char *s = 0;
+ Length = ImmGetCompositionStringW(himc, GCS_COMPSTR, Buffer, sizeof(Buffer) * sizeof(Buffer[0]));
+ Buffer[Length / sizeof(Buffer[0])] = 0;
+ s = WIN_StringToUTF8(Buffer);
+ Cursor = LOWORD(ImmGetCompositionStringW(himc, GCS_CURSORPOS, 0, 0));
+ SDL_SendEditingText(s, Cursor, 0);
+ SDL_free(s);
+ }
+ ImmReleaseContext(hwnd, himc);
+ break;
+ case WM_IME_ENDCOMPOSITION:
+ SDL_SendKeyboardText("");
+ break;
+ case WM_IME_NOTIFY:
+ switch (wParam)
+ {
+ case IMN_SETCONVERSIONMODE:
+ break;
+ case IMN_SETOPENSTATUS:
+ break;
+ case IMN_OPENCANDIDATE:
+ case IMN_CHANGECANDIDATE:
+ trap = SDL_TRUE;
+ break;
+ case IMN_CLOSECANDIDATE:
+ trap = SDL_TRUE;
+ break;
+ case IMN_PRIVATE:
+ break;
+ default:
+ trap = SDL_TRUE;
+ break;
+ }
+ break;
+ }
+ return trap;
+}
+
/* vi: set ts=4 sw=4 expandtab: */