https://git.reactos.org/?p=reactos.git;a=commitdiff;h=23bb27037d90c3d3c5a8a…
commit 23bb27037d90c3d3c5a8a5441d93d0b922ac14fa
Author: Katayama Hirofumi MZ <katayama.hirofumi.mz(a)gmail.com>
AuthorDate: Thu Jan 27 21:19:37 2022 +0900
Commit: GitHub <noreply(a)github.com>
CommitDate: Thu Jan 27 21:19:37 2022 +0900
[USER32] Implement User32CreateImeUI (#4316)
Implementing Japanese input...
- Add User32CreateImeUIWindow, User32GetImeShowStatus, User32SendImeUIMessage,
User32UpdateImcOfImeUI, User32SetImeWindowOfImc and User32NotifyOpenStatus helper
functions.
- Add WM_IME_SELECT, WM_IME_COMPOSITION, WM_IME_STARTCOMPOSITION and
WM_IME_ENDCOMPOSITION message handling of the IME window.
- Rename ImeWnd_OnDestroy as User32DestroyImeUIWindow.
- Rename CheckIMCForWindow as User32CanSetImeWindowToImc.
- Improve ImeWnd_OnCreate function.
CORE-11700
---
win32ss/include/ntuser.h | 2 +-
win32ss/user/user32/misc/imm.c | 171 +++++++++++++++++++++++++++++++++++++----
2 files changed, 157 insertions(+), 16 deletions(-)
diff --git a/win32ss/include/ntuser.h b/win32ss/include/ntuser.h
index 400830ab3e5..705f5aa08a9 100644
--- a/win32ss/include/ntuser.h
+++ b/win32ss/include/ntuser.h
@@ -1200,7 +1200,7 @@ typedef struct tagIMEUI
HWND hwndIMC;
HKL hKL;
HWND hwndUI;
- INT nCntInIMEProc;
+ LONG nCntInIMEProc;
struct {
UINT fShowStatus:1;
UINT fActivate:1;
diff --git a/win32ss/user/user32/misc/imm.c b/win32ss/user/user32/misc/imm.c
index 26bc38cad4c..7e70167b277 100644
--- a/win32ss/user/user32/misc/imm.c
+++ b/win32ss/user/user32/misc/imm.c
@@ -133,29 +133,142 @@ BOOL WINAPI User32InitializeImmEntryTable(DWORD magic)
return IMM_FN(ImmRegisterClient)(&gSharedInfo, ghImm32);
}
-static BOOL CheckIMCForWindow(HIMC hIMC, HWND hWnd)
+static BOOL User32CanSetImeWindowToImc(HIMC hIMC, HWND hImeWnd)
{
PIMC pIMC = ValidateHandle(hIMC, TYPE_INPUTCONTEXT);
- return pIMC && (!pIMC->hImeWnd || pIMC->hImeWnd == hWnd ||
!ValidateHwnd(pIMC->hImeWnd));
+ return pIMC && (!pIMC->hImeWnd || pIMC->hImeWnd == hImeWnd ||
!ValidateHwnd(pIMC->hImeWnd));
+}
+
+static BOOL User32GetImeShowStatus(VOID)
+{
+ return (BOOL)NtUserCallNoParam(NOPARAM_ROUTINE_GETIMESHOWSTATUS);
+}
+
+static LRESULT
+User32SendImeUIMessage(PIMEUI pimeui, UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL
unicode)
+{
+ LRESULT ret = 0;
+ HWND hwndUI = pimeui->hwndUI;
+ PWND pwnd, pwndUI;
+
+ pwnd = pimeui->spwnd;
+ pwndUI = ValidateHwnd(hwndUI);
+ if (!pwnd || (pwnd->state & WNDS_DESTROYED) || (pwnd->state2 &
WNDS2_INDESTROY) ||
+ !pwndUI || (pwndUI->state & WNDS_DESTROYED) || (pwndUI->state2 &
WNDS2_INDESTROY))
+ {
+ return 0;
+ }
+
+ InterlockedIncrement(&pimeui->nCntInIMEProc);
+
+ if (unicode)
+ ret = SendMessageW(hwndUI, uMsg, wParam, lParam);
+ else
+ ret = SendMessageA(hwndUI, uMsg, wParam, lParam);
+
+ InterlockedDecrement(&pimeui->nCntInIMEProc);
+
+ return ret;
+}
+
+static VOID User32NotifyOpenStatus(PIMEUI pimeui, HWND hwndIMC, BOOL bOpen)
+{
+ WPARAM wParam = (bOpen ? IMN_OPENSTATUSWINDOW : IMN_CLOSESTATUSWINDOW);
+
+ pimeui->fShowStatus = bOpen;
+
+ if (LOWORD(GetWin32ClientInfo()->dwExpWinVer) >= 0x400)
+ SendMessageW(hwndIMC, WM_IME_NOTIFY, wParam, 0);
+ else
+ User32SendImeUIMessage(pimeui, WM_IME_NOTIFY, wParam, 0, TRUE);
+}
+
+static VOID User32SetImeWindowOfImc(HIMC hIMC, HWND hImeWnd)
+{
+ PIMC pIMC = ValidateHandle(hIMC, TYPE_INPUTCONTEXT);
+ if (!pIMC || pIMC->hImeWnd == hImeWnd)
+ return;
+
+ NtUserUpdateInputContext(hIMC, UIC_IMEWINDOW, (ULONG_PTR)hImeWnd);
+}
+
+static VOID User32UpdateImcOfImeUI(PIMEUI pimeui, HIMC hNewIMC)
+{
+ HWND hImeWnd = UserHMGetHandle(pimeui->spwnd);
+ HIMC hOldIMC = pimeui->hIMC;
+
+ if (hNewIMC == hOldIMC)
+ return;
+
+ if (hOldIMC)
+ User32SetImeWindowOfImc(hOldIMC, NULL);
+
+ pimeui->hIMC = hNewIMC;
+
+ if (hNewIMC)
+ User32SetImeWindowOfImc(hNewIMC, hImeWnd);
+}
+
+static HWND User32CreateImeUIWindow(PIMEUI pimeui, HKL hKL)
+{
+ IMEINFOEX ImeInfoEx;
+ PIMEDPI pImeDpi;
+ WNDCLASSW wc;
+ HWND hwndUI = NULL;
+ CHAR szUIClass[32];
+ PWND pwnd = pimeui->spwnd;
+
+ if (!pwnd || !IMM_FN(ImmGetImeInfoEx)(&ImeInfoEx, ImeInfoExKeyboardLayout,
&hKL))
+ return NULL;
+
+ pImeDpi = IMM_FN(ImmLockImeDpi)(hKL);
+ if (!pImeDpi)
+ return NULL;
+
+ if (!GetClassInfoW(pImeDpi->hInst, ImeInfoEx.wszUIClass, &wc))
+ goto Quit;
+
+ if (ImeInfoEx.ImeInfo.fdwProperty & IME_PROP_UNICODE)
+ {
+ hwndUI = CreateWindowW(ImeInfoEx.wszUIClass, ImeInfoEx.wszUIClass, WS_POPUP |
WS_DISABLED,
+ 0, 0, 0, 0, UserHMGetHandle(pwnd), 0, wc.hInstance,
NULL);
+ }
+ else
+ {
+ WideCharToMultiByte(CP_ACP, 0, ImeInfoEx.wszUIClass, -1,
+ szUIClass, _countof(szUIClass), NULL, NULL);
+ szUIClass[_countof(szUIClass) - 1] = 0;
+
+ hwndUI = CreateWindowA(szUIClass, szUIClass, WS_POPUP | WS_DISABLED,
+ 0, 0, 0, 0, UserHMGetHandle(pwnd), 0, wc.hInstance,
NULL);
+ }
+
+ if (hwndUI)
+ NtUserSetWindowLong(hwndUI, IMMGWL_IMC, (LONG_PTR)pimeui->hIMC, FALSE);
+
+Quit:
+ IMM_FN(ImmUnlockImeDpi)(pImeDpi);
+ return hwndUI;
}
static BOOL ImeWnd_OnCreate(PIMEUI pimeui, LPCREATESTRUCT lpCS)
{
PWND pParentWnd, pWnd = pimeui->spwnd;
- HIMC hIMC;
+ HIMC hIMC = NULL;
if (!pWnd || (pWnd->style & (WS_DISABLED | WS_POPUP)) != (WS_DISABLED |
WS_POPUP))
return FALSE;
- pimeui->hIMC = NULL;
pParentWnd = ValidateHwnd(lpCS->hwndParent);
if (pParentWnd)
{
hIMC = pParentWnd->hImc;
- if (hIMC && CheckIMCForWindow(hIMC, UserHMGetHandle(pWnd)))
- pimeui->hIMC = hIMC;
+ if (hIMC && !User32CanSetImeWindowToImc(hIMC, UserHMGetHandle(pWnd)))
+ hIMC = NULL;
}
+ User32UpdateImcOfImeUI(pimeui, hIMC);
+
pimeui->fShowStatus = FALSE;
pimeui->nCntInIMEProc = 0;
pimeui->fActivate = FALSE;
@@ -165,10 +278,13 @@ static BOOL ImeWnd_OnCreate(PIMEUI pimeui, LPCREATESTRUCT lpCS)
pimeui->fCtrlShowStatus = TRUE;
IMM_FN(ImmLoadIME)(pimeui->hKL);
+
+ pimeui->hwndUI = NULL;
+
return TRUE;
}
-static void ImeWnd_OnDestroy(PIMEUI pimeui)
+static VOID User32DestroyImeUIWindow(PIMEUI pimeui)
{
HWND hwndUI = pimeui->hwndUI;
@@ -182,6 +298,35 @@ static void ImeWnd_OnDestroy(PIMEUI pimeui)
pimeui->hwndUI = NULL;
}
+VOID ImeWnd_OnImeSelect(PIMEUI pimeui, WPARAM wParam, LPARAM lParam)
+{
+ HKL hKL;
+ HWND hwndUI, hwndIMC = pimeui->hwndIMC;
+
+ if (wParam)
+ {
+ pimeui->hKL = hKL = (HKL)lParam;
+ pimeui->hwndUI = hwndUI = User32CreateImeUIWindow(pimeui, hKL);
+ if (hwndUI)
+ User32SendImeUIMessage(pimeui, WM_IME_SELECT, wParam, lParam, TRUE);
+
+ if (User32GetImeShowStatus() && pimeui->fCtrlShowStatus)
+ {
+ if (!pimeui->fShowStatus && pimeui->fActivate &&
IsWindow(hwndIMC))
+ User32NotifyOpenStatus(pimeui, hwndIMC, TRUE);
+ }
+ }
+ else
+ {
+ if (pimeui->fShowStatus && pimeui->fActivate &&
IsWindow(hwndIMC))
+ User32NotifyOpenStatus(pimeui, hwndIMC, FALSE);
+
+ User32SendImeUIMessage(pimeui, WM_IME_SELECT, wParam, lParam, TRUE);
+ User32DestroyImeUIWindow(pimeui);
+ pimeui->hKL = NULL;
+ }
+}
+
LRESULT WINAPI ImeWndProc_common( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, BOOL
unicode ) // ReactOS
{
PWND pWnd;
@@ -226,6 +371,7 @@ LRESULT WINAPI ImeWndProc_common( HWND hwnd, UINT msg, WPARAM wParam,
LPARAM lPa
case WM_IME_CHAR:
case WM_IME_COMPOSITIONFULL:
case WM_IME_CONTROL:
+ case WM_IME_NOTIFY:
case WM_IME_REQUEST:
case WM_IME_SELECT:
case WM_IME_SETCONTEXT:
@@ -234,10 +380,6 @@ LRESULT WINAPI ImeWndProc_common( HWND hwnd, UINT msg, WPARAM wParam,
LPARAM lPa
case WM_IME_ENDCOMPOSITION:
return 0;
- case WM_IME_NOTIFY:
- // TODO:
- return 0;
-
case WM_IME_SYSTEM:
// TODO:
return 0;
@@ -257,7 +399,7 @@ LRESULT WINAPI ImeWndProc_common( HWND hwnd, UINT msg, WPARAM wParam,
LPARAM lPa
return (ImeWnd_OnCreate(pimeui, (LPCREATESTRUCT)lParam) ? 0 : -1);
case WM_DESTROY:
- ImeWnd_OnDestroy(pimeui);
+ User32DestroyImeUIWindow(pimeui);
break;
case WM_NCDESTROY:
@@ -279,8 +421,7 @@ LRESULT WINAPI ImeWndProc_common( HWND hwnd, UINT msg, WPARAM wParam,
LPARAM lPa
case WM_IME_STARTCOMPOSITION:
case WM_IME_COMPOSITION:
case WM_IME_ENDCOMPOSITION:
- // TODO:
- break;
+ return User32SendImeUIMessage(pimeui, msg, wParam, lParam, unicode);
case WM_IME_CONTROL:
// TODO:
@@ -294,7 +435,7 @@ LRESULT WINAPI ImeWndProc_common( HWND hwnd, UINT msg, WPARAM wParam,
LPARAM lPa
break;
case WM_IME_SELECT:
- // TODO:
+ ImeWnd_OnImeSelect(pimeui, wParam, lParam);
break;
case WM_IME_SETCONTEXT: