--- old/src/java.desktop/windows/native/libawt/windows/awt_InputMethod.cpp 2020-08-17 10:24:41.000000000 +0100 +++ new/src/java.desktop/windows/native/libawt/windows/awt_InputMethod.cpp 2020-08-17 10:24:41.000000000 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -57,7 +57,7 @@ TRY; // use special message to call ImmCreateContext() in main thread. - return (jint)AwtToolkit::GetInstance().SendMessage(WM_AWT_CREATECONTEXT); + return (jint)AwtToolkit::GetInstance().InvokeInputMethodFunction(WM_AWT_CREATECONTEXT); CATCH_BAD_ALLOC_RET(0); } @@ -74,7 +74,7 @@ TRY_NO_VERIFY; // use special message to call ImmDestroyContext() in main thread. - AwtToolkit::GetInstance().SendMessage(WM_AWT_DESTROYCONTEXT, context, 0); + AwtToolkit::GetInstance().InvokeInputMethodFunction(WM_AWT_DESTROYCONTEXT, context, 0); CATCH_BAD_ALLOC; } @@ -101,7 +101,7 @@ enis->context = context; enis->useNativeCompWindow = useNativeCompWindow; - AwtToolkit::GetInstance().SendMessage(WM_AWT_ASSOCIATECONTEXT, + AwtToolkit::GetInstance().InvokeInputMethodFunction(WM_AWT_ASSOCIATECONTEXT, reinterpret_cast(enis), (LPARAM)0); // global refs are deleted in message handler @@ -128,7 +128,7 @@ enis->context = NULL; enis->useNativeCompWindow = JNI_TRUE; - AwtToolkit::GetInstance().SendMessage(WM_AWT_ASSOCIATECONTEXT, + AwtToolkit::GetInstance().InvokeInputMethodFunction(WM_AWT_ASSOCIATECONTEXT, reinterpret_cast(enis), (LPARAM)0); // global refs are deleted in message handler @@ -175,7 +175,7 @@ jobject peerGlobalRef = env->NewGlobalRef(peer); // use special message to access pData on the toolkit thread - AwtToolkit::GetInstance().SendMessage(WM_AWT_HANDLE_NATIVE_IME_EVENT, + AwtToolkit::GetInstance().InvokeInputMethodFunction(WM_AWT_HANDLE_NATIVE_IME_EVENT, reinterpret_cast(peerGlobalRef), reinterpret_cast(&msg)); // global ref is deleted in message handler @@ -205,7 +205,7 @@ // 10/29/98 - Changed to commit it according to the flag. // use special message to call ImmNotifyIME() in main thread. - AwtToolkit::GetInstance().SendMessage(WM_AWT_ENDCOMPOSITION, context, + AwtToolkit::GetInstance().InvokeInputMethodFunction(WM_AWT_ENDCOMPOSITION, context, (LPARAM)(flag != sun_awt_windows_WInputMethod_DISCARD_INPUT)); CATCH_BAD_ALLOC; @@ -222,7 +222,7 @@ TRY; // use special message to call ImmSetConversionStatus() in main thread. - AwtToolkit::GetInstance().SendMessage(WM_AWT_SETCONVERSIONSTATUS, + AwtToolkit::GetInstance().InvokeInputMethodFunction(WM_AWT_SETCONVERSIONSTATUS, context, MAKELPARAM((WORD)request, (WORD)0)); @@ -240,7 +240,7 @@ TRY; // use special message to call ImmSetConversionStatus() in main thread. - return (jint) AwtToolkit::GetInstance().SendMessage( + return (jint) AwtToolkit::GetInstance().InvokeInputMethodFunction( WM_AWT_GETCONVERSIONSTATUS, context, 0); CATCH_BAD_ALLOC_RET(0); @@ -257,7 +257,7 @@ TRY; // use special message to call ImmSetConversionStatus() in main thread. - AwtToolkit::GetInstance().SendMessage(WM_AWT_SETOPENSTATUS, + AwtToolkit::GetInstance().InvokeInputMethodFunction(WM_AWT_SETOPENSTATUS, context, flag); CATCH_BAD_ALLOC; @@ -274,7 +274,7 @@ TRY; // use special message to call ImmSetConversionStatus() in main thread. - return (jboolean)(AwtToolkit::GetInstance().SendMessage( + return (jboolean)(AwtToolkit::GetInstance().InvokeInputMethodFunction( WM_AWT_GETOPENSTATUS, context, 0)); CATCH_BAD_ALLOC_RET(0); @@ -353,7 +353,7 @@ if (supported != NULL) { if (strcmp(supported, requested) == 0) { // use special message to call ActivateKeyboardLayout() in main thread. - if (AwtToolkit::GetInstance().SendMessage(WM_AWT_ACTIVATEKEYBOARDLAYOUT, (WPARAM)onActivate, (LPARAM)hKLList[i])) { + if (AwtToolkit::GetInstance().InvokeInputMethodFunction(WM_AWT_ACTIVATEKEYBOARDLAYOUT, (WPARAM)onActivate, (LPARAM)hKLList[i])) { //also need to change the same keyboard layout for the Java AWT-EventQueue thread AwtToolkit::activateKeyboardLayout(hKLList[i]); retValue = JNI_TRUE; @@ -392,7 +392,7 @@ jobject peerGlobalRef = env->NewGlobalRef(peer); // use special message to access pData on the toolkit thread - LRESULT res = AwtToolkit::GetInstance().SendMessage(WM_AWT_GET_DEFAULT_IME_HANDLER, + LRESULT res = AwtToolkit::GetInstance().InvokeInputMethodFunction(WM_AWT_GET_DEFAULT_IME_HANDLER, reinterpret_cast(peerGlobalRef), 0); // global ref is deleted in message handler @@ -431,7 +431,7 @@ // See CR 4805862, AwtToolkit::WndProc // use special message to open candidate window in main thread. - AwtToolkit::GetInstance().SendMessage(WM_AWT_OPENCANDIDATEWINDOW, + AwtToolkit::GetInstance().InvokeInputMethodFunction(WM_AWT_OPENCANDIDATEWINDOW, (WPARAM)peerGlobalRef, MAKELONG(x, y)); // global ref is deleted in message handler --- old/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp 2020-08-17 10:24:43.000000000 +0100 +++ new/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp 2020-08-17 10:24:42.000000000 +0100 @@ -343,6 +343,7 @@ ::GetKeyboardState(m_lastKeyboardState); m_waitEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL); + m_inputMethodWaitEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL); isInDoDragDropLoop = FALSE; eventNumber = 0; } @@ -777,6 +778,7 @@ delete tk.m_cmdIDs; ::CloseHandle(m_waitEvent); + ::CloseHandle(m_inputMethodWaitEvent); tk.m_isDisposed = TRUE; @@ -1087,11 +1089,17 @@ // it returs with no error. (This restriction is not documented) // So we must use thse messages to call these APIs in main thread. case WM_AWT_CREATECONTEXT: { - return reinterpret_cast( + AwtToolkit& tk = AwtToolkit::GetInstance(); + tk.m_inputMethodData = reinterpret_cast( reinterpret_cast(ImmCreateContext())); + ::SetEvent(tk.m_inputMethodWaitEvent); + return tk.m_inputMethodData; } case WM_AWT_DESTROYCONTEXT: { ImmDestroyContext((HIMC)wParam); + AwtToolkit& tk = AwtToolkit::GetInstance(); + tk.m_inputMethodData = 0; + ::SetEvent(tk.m_inputMethodWaitEvent); return 0; } case WM_AWT_ASSOCIATECONTEXT: { @@ -1117,17 +1125,21 @@ } delete data; + AwtToolkit& tk = AwtToolkit::GetInstance(); + tk.m_inputMethodData = 0; + ::SetEvent(tk.m_inputMethodWaitEvent); return 0; } case WM_AWT_GET_DEFAULT_IME_HANDLER: { LRESULT ret = (LRESULT)FALSE; jobject peer = (jobject)wParam; + AwtToolkit& tk = AwtToolkit::GetInstance(); AwtComponent* comp = (AwtComponent*)JNI_GET_PDATA(peer); if (comp != NULL) { HWND defaultIMEHandler = ImmGetDefaultIMEWnd(comp->GetHWnd()); if (defaultIMEHandler != NULL) { - AwtToolkit::GetInstance().SetInputMethodWindow(defaultIMEHandler); + tk.SetInputMethodWindow(defaultIMEHandler); ret = (LRESULT)TRUE; } } @@ -1135,6 +1147,8 @@ if (peer != NULL) { env->DeleteGlobalRef(peer); } + tk.m_inputMethodData = ret; + ::SetEvent(tk.m_inputMethodWaitEvent); return ret; } case WM_AWT_HANDLE_NATIVE_IME_EVENT: { @@ -1162,6 +1176,9 @@ if (peer != NULL) { env->DeleteGlobalRef(peer); } + AwtToolkit& tk = AwtToolkit::GetInstance(); + tk.m_inputMethodData = 0; + ::SetEvent(tk.m_inputMethodWaitEvent); return 0; } case WM_AWT_ENDCOMPOSITION: { @@ -1170,6 +1187,9 @@ Changed to commit it according to the flag 10/29/98*/ ImmNotifyIME((HIMC)wParam, NI_COMPOSITIONSTR, (lParam ? CPS_COMPLETE : CPS_CANCEL), 0); + AwtToolkit& tk = AwtToolkit::GetInstance(); + tk.m_inputMethodData = 0; + ::SetEvent(tk.m_inputMethodWaitEvent); return 0; } case WM_AWT_SETCONVERSIONSTATUS: { @@ -1177,12 +1197,18 @@ DWORD smode; ImmGetConversionStatus((HIMC)wParam, (LPDWORD)&cmode, (LPDWORD)&smode); ImmSetConversionStatus((HIMC)wParam, (DWORD)LOWORD(lParam), smode); + AwtToolkit& tk = AwtToolkit::GetInstance(); + tk.m_inputMethodData = 0; + ::SetEvent(tk.m_inputMethodWaitEvent); return 0; } case WM_AWT_GETCONVERSIONSTATUS: { DWORD cmode; DWORD smode; ImmGetConversionStatus((HIMC)wParam, (LPDWORD)&cmode, (LPDWORD)&smode); + AwtToolkit& tk = AwtToolkit::GetInstance(); + tk.m_inputMethodData = cmode; + ::SetEvent(tk.m_inputMethodWaitEvent); return cmode; } case WM_AWT_ACTIVATEKEYBOARDLAYOUT: { @@ -1207,7 +1233,10 @@ ::ToAscii(VK_SPACE, ::MapVirtualKey(VK_SPACE, 0), keyboardState, &ignored, 0); - return (LRESULT)activateKeyboardLayout((HKL)lParam); + AwtToolkit& tk = AwtToolkit::GetInstance(); + tk.m_inputMethodData = (LRESULT)activateKeyboardLayout((HKL)lParam); + ::SetEvent(tk.m_inputMethodWaitEvent); + return tk.m_inputMethodData; } case WM_AWT_OPENCANDIDATEWINDOW: { jobject peerObject = (jobject)wParam; @@ -1217,6 +1246,9 @@ // instead of LOWORD and HIWORD p->OpenCandidateWindow(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); env->DeleteGlobalRef(peerObject); + AwtToolkit& tk = AwtToolkit::GetInstance(); + tk.m_inputMethodData = 0; + ::SetEvent(tk.m_inputMethodWaitEvent); return 0; } @@ -1238,10 +1270,16 @@ case WM_AWT_SETOPENSTATUS: { ImmSetOpenStatus((HIMC)wParam, (BOOL)lParam); + AwtToolkit& tk = AwtToolkit::GetInstance(); + tk.m_inputMethodData = 0; + ::SetEvent(tk.m_inputMethodWaitEvent); return 0; } case WM_AWT_GETOPENSTATUS: { - return (DWORD)ImmGetOpenStatus((HIMC)wParam); + AwtToolkit& tk = AwtToolkit::GetInstance(); + tk.m_inputMethodData = (DWORD)ImmGetOpenStatus((HIMC)wParam); + ::SetEvent(tk.m_inputMethodWaitEvent); + return tk.m_inputMethodData; } case WM_DISPLAYCHANGE: { // Reinitialize screens @@ -3166,3 +3204,21 @@ } return m_pCloseTouchInputHandle(hTouchInput); } + +/* + * The fuction intended for access to an IME API. It posts IME message to the queue and + * waits untill the message processing is completed. + * + * On Windows 10 the IME may process the messages send via SenMessage() from other threads + * when the IME is called by TranslateMessage(). This may cause an reentrancy issue when + * the windows procedure processing the sent message call an IME function and leaves + * the IME functionality in an unexpected state. + * This function avoids reentrancy issue and must be used for sending of all IME messages + * instead of SendMessage(). + */ +LRESULT AwtToolkit::InvokeInputMethodFunction(UINT msg, WPARAM wParam, LPARAM lParam) { + CriticalSection::Lock lock(m_inputMethodLock); + PostMessage(msg, wParam, lParam); + ::WaitForSingleObject(m_inputMethodWaitEvent, INFINITE); + return m_inputMethodData; +} --- old/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.h 2020-08-17 10:24:44.000000000 +0100 +++ new/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.h 2020-08-17 10:24:43.000000000 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -244,6 +244,8 @@ UINT cInputs, PTOUCHINPUT pInputs, int cbSize); BOOL TICloseTouchInputHandle(HTOUCHINPUT hTouchInput); + LRESULT InvokeInputMethodFunction(UINT msg, WPARAM wParam=0, LPARAM lParam=0); + INLINE BOOL localPump() { return m_localPump; } INLINE BOOL VerifyComponents() { return FALSE; } // TODO: Use new DebugHelper class to set this flag INLINE HWND GetHWnd() { return m_toolkitHWnd; } @@ -498,6 +500,10 @@ HMODULE m_dllHandle; /* The module handle. */ CriticalSection m_Sync; + CriticalSection m_inputMethodLock; + + HANDLE m_inputMethodWaitEvent; + LRESULT m_inputMethodData; /* track display changes - used by palette-updating code. This is a workaround for a windows bug that prevents