[IMM32] Improve ImmSimulateHotKey (#3858)
authorKatayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
Sat, 31 Jul 2021 06:56:11 +0000 (15:56 +0900)
committerGitHub <noreply@github.com>
Sat, 31 Jul 2021 06:56:11 +0000 (15:56 +0900)
- Improve ImmSimulateHotKey function.
- Modify IMEDPI structure.
CORE-11700

dll/win32/imm32/imm.c
win32ss/include/ntuser.h

index 5e655e6..9c7aa19 100644 (file)
@@ -48,6 +48,10 @@ WINE_DEFAULT_DEBUG_CHANNEL(imm);
 #define IMM_INIT_MAGIC 0x19650412
 #define IMM_INVALID_CANDFORM ULONG_MAX
 
+#define LANGID_CHINESE_SIMPLIFIED MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED)
+#define LANGID_CHINESE_TRADITIONAL MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL)
+#define LANGID_JAPANESE MAKELANGID(LANG_JAPANESE, SUBLANG_DEFAULT)
+
 #define REGKEY_KEYBOARD_LAYOUTS \
     L"System\\CurrentControlSet\\Control\\Keyboard Layouts"
 #define REGKEY_IMM \
@@ -1205,6 +1209,234 @@ static DWORD APIENTRY Imm32AllocAndBuildHimcList(DWORD dwThreadId, HIMC **pphLis
 #undef MAX_RETRY
 }
 
+static BOOL APIENTRY Imm32ImeNonImeToggle(HIMC hIMC, HKL hKL, HWND hWnd, LANGID LangID)
+{
+    LPINPUTCONTEXT pIC;
+    BOOL fOpen;
+
+    if (hWnd != NULL)
+        return FALSE;
+
+    if (!IS_IME_HKL(hKL) || LOWORD(hKL) != LangID)
+    {
+        FIXME("We have to do something here\n");
+        return TRUE;
+    }
+
+    pIC = ImmLockIMC(hIMC);
+    if (pIC == NULL)
+        return TRUE;
+
+    fOpen = pIC->fOpen;
+    ImmUnlockIMC(hIMC);
+
+    if (!fOpen)
+    {
+        ImmSetOpenStatus(hIMC, TRUE);
+        return TRUE;
+    }
+
+    FIXME("We have to do something here\n");
+    return TRUE;
+}
+
+static BOOL APIENTRY Imm32CShapeToggle(HIMC hIMC, HKL hKL, HWND hWnd)
+{
+    LPINPUTCONTEXT pIC;
+    BOOL fOpen;
+    DWORD dwConversion, dwSentence;
+
+    if (hWnd == NULL || !IS_IME_HKL(hKL))
+        return FALSE;
+
+    pIC = ImmLockIMC(hIMC);
+    if (pIC == NULL)
+        return TRUE;
+
+    fOpen = pIC->fOpen;
+    if (fOpen)
+    {
+        dwConversion = (pIC->fdwConversion ^ IME_CMODE_FULLSHAPE);
+        dwSentence = pIC->fdwSentence;
+    }
+
+    ImmUnlockIMC(hIMC);
+
+    if (fOpen)
+        ImmSetConversionStatus(hIMC, dwConversion, dwSentence);
+    else
+        ImmSetOpenStatus(hIMC, TRUE);
+
+    return TRUE;
+}
+
+static BOOL APIENTRY Imm32CSymbolToggle(HIMC hIMC, HKL hKL, HWND hWnd)
+{
+    LPINPUTCONTEXT pIC;
+    BOOL fOpen;
+    DWORD dwConversion, dwSentence;
+
+    if (hWnd == NULL || !IS_IME_HKL(hKL))
+        return FALSE;
+
+    pIC = ImmLockIMC(hIMC);
+    if (pIC == NULL)
+        return TRUE;
+
+    fOpen = pIC->fOpen;
+    if (fOpen)
+    {
+        dwConversion = (pIC->fdwConversion ^ IME_CMODE_SYMBOL);
+        dwSentence = pIC->fdwSentence;
+    }
+
+    ImmUnlockIMC(hIMC);
+
+    if (fOpen)
+        ImmSetConversionStatus(hIMC, dwConversion, dwSentence);
+    else
+        ImmSetOpenStatus(hIMC, TRUE);
+
+    return TRUE;
+}
+
+static BOOL APIENTRY Imm32JCloseOpen(HIMC hIMC, HKL hKL, HWND hWnd)
+{
+    BOOL fOpen;
+
+    if (ImmIsIME(hKL) && LOWORD(hKL) == LANGID_JAPANESE)
+    {
+        fOpen = ImmGetOpenStatus(hIMC);
+        ImmSetOpenStatus(hIMC, !fOpen);
+        return TRUE;
+    }
+
+    FIXME("We have to do something here\n");
+    return TRUE;
+}
+
+static BOOL APIENTRY Imm32KShapeToggle(HIMC hIMC)
+{
+    LPINPUTCONTEXT pIC;
+    DWORD dwConversion, dwSentence;
+
+    pIC = ImmLockIMC(hIMC);
+    if (pIC == NULL)
+        return FALSE;
+
+    dwConversion = (pIC->fdwConversion ^ IME_CMODE_FULLSHAPE);
+    dwSentence = pIC->fdwSentence;
+    ImmSetConversionStatus(hIMC, dwConversion, dwSentence);
+
+    if (pIC->fdwConversion & (IME_CMODE_FULLSHAPE | IME_CMODE_NATIVE))
+        ImmSetOpenStatus(hIMC, TRUE);
+    else
+        ImmSetOpenStatus(hIMC, FALSE);
+
+    ImmUnlockIMC(hIMC);
+    return TRUE;
+}
+
+static BOOL APIENTRY Imm32KHanjaConvert(HIMC hIMC)
+{
+    LPINPUTCONTEXT pIC;
+    DWORD dwConversion, dwSentence;
+
+    pIC = ImmLockIMC(hIMC);
+    if (!pIC)
+        return FALSE;
+
+    dwConversion = (pIC->fdwConversion ^ IME_CMODE_HANJACONVERT);
+    dwSentence = pIC->fdwSentence;
+    ImmUnlockIMC(hIMC);
+
+    ImmSetConversionStatus(hIMC, dwConversion, dwSentence);
+    return TRUE;
+}
+
+static BOOL APIENTRY Imm32KEnglish(HIMC hIMC)
+{
+    LPINPUTCONTEXT pIC;
+    DWORD dwConversion, dwSentence;
+    BOOL fOpen;
+
+    pIC = ImmLockIMC(hIMC);
+    if (pIC == NULL)
+        return FALSE;
+
+    dwConversion = (pIC->fdwConversion ^ IME_CMODE_NATIVE);
+    dwSentence = pIC->fdwSentence;
+    ImmSetConversionStatus(hIMC, dwConversion, dwSentence);
+
+    fOpen = ((pIC->fdwConversion & (IME_CMODE_FULLSHAPE | IME_CMODE_NATIVE)) != 0);
+    ImmSetOpenStatus(hIMC, fOpen);
+
+    ImmUnlockIMC(hIMC);
+    return TRUE;
+}
+
+static BOOL APIENTRY Imm32ProcessHotKey(HWND hWnd, HIMC hIMC, HKL hKL, DWORD dwHotKeyID)
+{
+    DWORD dwImeThreadId, dwThreadId;
+    PIMEDPI pImeDpi;
+    BOOL ret;
+
+    if (hIMC)
+    {
+        dwImeThreadId = Imm32QueryInputContext(hIMC, 1);
+        dwThreadId = GetCurrentThreadId();
+        if (dwImeThreadId != dwThreadId)
+            return FALSE;
+    }
+
+    switch (dwHotKeyID)
+    {
+        case IME_CHOTKEY_IME_NONIME_TOGGLE:
+            return Imm32ImeNonImeToggle(hIMC, hKL, hWnd, LANGID_CHINESE_SIMPLIFIED);
+
+        case IME_CHOTKEY_SHAPE_TOGGLE:
+            return Imm32CShapeToggle(hIMC, hKL, hWnd);
+
+        case IME_CHOTKEY_SYMBOL_TOGGLE:
+            return Imm32CSymbolToggle(hIMC, hKL, hWnd);
+
+        case IME_JHOTKEY_CLOSE_OPEN:
+            return Imm32JCloseOpen(hIMC, hKL, hWnd);
+
+        case IME_KHOTKEY_SHAPE_TOGGLE:
+            return Imm32KShapeToggle(hIMC);
+
+        case IME_KHOTKEY_HANJACONVERT:
+            return Imm32KHanjaConvert(hIMC);
+
+        case IME_KHOTKEY_ENGLISH:
+            return Imm32KEnglish(hIMC);
+
+        case IME_THOTKEY_IME_NONIME_TOGGLE:
+            return Imm32ImeNonImeToggle(hIMC, hKL, hWnd, LANGID_CHINESE_TRADITIONAL);
+
+        case IME_THOTKEY_SHAPE_TOGGLE:
+            return Imm32CShapeToggle(hIMC, hKL, hWnd);
+
+        case IME_THOTKEY_SYMBOL_TOGGLE:
+            return Imm32CSymbolToggle(hIMC, hKL, hWnd);
+
+        default:
+            break;
+    }
+
+    if (dwHotKeyID < IME_HOTKEY_PRIVATE_FIRST || IME_HOTKEY_PRIVATE_LAST < dwHotKeyID)
+        return FALSE;
+
+    pImeDpi = ImmLockImeDpi(hKL);
+    if (pImeDpi == NULL)
+        return FALSE;
+
+    ret = (BOOL)pImeDpi->ImeEscape(hIMC, IME_ESC_PRIVATE_HOTKEY, &dwHotKeyID);
+    ImmUnlockImeDpi(pImeDpi);
+    return ret;
+}
+
 PCLIENTIMC WINAPI ImmLockClientImc(HIMC hImc)
 {
     PCLIENTIMC pClientImc;
@@ -3288,9 +3520,19 @@ BOOL WINAPI ImmShowSoftKeyboard(HWND hSoftWnd, int nCmdShow)
  */
 BOOL WINAPI ImmSimulateHotKey(HWND hWnd, DWORD dwHotKeyID)
 {
-  FIXME("(%p, %d): stub\n", hWnd, dwHotKeyID);
-  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-  return FALSE;
+    HIMC hIMC;
+    DWORD dwThreadId;
+    HKL hKL;
+    BOOL ret;
+
+    TRACE("ImmSimulateHotKey(%p, 0x%lX)\n", hWnd, dwHotKeyID);
+
+    hIMC = ImmGetContext(hWnd);
+    dwThreadId = GetWindowThreadProcessId(hWnd, NULL);
+    hKL = GetKeyboardLayout(dwThreadId);
+    ret = Imm32ProcessHotKey(hWnd, hIMC, hKL, dwHotKeyID);
+    ImmReleaseContext(hWnd, hIMC);
+    return ret;
 }
 
 /***********************************************************************
index 8182efe..024e941 100644 (file)
@@ -1213,6 +1213,7 @@ typedef struct _IMEWND
 } IMEWND, *PIMEWND;
 
 typedef BOOL (WINAPI *FN_ImeDestroy)(UINT uReserved);
+typedef LRESULT (WINAPI *FN_ImeEscape)(HIMC hIMC, UINT uEscape, LPVOID lpData);
 typedef BOOL (WINAPI *FN_NotifyIME)(HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue);
 
 typedef struct IMEDPI /* unconfirmed */
@@ -1227,7 +1228,8 @@ typedef struct IMEDPI /* unconfirmed */
     DWORD          dwFlags;
     DWORD          dwUnknown3[7];
     FN_ImeDestroy  ImeDestroy;
-    DWORD          dwUnknown4[5];
+    FN_ImeEscape   ImeEscape;
+    DWORD          dwUnknown4[4];
     FN_NotifyIME   NotifyIME;
     /* ... */
 } IMEDPI, *PIMEDPI;
@@ -1239,6 +1241,7 @@ C_ASSERT(offsetof(IMEDPI, hKL) == 0x8);
 C_ASSERT(offsetof(IMEDPI, cLockObj) == 0x4c);
 C_ASSERT(offsetof(IMEDPI, dwFlags) == 0x50);
 C_ASSERT(offsetof(IMEDPI, ImeDestroy) == 0x70);
+C_ASSERT(offsetof(IMEDPI, ImeEscape) == 0x74);
 C_ASSERT(offsetof(IMEDPI, NotifyIME) == 0x88);
 #endif