https://git.reactos.org/?p=reactos.git;a=commitdiff;h=23bb27037d90c3d3c5a8a5441d93d0b922ac14fa

commit 23bb27037d90c3d3c5a8a5441d93d0b922ac14fa
Author:     Katayama Hirofumi MZ <[email protected]>
AuthorDate: Thu Jan 27 21:19:37 2022 +0900
Commit:     GitHub <[email protected]>
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:

Reply via email to