changeset 2952:0679c7600523

6829180: Removing focused component from a window causes a JVM crash for JDK7b50+ on WinXP/Vista Summary: access pData on the toolkit thread Reviewed-by: art, anthony, naoto
author dcherepanov
date Fri, 05 Jun 2009 17:30:05 +0400
parents 08bcd34c5e50
children d8c81312ac1c
files jdk/src/windows/native/sun/windows/awt_Component.cpp jdk/src/windows/native/sun/windows/awt_InputMethod.cpp jdk/src/windows/native/sun/windows/awt_Toolkit.cpp jdk/src/windows/native/sun/windows/awt_Toolkit.h jdk/src/windows/native/sun/windows/awtmsg.h
diffstat 5 files changed, 125 insertions(+), 46 deletions(-) [+]
line wrap: on
line diff
--- a/jdk/src/windows/native/sun/windows/awt_Component.cpp	Thu Jun 04 15:18:46 2009 +0400
+++ b/jdk/src/windows/native/sun/windows/awt_Component.cpp	Fri Jun 05 17:30:05 2009 +0400
@@ -1254,6 +1254,8 @@
         WIN_MSG(WM_AWT_CREATECONTEXT)
         WIN_MSG(WM_AWT_DESTROYCONTEXT)
         WIN_MSG(WM_AWT_ASSOCIATECONTEXT)
+        WIN_MSG(WM_AWT_GET_DEFAULT_IME_HANDLER)
+        WIN_MSG(WM_AWT_HANDLE_NATIVE_IME_EVENT)
         WIN_MSG(WM_AWT_PRE_KEYDOWN)
         WIN_MSG(WM_AWT_PRE_KEYUP)
         WIN_MSG(WM_AWT_PRE_SYSKEYDOWN)
--- a/jdk/src/windows/native/sun/windows/awt_InputMethod.cpp	Thu Jun 04 15:18:46 2009 +0400
+++ b/jdk/src/windows/native/sun/windows/awt_InputMethod.cpp	Fri Jun 05 17:30:05 2009 +0400
@@ -91,16 +91,19 @@
 {
     TRY;
 
-    //get C++ Class of Focused Component
-    if (peer == 0)      return;
-    AwtComponent* p = (AwtComponent*)JNI_GET_PDATA(peer);
-    if (p == 0)         return;
+    jobject selfGlobalRef = env->NewGlobalRef(self);
+    jobject peerGlobalRef = env->NewGlobalRef(peer);
 
-    p->SetInputMethod(self, useNativeCompWindow);
+    EnableNativeIMEStruct *enis = new EnableNativeIMEStruct;
 
-    // use special message to call ImmAssociateContext() in main thread.
+    enis->self = selfGlobalRef;
+    enis->peer = peerGlobalRef;
+    enis->context = context;
+    enis->useNativeCompWindow = useNativeCompWindow;
+
     AwtToolkit::GetInstance().SendMessage(WM_AWT_ASSOCIATECONTEXT,
-                                          reinterpret_cast<WPARAM>(p->GetHWnd()), context);
+                                          reinterpret_cast<WPARAM>(enis), (LPARAM)0);
+    // global refs are deleted in message handler
 
     CATCH_BAD_ALLOC;
 }
@@ -116,16 +119,18 @@
 {
     TRY_NO_VERIFY;
 
-    //get C++ Class of Focused Component
-    if (peer == 0)      return;
-    AwtComponent* p = (AwtComponent*)JNI_GET_PDATA(peer);
-    if (p == 0)         return;
+    jobject peerGlobalRef = env->NewGlobalRef(peer);
+    // self reference is not used
 
-    p->SetInputMethod(NULL, TRUE);
+    EnableNativeIMEStruct *enis = new EnableNativeIMEStruct;
+    enis->self = NULL;
+    enis->peer = peerGlobalRef;
+    enis->context = NULL;
+    enis->useNativeCompWindow = JNI_TRUE;
 
-    // use special message to call ImmAssociateContext() in main thread.
     AwtToolkit::GetInstance().SendMessage(WM_AWT_ASSOCIATECONTEXT,
-                                          reinterpret_cast<WPARAM>(p->GetHWnd()), NULL);
+                                          reinterpret_cast<WPARAM>(enis), (LPARAM)0);
+    // global refs are deleted in message handler
 
     CATCH_BAD_ALLOC;
 }
@@ -167,23 +172,14 @@
     if (id >= java_awt_event_InputMethodEvent_INPUT_METHOD_FIRST &&
         id <= java_awt_event_InputMethodEvent_INPUT_METHOD_LAST)
     {
-        long modifiers = p->GetJavaModifiers();
-        if (msg.message==WM_CHAR || msg.message==WM_SYSCHAR) {
-            WCHAR unicodeChar = L'\0';
-            unicodeChar = (WCHAR)msg.wParam;
-            p->SendKeyEvent(java_awt_event_KeyEvent_KEY_TYPED,
-                            0, //to be fixed nowMillis(),
-                            java_awt_event_KeyEvent_CHAR_UNDEFINED,
-                            unicodeChar,
-                            modifiers,
-                            java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN, (jlong)0,
-                            &msg);
-        } else {
-            MSG* pCopiedMsg = new MSG;
-            *pCopiedMsg = msg;
-            p->SendMessage(WM_AWT_HANDLE_EVENT, (WPARAM) FALSE,
-                        (LPARAM) pCopiedMsg);
-        }
+        jobject peerGlobalRef = env->NewGlobalRef(peer);
+
+        // use special message to access pData on the toolkit thread
+        AwtToolkit::GetInstance().SendMessage(WM_AWT_HANDLE_NATIVE_IME_EVENT,
+                                              reinterpret_cast<WPARAM>(peerGlobalRef),
+                                              reinterpret_cast<LPARAM>(&msg));
+        // global ref is deleted in message handler
+
         (env)->SetBooleanField(event, AwtAWTEvent::consumedID, JNI_TRUE);
     }
 
@@ -373,22 +369,27 @@
        Windows system creates a default input method window for the
        toolkit thread.
     */
-    HWND hwndIME = AwtToolkit::GetInstance().GetInputMethodWindow();
-    if (hwndIME == NULL) {
-        if (peer == NULL) {
-            return;
+
+    HWND defaultIMEHandler = AwtToolkit::GetInstance().GetInputMethodWindow();
+
+    if (defaultIMEHandler == NULL)
+    {
+        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,
+                                          reinterpret_cast<WPARAM>(peerGlobalRef), 0);
+        // global ref is deleted in message handler
+
+        if (res == TRUE) {
+            defaultIMEHandler = AwtToolkit::GetInstance().GetInputMethodWindow();
         }
-
-        AwtComponent* p = (AwtComponent*)JNI_GET_PDATA(peer);
-        if (p == NULL || (hwndIME = ImmGetDefaultIMEWnd(p->GetHWnd())) == NULL) {
-            return;
-        }
-
-        AwtToolkit::GetInstance().SetInputMethodWindow(hwndIME);
     }
 
-    ::SendMessage(hwndIME, WM_IME_CONTROL,
-                  visible ? IMC_OPENSTATUSWINDOW : IMC_CLOSESTATUSWINDOW, 0);
+    if (defaultIMEHandler != NULL) {
+        ::SendMessage(defaultIMEHandler, WM_IME_CONTROL,
+                      visible ? IMC_OPENSTATUSWINDOW : IMC_CLOSESTATUSWINDOW, 0);
+    }
 }
 
 /*
@@ -417,6 +418,7 @@
     // use special message to open candidate window in main thread.
     AwtToolkit::GetInstance().SendMessage(WM_AWT_OPENCANDIDATEWINDOW,
                                           (WPARAM)peerGlobalRef, MAKELONG(x, y));
+    // global ref is deleted in message handler
 
     CATCH_BAD_ALLOC;
 }
--- a/jdk/src/windows/native/sun/windows/awt_Toolkit.cpp	Thu Jun 04 15:18:46 2009 +0400
+++ b/jdk/src/windows/native/sun/windows/awt_Toolkit.cpp	Fri Jun 05 17:30:05 2009 +0400
@@ -804,8 +804,73 @@
           return 0;
       }
       case WM_AWT_ASSOCIATECONTEXT: {
-          AwtComponent *p = AwtComponent::GetComponent((HWND)wParam);
-          p->ImmAssociateContext((HIMC)lParam);
+          EnableNativeIMEStruct *data = (EnableNativeIMEStruct*)wParam;
+
+          jobject peer = data->peer;
+          jobject self = data->self;
+          jint context = data->context;
+          jboolean useNativeCompWindow = data->useNativeCompWindow;
+
+          AwtComponent* comp = (AwtComponent*)JNI_GET_PDATA(peer);
+          if (comp != NULL)
+          {
+              comp->SetInputMethod(self, useNativeCompWindow);
+              comp->ImmAssociateContext((HIMC)context);
+          }
+
+          if (peer != NULL) {
+              env->DeleteGlobalRef(peer);
+          }
+          if (self != NULL) {
+              env->DeleteGlobalRef(self);
+          }
+
+          delete data;
+          return 0;
+      }
+      case WM_AWT_GET_DEFAULT_IME_HANDLER: {
+          LRESULT ret = (LRESULT)FALSE;
+          jobject peer = (jobject)wParam;
+
+          AwtComponent* comp = (AwtComponent*)JNI_GET_PDATA(peer);
+          if (comp != NULL) {
+              HWND defaultIMEHandler = ImmGetDefaultIMEWnd(comp->GetHWnd());
+              if (defaultIMEHandler != NULL) {
+                  AwtToolkit::GetInstance().SetInputMethodWindow(defaultIMEHandler);
+                  ret = (LRESULT)TRUE;
+              }
+          }
+
+          if (peer != NULL) {
+              env->DeleteGlobalRef(peer);
+          }
+          return ret;
+      }
+      case WM_AWT_HANDLE_NATIVE_IME_EVENT: {
+          jobject peer = (jobject)wParam;
+          AwtComponent* comp = (AwtComponent*)JNI_GET_PDATA(peer);
+          MSG* msg = (MSG*)lParam;
+
+          long modifiers = comp->GetJavaModifiers();
+          if ((comp != NULL) && (msg->message==WM_CHAR || msg->message==WM_SYSCHAR)) {
+              WCHAR unicodeChar = (WCHAR)msg->wParam;
+              comp->SendKeyEvent(java_awt_event_KeyEvent_KEY_TYPED,
+                                 0, //to be fixed nowMillis(),
+                                 java_awt_event_KeyEvent_CHAR_UNDEFINED,
+                                 unicodeChar,
+                                 modifiers,
+                                 java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN, (jlong)0,
+                                 msg);
+          } else if (comp != NULL) {
+              MSG* pCopiedMsg = new MSG;
+              *pCopiedMsg = *msg;
+              comp->SendMessage(WM_AWT_HANDLE_EVENT, (WPARAM) FALSE,
+                                (LPARAM) pCopiedMsg);
+          }
+
+          if (peer != NULL) {
+              env->DeleteGlobalRef(peer);
+          }
           return 0;
       }
       case WM_AWT_ENDCOMPOSITION: {
--- a/jdk/src/windows/native/sun/windows/awt_Toolkit.h	Thu Jun 04 15:18:46 2009 +0400
+++ b/jdk/src/windows/native/sun/windows/awt_Toolkit.h	Fri Jun 05 17:30:05 2009 +0400
@@ -61,6 +61,14 @@
 typedef VOID (CALLBACK* IDLEPROC)(VOID);
 typedef BOOL (CALLBACK* PEEKMESSAGEPROC)(MSG&);
 
+// Struct for _WInputMethod_enable|disableNativeIME method
+struct EnableNativeIMEStruct {
+    jobject self;
+    jobject peer;
+    jint context;
+    jboolean useNativeCompWindow;
+};
+
 /*
  * class JNILocalFrame
  * Push/PopLocalFrame helper
--- a/jdk/src/windows/native/sun/windows/awtmsg.h	Thu Jun 04 15:18:46 2009 +0400
+++ b/jdk/src/windows/native/sun/windows/awtmsg.h	Fri Jun 05 17:30:05 2009 +0400
@@ -208,6 +208,8 @@
     WM_AWT_CREATECONTEXT,
     WM_AWT_DESTROYCONTEXT,
     WM_AWT_ASSOCIATECONTEXT,
+    WM_AWT_GET_DEFAULT_IME_HANDLER,
+    WM_AWT_HANDLE_NATIVE_IME_EVENT,
     WM_AWT_PRE_KEYDOWN,
     WM_AWT_PRE_KEYUP,
     WM_AWT_PRE_SYSKEYDOWN,