Skip to content
This repository has been archived by the owner on Feb 11, 2021. It is now read-only.

Commit

Permalink
Initial IMM implementation.
Browse files Browse the repository at this point in the history
IME input should now work fairly well.
  • Loading branch information
dewyatt committed Jul 12, 2010
1 parent 3910703 commit 53fe014
Show file tree
Hide file tree
Showing 4 changed files with 197 additions and 3 deletions.
2 changes: 2 additions & 0 deletions src/video/win32/SDL_win32events.c
Expand Up @@ -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) {

Expand Down
186 changes: 183 additions & 3 deletions src/video/win32/SDL_win32keyboard.c
Expand Up @@ -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
Expand All @@ -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)
{
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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;

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
Expand All @@ -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: */
2 changes: 2 additions & 0 deletions src/video/win32/SDL_win32keyboard.h
Expand Up @@ -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: */
10 changes: 10 additions & 0 deletions src/video/win32/SDL_win32video.h
Expand Up @@ -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 */
Expand Down

0 comments on commit 53fe014

Please sign in to comment.