mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-09-05 19:08:12 +00:00
Removed unneeded Text Services Framework code from IME handling
We can get the candidate list in uiless mode using ImmGetCandidateListW() once message processing has completed
This commit is contained in:
@@ -1051,7 +1051,7 @@ LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara
|
||||
#endif /* WMMSG_DEBUG */
|
||||
|
||||
#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)
|
||||
if (IME_HandleMessage(hwnd, msg, wParam, &lParam, data->videodata)) {
|
||||
if (WIN_HandleIMEMessage(hwnd, msg, wParam, &lParam, data->videodata)) {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -2302,6 +2302,8 @@ void WIN_PumpEvents(SDL_VideoDevice *_this)
|
||||
|
||||
#endif /*!defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)*/
|
||||
|
||||
WIN_UpdateIMECandidates(_this);
|
||||
|
||||
#ifdef SDL_PLATFORM_GDK
|
||||
GDK_DispatchTaskQueue();
|
||||
#endif
|
||||
|
@@ -40,6 +40,8 @@ static int IME_Init(SDL_VideoData *videodata, SDL_Window *window);
|
||||
static void IME_Enable(SDL_VideoData *videodata, HWND hwnd);
|
||||
static void IME_Disable(SDL_VideoData *videodata, HWND hwnd);
|
||||
static void IME_SetTextInputArea(SDL_VideoData *videodata, const SDL_Rect *rect, int cursor);
|
||||
static void IME_ClearComposition(SDL_VideoData *videodata);
|
||||
static void IME_GetCandidateList(SDL_VideoData *videodata, HWND hwnd);
|
||||
static void IME_Quit(SDL_VideoData *videodata);
|
||||
#endif /* !SDL_DISABLE_WINDOWS_IME */
|
||||
|
||||
@@ -59,10 +61,6 @@ void WIN_InitKeyboard(SDL_VideoDevice *_this)
|
||||
data->ime_candlistindexbase = 1;
|
||||
data->ime_composition_length = 32 * sizeof(WCHAR);
|
||||
data->ime_composition = (WCHAR *)SDL_calloc(data->ime_composition_length, sizeof(WCHAR));
|
||||
data->ime_uielemsinkcookie = TF_INVALID_COOKIE;
|
||||
data->ime_alpnsinkcookie = TF_INVALID_COOKIE;
|
||||
data->ime_openmodesinkcookie = TF_INVALID_COOKIE;
|
||||
data->ime_convmodesinkcookie = TF_INVALID_COOKIE;
|
||||
#endif /* !SDL_DISABLE_WINDOWS_IME */
|
||||
|
||||
WIN_UpdateKeymap(SDL_FALSE);
|
||||
@@ -242,39 +240,29 @@ int WIN_UpdateTextInputArea(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef SDL_DISABLE_WINDOWS_IME
|
||||
|
||||
int WIN_ClearComposition(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
{
|
||||
#ifndef SDL_DISABLE_WINDOWS_IME
|
||||
SDL_VideoData *videodata = _this->driverdata;
|
||||
|
||||
IME_ClearComposition(videodata);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
SDL_bool IME_HandleMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM *lParam, SDL_VideoData *videodata)
|
||||
#ifdef SDL_DISABLE_WINDOWS_IME
|
||||
|
||||
SDL_bool WIN_HandleIMEMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM *lParam, SDL_VideoData *videodata)
|
||||
{
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
#else
|
||||
void WIN_UpdateIMECandidates(SDL_VideoDevice *_this)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef SDL_msctf_h_
|
||||
#define USE_INIT_GUID
|
||||
#elif defined(__GNUC__)
|
||||
#define USE_INIT_GUID
|
||||
#endif
|
||||
#ifdef USE_INIT_GUID
|
||||
#undef DEFINE_GUID
|
||||
#define DEFINE_GUID(n, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) static const GUID n = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }
|
||||
DEFINE_GUID(IID_ITfInputProcessorProfileActivationSink, 0x71C6E74E, 0x0F28, 0x11D8, 0xA8, 0x2A, 0x00, 0x06, 0x5B, 0x84, 0x43, 0x5C);
|
||||
DEFINE_GUID(IID_ITfUIElementSink, 0xEA1EA136, 0x19DF, 0x11D7, 0xA6, 0xD2, 0x00, 0x06, 0x5B, 0x84, 0x43, 0x5C);
|
||||
DEFINE_GUID(GUID_TFCAT_TIP_KEYBOARD, 0x34745C63, 0xB2F0, 0x4784, 0x8B, 0x67, 0x5E, 0x12, 0xC8, 0x70, 0x1A, 0x31);
|
||||
DEFINE_GUID(IID_ITfSource, 0x4EA48A35, 0x60AE, 0x446F, 0x8F, 0xD6, 0xE6, 0xA8, 0xD8, 0x24, 0x59, 0xF7);
|
||||
DEFINE_GUID(IID_ITfUIElementMgr, 0xEA1EA135, 0x19DF, 0x11D7, 0xA6, 0xD2, 0x00, 0x06, 0x5B, 0x84, 0x43, 0x5C);
|
||||
DEFINE_GUID(IID_ITfCandidateListUIElement, 0xEA1EA138, 0x19DF, 0x11D7, 0xA6, 0xD2, 0x00, 0x06, 0x5B, 0x84, 0x43, 0x5C);
|
||||
DEFINE_GUID(IID_ITfReadingInformationUIElement, 0xEA1EA139, 0x19DF, 0x11D7, 0xA6, 0xD2, 0x00, 0x06, 0x5B, 0x84, 0x43, 0x5C);
|
||||
DEFINE_GUID(IID_ITfThreadMgr, 0xAA80E801, 0x2021, 0x11D2, 0x93, 0xE0, 0x00, 0x60, 0xB0, 0x67, 0xB8, 0x6E);
|
||||
DEFINE_GUID(CLSID_TF_ThreadMgr, 0x529A9E6B, 0x6587, 0x4F23, 0xAB, 0x9E, 0x9C, 0x7D, 0x68, 0x3E, 0x3C, 0x50);
|
||||
DEFINE_GUID(IID_ITfThreadMgrEx, 0x3E90ADE3, 0x7594, 0x4CB0, 0xBB, 0x58, 0x69, 0x62, 0x8F, 0x5F, 0x45, 0x8C);
|
||||
#endif
|
||||
#else
|
||||
|
||||
#define LANG_CHT MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL)
|
||||
#define LANG_CHS MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED)
|
||||
@@ -312,18 +300,12 @@ DEFINE_GUID(IID_ITfThreadMgrEx, 0x3E90ADE3, 0x7594, 0x4CB0, 0xBB, 0x58, 0x69, 0x
|
||||
#define SUBLANG() SUBLANGID(LANG())
|
||||
|
||||
static void IME_UpdateInputLocale(SDL_VideoData *videodata);
|
||||
static void IME_ClearComposition(SDL_VideoData *videodata);
|
||||
static void IME_SetWindow(SDL_VideoData *videodata, SDL_Window *window);
|
||||
static void IME_SetupAPI(SDL_VideoData *videodata);
|
||||
static DWORD IME_GetId(SDL_VideoData *videodata, UINT uIndex);
|
||||
static void IME_SendEditingEvent(SDL_VideoData *videodata);
|
||||
static void IME_SendClearComposition(SDL_VideoData *videodata);
|
||||
|
||||
static SDL_bool UILess_SetupSinks(SDL_VideoData *videodata);
|
||||
static void UILess_ReleaseSinks(SDL_VideoData *videodata);
|
||||
static void UILess_EnableUIUpdates(SDL_VideoData *videodata);
|
||||
static void UILess_DisableUIUpdates(SDL_VideoData *videodata);
|
||||
|
||||
static SDL_bool WIN_ShouldShowNativeUI()
|
||||
{
|
||||
return SDL_GetHintBoolean(SDL_HINT_IME_SHOW_UI, SDL_TRUE);
|
||||
@@ -332,21 +314,12 @@ static SDL_bool WIN_ShouldShowNativeUI()
|
||||
static int IME_Init(SDL_VideoData *videodata, SDL_Window *window)
|
||||
{
|
||||
HWND hwnd = window->driverdata->hwnd;
|
||||
HRESULT hResult = S_OK;
|
||||
|
||||
if (videodata->ime_initialized) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
videodata->ime_hwnd_main = hwnd;
|
||||
if (SUCCEEDED(WIN_CoInitialize())) {
|
||||
videodata->ime_com_initialized = SDL_TRUE;
|
||||
hResult = CoCreateInstance(&CLSID_TF_ThreadMgr, NULL, CLSCTX_INPROC_SERVER, &IID_ITfThreadMgr, (LPVOID *)&videodata->ime_threadmgr);
|
||||
if (hResult != S_OK) {
|
||||
videodata->ime_available = SDL_FALSE;
|
||||
return SDL_SetError("CoCreateInstance() failed, HRESULT is %08X", (unsigned int)hResult);
|
||||
}
|
||||
}
|
||||
videodata->ime_initialized = SDL_TRUE;
|
||||
videodata->ime_himm32 = SDL_LoadObject("imm32.dll");
|
||||
if (!videodata->ime_himm32) {
|
||||
@@ -375,7 +348,7 @@ static int IME_Init(SDL_VideoData *videodata, SDL_Window *window)
|
||||
if (WIN_ShouldShowNativeUI()) {
|
||||
videodata->ime_uiless = SDL_FALSE;
|
||||
} else {
|
||||
videodata->ime_uiless = UILess_SetupSinks(videodata);
|
||||
videodata->ime_uiless = SDL_TRUE;
|
||||
}
|
||||
IME_UpdateInputLocale(videodata);
|
||||
IME_Disable(videodata, hwnd);
|
||||
@@ -398,7 +371,6 @@ static void IME_Enable(SDL_VideoData *videodata, HWND hwnd)
|
||||
|
||||
videodata->ime_enabled = SDL_TRUE;
|
||||
IME_UpdateInputLocale(videodata);
|
||||
UILess_EnableUIUpdates(videodata);
|
||||
}
|
||||
|
||||
static void IME_Disable(SDL_VideoData *videodata, HWND hwnd)
|
||||
@@ -413,7 +385,6 @@ static void IME_Disable(SDL_VideoData *videodata, HWND hwnd)
|
||||
}
|
||||
|
||||
videodata->ime_enabled = SDL_FALSE;
|
||||
UILess_DisableUIUpdates(videodata);
|
||||
}
|
||||
|
||||
static void IME_Quit(SDL_VideoData *videodata)
|
||||
@@ -422,7 +393,6 @@ static void IME_Quit(SDL_VideoData *videodata)
|
||||
return;
|
||||
}
|
||||
|
||||
UILess_ReleaseSinks(videodata);
|
||||
if (videodata->ime_hwnd_main) {
|
||||
ImmAssociateContext(videodata->ime_hwnd_main, videodata->ime_himc);
|
||||
}
|
||||
@@ -433,14 +403,6 @@ static void IME_Quit(SDL_VideoData *videodata)
|
||||
SDL_UnloadObject(videodata->ime_himm32);
|
||||
videodata->ime_himm32 = 0;
|
||||
}
|
||||
if (videodata->ime_threadmgr) {
|
||||
videodata->ime_threadmgr->lpVtbl->Release(videodata->ime_threadmgr);
|
||||
videodata->ime_threadmgr = 0;
|
||||
}
|
||||
if (videodata->ime_com_initialized) {
|
||||
WIN_CoUninitialize();
|
||||
videodata->ime_com_initialized = SDL_FALSE;
|
||||
}
|
||||
for (int i = 0; i < videodata->ime_candcount; ++i) {
|
||||
SDL_free(videodata->ime_candidates[i]);
|
||||
videodata->ime_candidates[i] = NULL;
|
||||
@@ -459,10 +421,6 @@ static void IME_GetReadingString(SDL_VideoData *videodata, HWND hwnd)
|
||||
BOOL vertical = FALSE;
|
||||
UINT maxuilen = 0;
|
||||
|
||||
if (videodata->ime_uiless) {
|
||||
return;
|
||||
}
|
||||
|
||||
videodata->ime_readingstring[0] = 0;
|
||||
|
||||
id = IME_GetId(videodata, 0);
|
||||
@@ -554,9 +512,6 @@ static void IME_InputLangChanged(SDL_VideoData *videodata)
|
||||
{
|
||||
UINT lang = PRIMLANG();
|
||||
IME_UpdateInputLocale(videodata);
|
||||
if (!videodata->ime_uiless) {
|
||||
videodata->ime_candlistindexbase = (videodata->ime_hkl == CHT_HKL_DAYI) ? 0 : 1;
|
||||
}
|
||||
|
||||
IME_SetupAPI(videodata);
|
||||
if (lang != PRIMLANG()) {
|
||||
@@ -647,11 +602,8 @@ static void IME_SetupAPI(SDL_VideoData *videodata)
|
||||
char ime_file[MAX_PATH + 1];
|
||||
void *hime = 0;
|
||||
HKL hkl = 0;
|
||||
videodata->GetReadingString = 0;
|
||||
videodata->ShowReadingWindow = 0;
|
||||
if (videodata->ime_uiless) {
|
||||
return;
|
||||
}
|
||||
videodata->GetReadingString = NULL;
|
||||
videodata->ShowReadingWindow = NULL;
|
||||
|
||||
hkl = videodata->ime_hkl;
|
||||
if (!ImmGetIMEFileNameA(hkl, ime_file, sizeof(ime_file) - 1)) {
|
||||
@@ -689,15 +641,6 @@ static void IME_SetWindow(SDL_VideoData *videodata, SDL_Window *window)
|
||||
SDL_zero(videodata->ime_candidate_area);
|
||||
}
|
||||
|
||||
if (videodata->ime_threadmgr) {
|
||||
struct ITfDocumentMgr *document_mgr = 0;
|
||||
if (SUCCEEDED(videodata->ime_threadmgr->lpVtbl->AssociateFocus(videodata->ime_threadmgr, hwnd, NULL, &document_mgr))) {
|
||||
if (document_mgr) {
|
||||
document_mgr->lpVtbl->Release(document_mgr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IME_SetTextInputArea(videodata, &window->text_input_rect, window->text_input_cursor);
|
||||
}
|
||||
|
||||
@@ -751,6 +694,7 @@ static void IME_UpdateInputLocale(SDL_VideoData *videodata)
|
||||
|
||||
videodata->ime_hkl = hklnext;
|
||||
videodata->ime_horizontal_candidates = (PRIMLANG() == LANG_KOREAN || LANG() == LANG_CHS);
|
||||
videodata->ime_candlistindexbase = (videodata->ime_hkl == CHT_HKL_DAYI) ? 0 : 1;
|
||||
}
|
||||
|
||||
static void IME_ClearComposition(SDL_VideoData *videodata)
|
||||
@@ -766,9 +710,7 @@ static void IME_ClearComposition(SDL_VideoData *videodata)
|
||||
}
|
||||
|
||||
ImmNotifyIME(himc, NI_COMPOSITIONSTR, CPS_CANCEL, 0);
|
||||
if (videodata->ime_uiless) {
|
||||
ImmSetCompositionString(himc, SCS_SETSTR, TEXT(""), sizeof(TCHAR), TEXT(""), sizeof(TCHAR));
|
||||
}
|
||||
ImmSetCompositionString(himc, SCS_SETSTR, TEXT(""), sizeof(TCHAR), TEXT(""), sizeof(TCHAR));
|
||||
|
||||
ImmNotifyIME(himc, NI_CLOSECANDIDATE, 0, 0);
|
||||
ImmReleaseContext(videodata->ime_hwnd_current, himc);
|
||||
@@ -924,7 +866,6 @@ static int IME_OpenCandidateList(SDL_VideoData *videodata)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void IME_AddCandidate(SDL_VideoData *videodata, UINT i, LPCWSTR candidate)
|
||||
{
|
||||
if (videodata->ime_candidates[i]) {
|
||||
@@ -960,10 +901,83 @@ static void IME_CloseCandidateList(SDL_VideoData *videodata)
|
||||
}
|
||||
}
|
||||
|
||||
SDL_bool IME_HandleMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM *lParam, SDL_VideoData *videodata)
|
||||
static void IME_GetCandidateList(SDL_VideoData *videodata, HWND hwnd)
|
||||
{
|
||||
HIMC himc;
|
||||
DWORD size;
|
||||
LPCANDIDATELIST cand_list;
|
||||
SDL_bool has_candidates = SDL_FALSE;
|
||||
|
||||
himc = ImmGetContext(hwnd);
|
||||
if (himc) {
|
||||
size = ImmGetCandidateListW(himc, 0, NULL, 0);
|
||||
if (size != 0) {
|
||||
cand_list = (LPCANDIDATELIST)SDL_malloc(size);
|
||||
if (cand_list != NULL) {
|
||||
size = ImmGetCandidateListW(himc, 0, cand_list, size);
|
||||
if (size != 0) {
|
||||
if (IME_OpenCandidateList(videodata) == 0) {
|
||||
UINT i, j;
|
||||
UINT page_start = 0;
|
||||
UINT page_size = 0;
|
||||
|
||||
videodata->ime_candsel = cand_list->dwSelection;
|
||||
|
||||
if (LANG() == LANG_CHS && IME_GetId(videodata, 0)) {
|
||||
const UINT maxcandchar = 18;
|
||||
size_t cchars = 0;
|
||||
|
||||
for (i = 0; i < cand_list->dwCount; ++i) {
|
||||
size_t len = SDL_wcslen((LPWSTR)((DWORD_PTR)cand_list + cand_list->dwOffset[i])) + 1;
|
||||
if (len + cchars > maxcandchar) {
|
||||
if (i > cand_list->dwSelection) {
|
||||
break;
|
||||
}
|
||||
|
||||
page_start = i;
|
||||
cchars = len;
|
||||
} else {
|
||||
cchars += len;
|
||||
}
|
||||
}
|
||||
page_size = i - page_start;
|
||||
} else {
|
||||
page_size = SDL_min(cand_list->dwPageSize == 0 ? MAX_CANDLIST : cand_list->dwPageSize, MAX_CANDLIST);
|
||||
page_start = (cand_list->dwSelection / page_size) * page_size;
|
||||
}
|
||||
for (i = page_start, j = 0; (DWORD)i < cand_list->dwCount && j < page_size; i++, j++) {
|
||||
LPCWSTR candidate = (LPCWSTR)((DWORD_PTR)cand_list + cand_list->dwOffset[i]);
|
||||
IME_AddCandidate(videodata, j, candidate);
|
||||
}
|
||||
|
||||
has_candidates = SDL_TRUE;
|
||||
IME_SendCandidateList(videodata);
|
||||
}
|
||||
}
|
||||
SDL_free(cand_list);
|
||||
}
|
||||
}
|
||||
ImmReleaseContext(hwnd, himc);
|
||||
}
|
||||
|
||||
if (!has_candidates) {
|
||||
IME_CloseCandidateList(videodata);
|
||||
}
|
||||
}
|
||||
|
||||
SDL_bool WIN_HandleIMEMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM *lParam, SDL_VideoData *videodata)
|
||||
{
|
||||
SDL_bool trap = SDL_FALSE;
|
||||
HIMC himc = 0;
|
||||
|
||||
if (msg == WM_IME_SETCONTEXT) {
|
||||
SDL_DebugIMELog("WM_IME_SETCONTEXT\n");
|
||||
if (videodata->ime_uiless) {
|
||||
*lParam = 0;
|
||||
}
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
if (!videodata->ime_initialized || !videodata->ime_available || !videodata->ime_enabled) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
@@ -981,12 +995,6 @@ SDL_bool IME_HandleMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM *lParam, S
|
||||
SDL_DebugIMELog("WM_INPUTLANGCHANGE\n");
|
||||
IME_InputLangChanged(videodata);
|
||||
break;
|
||||
case WM_IME_SETCONTEXT:
|
||||
SDL_DebugIMELog("WM_IME_SETCONTEXT\n");
|
||||
if (videodata->ime_uiless) {
|
||||
*lParam = 0;
|
||||
}
|
||||
break;
|
||||
case WM_IME_STARTCOMPOSITION:
|
||||
SDL_DebugIMELog("WM_IME_STARTCOMPOSITION\n");
|
||||
trap = SDL_TRUE;
|
||||
@@ -1003,10 +1011,7 @@ SDL_bool IME_HandleMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM *lParam, S
|
||||
}
|
||||
if (*lParam & GCS_COMPSTR) {
|
||||
SDL_DebugIMELog("GCS_COMPSTR\n");
|
||||
if (!videodata->ime_uiless) {
|
||||
videodata->ime_readingstring[0] = 0;
|
||||
}
|
||||
|
||||
videodata->ime_readingstring[0] = 0;
|
||||
IME_GetCompositionString(videodata, himc, GCS_COMPSTR);
|
||||
IME_SendEditingEvent(videodata);
|
||||
}
|
||||
@@ -1038,11 +1043,18 @@ SDL_bool IME_HandleMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM *lParam, S
|
||||
case IMN_OPENCANDIDATE:
|
||||
case IMN_CHANGECANDIDATE:
|
||||
SDL_DebugIMELog("%s\n", wParam == IMN_OPENCANDIDATE ? "IMN_OPENCANDIDATE" : "IMN_CHANGECANDIDATE");
|
||||
trap = SDL_TRUE;
|
||||
if (videodata->ime_uiless) {
|
||||
videodata->ime_update_candidates = SDL_TRUE;
|
||||
trap = SDL_TRUE;
|
||||
}
|
||||
break;
|
||||
case IMN_CLOSECANDIDATE:
|
||||
SDL_DebugIMELog("IMN_CLOSECANDIDATE\n");
|
||||
trap = SDL_TRUE;
|
||||
if (videodata->ime_uiless) {
|
||||
videodata->ime_update_candidates = SDL_FALSE;
|
||||
IME_CloseCandidateList(videodata);
|
||||
trap = SDL_TRUE;
|
||||
}
|
||||
break;
|
||||
case IMN_PRIVATE:
|
||||
{
|
||||
@@ -1080,321 +1092,14 @@ SDL_bool IME_HandleMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM *lParam, S
|
||||
return trap;
|
||||
}
|
||||
|
||||
static void UILess_GetCandidateList(SDL_VideoData *videodata, ITfCandidateListUIElement *pcandlist)
|
||||
{
|
||||
UINT selection = 0;
|
||||
UINT count = 0;
|
||||
UINT page = 0;
|
||||
UINT pgcount = 0;
|
||||
DWORD pgstart = 0;
|
||||
DWORD pgsize = 0;
|
||||
UINT i, j;
|
||||
|
||||
if (IME_OpenCandidateList(videodata) < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
pcandlist->lpVtbl->GetSelection(pcandlist, &selection);
|
||||
pcandlist->lpVtbl->GetCount(pcandlist, &count);
|
||||
pcandlist->lpVtbl->GetCurrentPage(pcandlist, &page);
|
||||
|
||||
pcandlist->lpVtbl->GetPageIndex(pcandlist, NULL, 0, &pgcount);
|
||||
if (pgcount > 0) {
|
||||
UINT *idxlist = SDL_malloc(sizeof(UINT) * pgcount);
|
||||
if (idxlist) {
|
||||
pcandlist->lpVtbl->GetPageIndex(pcandlist, idxlist, pgcount, &pgcount);
|
||||
pgstart = idxlist[page];
|
||||
if (page < pgcount - 1) {
|
||||
pgsize = SDL_min(count, idxlist[page + 1]) - pgstart;
|
||||
} else {
|
||||
pgsize = count - pgstart;
|
||||
}
|
||||
|
||||
SDL_free(idxlist);
|
||||
}
|
||||
}
|
||||
pgsize = SDL_min(pgsize, MAX_CANDLIST);
|
||||
videodata->ime_candsel = selection - pgstart;
|
||||
for (i = pgstart, j = 0; (DWORD)i < count && j < pgsize; i++, j++) {
|
||||
BSTR bstr;
|
||||
if (SUCCEEDED(pcandlist->lpVtbl->GetString(pcandlist, i, &bstr))) {
|
||||
if (bstr) {
|
||||
IME_AddCandidate(videodata, j, bstr);
|
||||
SysFreeString(bstr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IME_SendCandidateList(videodata);
|
||||
}
|
||||
|
||||
STDMETHODIMP_(ULONG)
|
||||
TSFSink_AddRef(TSFSink *sink)
|
||||
{
|
||||
return ++sink->refcount;
|
||||
}
|
||||
|
||||
STDMETHODIMP_(ULONG)
|
||||
TSFSink_Release(TSFSink *sink)
|
||||
{
|
||||
--sink->refcount;
|
||||
if (sink->refcount == 0) {
|
||||
SDL_free(sink);
|
||||
return 0;
|
||||
}
|
||||
return sink->refcount;
|
||||
}
|
||||
|
||||
STDMETHODIMP UIElementSink_QueryInterface(TSFSink *sink, REFIID riid, PVOID *ppv)
|
||||
{
|
||||
if (!ppv) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
*ppv = 0;
|
||||
if (WIN_IsEqualIID(riid, &IID_IUnknown)) {
|
||||
*ppv = (IUnknown *)sink;
|
||||
} else if (WIN_IsEqualIID(riid, &IID_ITfUIElementSink)) {
|
||||
*ppv = (ITfUIElementSink *)sink;
|
||||
}
|
||||
|
||||
if (*ppv) {
|
||||
TSFSink_AddRef(sink);
|
||||
return S_OK;
|
||||
}
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
ITfUIElement *UILess_GetUIElement(SDL_VideoData *videodata, DWORD dwUIElementId)
|
||||
{
|
||||
ITfUIElementMgr *puiem = 0;
|
||||
ITfUIElement *pelem = 0;
|
||||
ITfThreadMgrEx *threadmgrex = videodata->ime_threadmgrex;
|
||||
|
||||
if (SUCCEEDED(threadmgrex->lpVtbl->QueryInterface(threadmgrex, &IID_ITfUIElementMgr, (LPVOID *)&puiem))) {
|
||||
puiem->lpVtbl->GetUIElement(puiem, dwUIElementId, &pelem);
|
||||
puiem->lpVtbl->Release(puiem);
|
||||
}
|
||||
return pelem;
|
||||
}
|
||||
|
||||
STDMETHODIMP UIElementSink_BeginUIElement(TSFSink *sink, DWORD dwUIElementId, BOOL *pbShow)
|
||||
{
|
||||
ITfUIElement *element = UILess_GetUIElement((SDL_VideoData *)sink->data, dwUIElementId);
|
||||
ITfReadingInformationUIElement *preading = 0;
|
||||
ITfCandidateListUIElement *pcandlist = 0;
|
||||
SDL_VideoData *videodata = (SDL_VideoData *)sink->data;
|
||||
if (!element) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
*pbShow = FALSE;
|
||||
if (SUCCEEDED(element->lpVtbl->QueryInterface(element, &IID_ITfReadingInformationUIElement, (LPVOID *)&preading))) {
|
||||
BSTR bstr;
|
||||
if (SUCCEEDED(preading->lpVtbl->GetString(preading, &bstr)) && bstr) {
|
||||
SysFreeString(bstr);
|
||||
}
|
||||
preading->lpVtbl->Release(preading);
|
||||
} else if (SUCCEEDED(element->lpVtbl->QueryInterface(element, &IID_ITfCandidateListUIElement, (LPVOID *)&pcandlist))) {
|
||||
videodata->ime_candref++;
|
||||
UILess_GetCandidateList(videodata, pcandlist);
|
||||
pcandlist->lpVtbl->Release(pcandlist);
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP UIElementSink_UpdateUIElement(TSFSink *sink, DWORD dwUIElementId)
|
||||
{
|
||||
ITfUIElement *element = UILess_GetUIElement((SDL_VideoData *)sink->data, dwUIElementId);
|
||||
ITfReadingInformationUIElement *preading = 0;
|
||||
ITfCandidateListUIElement *pcandlist = 0;
|
||||
SDL_VideoData *videodata = (SDL_VideoData *)sink->data;
|
||||
if (!element) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(element->lpVtbl->QueryInterface(element, &IID_ITfReadingInformationUIElement, (LPVOID *)&preading))) {
|
||||
BSTR bstr;
|
||||
if (SUCCEEDED(preading->lpVtbl->GetString(preading, &bstr)) && bstr) {
|
||||
WCHAR *s = (WCHAR *)bstr;
|
||||
SDL_wcslcpy(videodata->ime_readingstring, s, SDL_arraysize(videodata->ime_readingstring));
|
||||
IME_SendEditingEvent(videodata);
|
||||
SysFreeString(bstr);
|
||||
}
|
||||
preading->lpVtbl->Release(preading);
|
||||
} else if (SUCCEEDED(element->lpVtbl->QueryInterface(element, &IID_ITfCandidateListUIElement, (LPVOID *)&pcandlist))) {
|
||||
UILess_GetCandidateList(videodata, pcandlist);
|
||||
pcandlist->lpVtbl->Release(pcandlist);
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP UIElementSink_EndUIElement(TSFSink *sink, DWORD dwUIElementId)
|
||||
{
|
||||
ITfUIElement *element = UILess_GetUIElement((SDL_VideoData *)sink->data, dwUIElementId);
|
||||
ITfReadingInformationUIElement *preading = 0;
|
||||
ITfCandidateListUIElement *pcandlist = 0;
|
||||
SDL_VideoData *videodata = (SDL_VideoData *)sink->data;
|
||||
if (!element) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(element->lpVtbl->QueryInterface(element, &IID_ITfReadingInformationUIElement, (LPVOID *)&preading))) {
|
||||
videodata->ime_readingstring[0] = 0;
|
||||
IME_SendEditingEvent(videodata);
|
||||
preading->lpVtbl->Release(preading);
|
||||
}
|
||||
if (SUCCEEDED(element->lpVtbl->QueryInterface(element, &IID_ITfCandidateListUIElement, (LPVOID *)&pcandlist))) {
|
||||
videodata->ime_candref--;
|
||||
if (videodata->ime_candref == 0) {
|
||||
IME_CloseCandidateList(videodata);
|
||||
}
|
||||
|
||||
pcandlist->lpVtbl->Release(pcandlist);
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP IPPASink_QueryInterface(TSFSink *sink, REFIID riid, PVOID *ppv)
|
||||
{
|
||||
if (!ppv) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
*ppv = 0;
|
||||
if (WIN_IsEqualIID(riid, &IID_IUnknown)) {
|
||||
*ppv = (IUnknown *)sink;
|
||||
} else if (WIN_IsEqualIID(riid, &IID_ITfInputProcessorProfileActivationSink)) {
|
||||
*ppv = (ITfInputProcessorProfileActivationSink *)sink;
|
||||
}
|
||||
|
||||
if (*ppv) {
|
||||
TSFSink_AddRef(sink);
|
||||
return S_OK;
|
||||
}
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
STDMETHODIMP IPPASink_OnActivated(TSFSink *sink, DWORD dwProfileType, LANGID langid, REFCLSID clsid, REFGUID catid, REFGUID guidProfile, HKL hkl, DWORD dwFlags)
|
||||
{
|
||||
static const GUID SDL_TF_PROFILE_DAYI = { 0x037B2C25, 0x480C, 0x4D7F, { 0xB0, 0x27, 0xD6, 0xCA, 0x6B, 0x69, 0x78, 0x8A } };
|
||||
SDL_VideoData *videodata = (SDL_VideoData *)sink->data;
|
||||
videodata->ime_candlistindexbase = WIN_IsEqualGUID(&SDL_TF_PROFILE_DAYI, guidProfile) ? 0 : 1;
|
||||
if (WIN_IsEqualIID(catid, &GUID_TFCAT_TIP_KEYBOARD) && (dwFlags & TF_IPSINK_FLAG_ACTIVE)) {
|
||||
IME_InputLangChanged((SDL_VideoData *)sink->data);
|
||||
}
|
||||
|
||||
IME_CloseCandidateList(videodata);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static void *vtUIElementSink[] = {
|
||||
(void *)(UIElementSink_QueryInterface),
|
||||
(void *)(TSFSink_AddRef),
|
||||
(void *)(TSFSink_Release),
|
||||
(void *)(UIElementSink_BeginUIElement),
|
||||
(void *)(UIElementSink_UpdateUIElement),
|
||||
(void *)(UIElementSink_EndUIElement)
|
||||
};
|
||||
|
||||
static void *vtIPPASink[] = {
|
||||
(void *)(IPPASink_QueryInterface),
|
||||
(void *)(TSFSink_AddRef),
|
||||
(void *)(TSFSink_Release),
|
||||
(void *)(IPPASink_OnActivated)
|
||||
};
|
||||
|
||||
static void UILess_EnableUIUpdates(SDL_VideoData *videodata)
|
||||
{
|
||||
ITfSource *source = 0;
|
||||
if (!videodata->ime_threadmgrex || videodata->ime_uielemsinkcookie != TF_INVALID_COOKIE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(videodata->ime_threadmgrex->lpVtbl->QueryInterface(videodata->ime_threadmgrex, &IID_ITfSource, (LPVOID *)&source))) {
|
||||
source->lpVtbl->AdviseSink(source, &IID_ITfUIElementSink, (IUnknown *)videodata->ime_uielemsink, &videodata->ime_uielemsinkcookie);
|
||||
source->lpVtbl->Release(source);
|
||||
}
|
||||
}
|
||||
|
||||
static void UILess_DisableUIUpdates(SDL_VideoData *videodata)
|
||||
{
|
||||
ITfSource *source = 0;
|
||||
if (!videodata->ime_threadmgrex || videodata->ime_uielemsinkcookie == TF_INVALID_COOKIE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(videodata->ime_threadmgrex->lpVtbl->QueryInterface(videodata->ime_threadmgrex, &IID_ITfSource, (LPVOID *)&source))) {
|
||||
source->lpVtbl->UnadviseSink(source, videodata->ime_uielemsinkcookie);
|
||||
videodata->ime_uielemsinkcookie = TF_INVALID_COOKIE;
|
||||
source->lpVtbl->Release(source);
|
||||
}
|
||||
}
|
||||
|
||||
static SDL_bool UILess_SetupSinks(SDL_VideoData *videodata)
|
||||
{
|
||||
TfClientId clientid = 0;
|
||||
SDL_bool result = SDL_FALSE;
|
||||
ITfSource *source = 0;
|
||||
if (FAILED(CoCreateInstance(&CLSID_TF_ThreadMgr, NULL, CLSCTX_INPROC_SERVER, &IID_ITfThreadMgrEx, (LPVOID *)&videodata->ime_threadmgrex))) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
if (FAILED(videodata->ime_threadmgrex->lpVtbl->ActivateEx(videodata->ime_threadmgrex, &clientid, TF_TMAE_UIELEMENTENABLEDONLY))) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
videodata->ime_uielemsink = (TSFSink *)SDL_malloc(sizeof(TSFSink));
|
||||
videodata->ime_ippasink = (TSFSink *)SDL_malloc(sizeof(TSFSink));
|
||||
|
||||
videodata->ime_uielemsink->lpVtbl = vtUIElementSink;
|
||||
videodata->ime_uielemsink->refcount = 1;
|
||||
videodata->ime_uielemsink->data = videodata;
|
||||
|
||||
videodata->ime_ippasink->lpVtbl = vtIPPASink;
|
||||
videodata->ime_ippasink->refcount = 1;
|
||||
videodata->ime_ippasink->data = videodata;
|
||||
|
||||
if (SUCCEEDED(videodata->ime_threadmgrex->lpVtbl->QueryInterface(videodata->ime_threadmgrex, &IID_ITfSource, (LPVOID *)&source))) {
|
||||
if (SUCCEEDED(source->lpVtbl->AdviseSink(source, &IID_ITfUIElementSink, (IUnknown *)videodata->ime_uielemsink, &videodata->ime_uielemsinkcookie))) {
|
||||
if (SUCCEEDED(source->lpVtbl->AdviseSink(source, &IID_ITfInputProcessorProfileActivationSink, (IUnknown *)videodata->ime_ippasink, &videodata->ime_alpnsinkcookie))) {
|
||||
result = SDL_TRUE;
|
||||
}
|
||||
}
|
||||
source->lpVtbl->Release(source);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#define SAFE_RELEASE(p) \
|
||||
{ \
|
||||
if (p) { \
|
||||
(p)->lpVtbl->Release((p)); \
|
||||
(p) = 0; \
|
||||
} \
|
||||
}
|
||||
|
||||
static void UILess_ReleaseSinks(SDL_VideoData *videodata)
|
||||
{
|
||||
ITfSource *source = 0;
|
||||
if (videodata->ime_threadmgrex && SUCCEEDED(videodata->ime_threadmgrex->lpVtbl->QueryInterface(videodata->ime_threadmgrex, &IID_ITfSource, (LPVOID *)&source))) {
|
||||
source->lpVtbl->UnadviseSink(source, videodata->ime_uielemsinkcookie);
|
||||
source->lpVtbl->UnadviseSink(source, videodata->ime_alpnsinkcookie);
|
||||
SAFE_RELEASE(source);
|
||||
videodata->ime_threadmgrex->lpVtbl->Deactivate(videodata->ime_threadmgrex);
|
||||
SAFE_RELEASE(videodata->ime_threadmgrex);
|
||||
TSFSink_Release(videodata->ime_uielemsink);
|
||||
videodata->ime_uielemsink = 0;
|
||||
TSFSink_Release(videodata->ime_ippasink);
|
||||
videodata->ime_ippasink = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int WIN_ClearComposition(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
void WIN_UpdateIMECandidates(SDL_VideoDevice *_this)
|
||||
{
|
||||
SDL_VideoData *videodata = _this->driverdata;
|
||||
IME_ClearComposition(videodata);
|
||||
return 0;
|
||||
|
||||
if (videodata->ime_update_candidates) {
|
||||
IME_GetCandidateList(videodata, videodata->ime_hwnd_current);
|
||||
videodata->ime_update_candidates = SDL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* SDL_DISABLE_WINDOWS_IME */
|
||||
|
@@ -34,6 +34,7 @@ extern int WIN_StopTextInput(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
extern int WIN_UpdateTextInputArea(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
extern int WIN_ClearComposition(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
|
||||
extern SDL_bool IME_HandleMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM *lParam, struct SDL_VideoData *videodata);
|
||||
extern SDL_bool WIN_HandleIMEMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM *lParam, struct SDL_VideoData *videodata);
|
||||
extern void WIN_UpdateIMECandidates(SDL_VideoDevice *_this);
|
||||
|
||||
#endif /* SDL_windowskeyboard_h_ */
|
||||
|
@@ -423,7 +423,6 @@ struct SDL_VideoData
|
||||
|
||||
#ifndef SDL_DISABLE_WINDOWS_IME
|
||||
SDL_bool ime_com_initialized;
|
||||
struct ITfThreadMgr *ime_threadmgr;
|
||||
SDL_bool ime_initialized;
|
||||
SDL_bool ime_enabled;
|
||||
SDL_bool ime_available;
|
||||
@@ -440,6 +439,7 @@ struct SDL_VideoData
|
||||
int ime_selected_length;
|
||||
|
||||
SDL_bool ime_candidates_open;
|
||||
SDL_bool ime_update_candidates;
|
||||
char *ime_candidates[MAX_CANDLIST];
|
||||
int ime_candcount;
|
||||
DWORD ime_candref;
|
||||
@@ -462,13 +462,6 @@ struct SDL_VideoData
|
||||
/* *INDENT-ON* */ /* clang-format on */
|
||||
|
||||
SDL_bool ime_uiless;
|
||||
struct ITfThreadMgrEx *ime_threadmgrex;
|
||||
DWORD ime_uielemsinkcookie;
|
||||
DWORD ime_alpnsinkcookie;
|
||||
DWORD ime_openmodesinkcookie;
|
||||
DWORD ime_convmodesinkcookie;
|
||||
TSFSink *ime_uielemsink;
|
||||
TSFSink *ime_ippasink;
|
||||
#endif /* !SDL_DISABLE_WINDOWS_IME */
|
||||
|
||||
BYTE pre_hook_key_state[256];
|
||||
|
Reference in New Issue
Block a user