Initial IMM implementation.
IME input should now work fairly well.
This commit is contained in:
parent
2f1a5c4653
commit
3d5a6d8597
4 changed files with 197 additions and 3 deletions
|
@ -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;
|
||||
|
||||
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: */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue