Commit 3d5a6d85 authored by dewyatt's avatar dewyatt

Initial IMM implementation.

IME input should now work fairly well.
parent 2f1a5c46
......@@ -131,6 +131,8 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
}
#endif
if (IME_HandleMessage(hwnd, msg, wParam, &lParam, data->videodata))
return 0;
switch (msg) {
......
......@@ -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 @@ BYTE keypad_scancodes[10] = {
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 @@ WIN_InitKeyboard(_THIS)
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 @@ WIN_UpdateKeymap()
void
WIN_QuitKeyboard(_THIS)
{
IME_Quit((SDL_VideoData *)_this->driverdata);
}
void
WIN_StartTextInput(_THIS, SDL_Window *window)
{
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 @@ WIN_SetTextInputRect(_THIS, SDL_Rect *rect)
}
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: */
......@@ -35,6 +35,8 @@ extern void WIN_StartTextInput(_THIS, SDL_Window *window);
extern void WIN_StopTextInput(_THIS, SDL_Window *window);
extern void WIN_SetTextInputRect(_THIS, SDL_Rect *rect);
extern SDL_bool IME_HandleMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM *lParam, struct SDL_VideoData *videodata);
#endif /* _SDL_win32keyboard_h */
/* vi: set ts=4 sw=4 expandtab: */
......@@ -75,6 +75,16 @@ typedef struct SDL_VideoData
#endif
const SDL_scancode *key_layout;
SDL_bool ime_com_initialized;
struct ITfThreadMgr *ime_thread_mgr;
SDL_bool ime_initialized;
SDL_bool ime_enabled;
SDL_bool ime_available;
HWND ime_hwnd_main;
HWND ime_hwnd_current;
HIMC ime_himc;
} SDL_VideoData;
#endif /* _SDL_win32video_h */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment