--- a/jdk/src/windows/classes/sun/awt/windows/WComponentPeer.java Mon Sep 26 15:40:05 2011 -0700
+++ b/jdk/src/windows/classes/sun/awt/windows/WComponentPeer.java Tue Sep 27 13:38:29 2011 +0400
@@ -615,6 +615,14 @@
_dispose();
}
+ public void disposeLater() {
+ postEvent(new InvocationEvent(Toolkit.getDefaultToolkit(), new Runnable() {
+ public void run() {
+ dispose();
+ }
+ }));
+ }
+
public synchronized void setForeground(Color c) {
foreground = c;
_setForeground(c.getRGB());
--- a/jdk/src/windows/native/sun/windows/awt_Component.cpp Mon Sep 26 15:40:05 2011 -0700
+++ b/jdk/src/windows/native/sun/windows/awt_Component.cpp Tue Sep 27 13:38:29 2011 +0400
@@ -183,6 +183,7 @@
jmethodID AwtComponent::getLocationOnScreenMID;
jmethodID AwtComponent::replaceSurfaceDataMID;
jmethodID AwtComponent::replaceSurfaceDataLaterMID;
+jmethodID AwtComponent::disposeLaterMID;
HKL AwtComponent::m_hkl = ::GetKeyboardLayout(0);
LANGID AwtComponent::m_idLang = LOWORD(::GetKeyboardLayout(0));
@@ -246,6 +247,7 @@
m_hCursorCache = NULL;
m_bSubclassed = FALSE;
+ m_bPauseDestroy = FALSE;
m_MessagesProcessing = 0;
m_wheelRotationAmount = 0;
@@ -319,6 +321,12 @@
m_brushBackground = NULL;
}
+ if (m_bPauseDestroy) {
+ // AwtComponent::WmNcDestroy could be released now
+ m_bPauseDestroy = FALSE;
+ m_hwnd = NULL;
+ }
+
// The component instance is deleted using AwtObject::Dispose() method
AwtObject::Dispose();
}
@@ -1377,6 +1385,7 @@
case WM_CREATE: mr = WmCreate(); break;
case WM_CLOSE: mr = WmClose(); break;
case WM_DESTROY: mr = WmDestroy(); break;
+ case WM_NCDESTROY: mr = WmNcDestroy(); break;
case WM_ERASEBKGND:
mr = WmEraseBkgnd((HDC)wParam, *(BOOL*)&retValue); break;
@@ -1965,10 +1974,24 @@
*/
MsgRouting AwtComponent::WmDestroy()
{
- // fix for 6259348: we should enter the SyncCall critical section before
- // disposing the native object, that is value 1 of lParam is intended for
- if(m_peerObject != NULL) { // is not being terminating
- AwtToolkit::GetInstance().SendMessage(WM_AWT_DISPOSE, (WPARAM)m_peerObject, (LPARAM)1);
+ return mrConsume;
+}
+
+/*
+ * This message should only be received when a window is destroyed by
+ * Windows, and not Java. It is sent only after child windows were destroyed.
+ */
+MsgRouting AwtComponent::WmNcDestroy()
+{
+ if (m_peerObject != NULL) { // is not being terminating
+ // Stay in this handler until AwtComponent::Dispose is called.
+ m_bPauseDestroy = TRUE;
+
+ JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
+ // Post invocation event for WObjectPeer.dispose to EDT
+ env->CallVoidMethod(m_peerObject, AwtComponent::disposeLaterMID);
+ // Wait until AwtComponent::Dispose is called
+ AwtToolkit::GetInstance().PumpToDestroy(this);
}
return mrConsume;
@@ -6300,6 +6323,7 @@
env->GetMethodID(peerCls, "replaceSurfaceData", "()V");
AwtComponent::replaceSurfaceDataLaterMID =
env->GetMethodID(peerCls, "replaceSurfaceDataLater", "()V");
+ AwtComponent::disposeLaterMID = env->GetMethodID(peerCls, "disposeLater", "()V");
DASSERT(AwtComponent::xID);
DASSERT(AwtComponent::yID);
@@ -6318,6 +6342,8 @@
DASSERT(AwtComponent::getLocationOnScreenMID);
DASSERT(AwtComponent::replaceSurfaceDataMID);
DASSERT(AwtComponent::replaceSurfaceDataLaterMID);
+ DASSERT(AwtComponent::disposeLaterMID);
+
CATCH_BAD_ALLOC;
}
--- a/jdk/src/windows/native/sun/windows/awt_Component.h Mon Sep 26 15:40:05 2011 -0700
+++ b/jdk/src/windows/native/sun/windows/awt_Component.h Tue Sep 27 13:38:29 2011 +0400
@@ -119,6 +119,7 @@
static jmethodID getLocationOnScreenMID;
static jmethodID replaceSurfaceDataMID;
static jmethodID replaceSurfaceDataLaterMID;
+ static jmethodID disposeLaterMID;
static const UINT WmAwtIsComponent;
static jint * masks; //InputEvent mask array
@@ -490,6 +491,7 @@
virtual MsgRouting WmCreate() {return mrDoDefault;}
virtual MsgRouting WmClose() {return mrDoDefault;}
virtual MsgRouting WmDestroy();
+ virtual MsgRouting WmNcDestroy();
virtual MsgRouting WmActivate(UINT nState, BOOL fMinimized, HWND opposite)
{
@@ -711,6 +713,10 @@
return m_MessagesProcessing == 0;
}
+ BOOL IsDestroyPaused() const {
+ return m_bPauseDestroy;
+ }
+
protected:
static AwtComponent* GetComponentImpl(HWND hWnd);
@@ -752,6 +758,7 @@
UINT m_mouseButtonClickAllowed;
BOOL m_bSubclassed;
+ BOOL m_bPauseDestroy;
COLORREF m_colorForeground;
COLORREF m_colorBackground;
--- a/jdk/src/windows/native/sun/windows/awt_Toolkit.cpp Mon Sep 26 15:40:05 2011 -0700
+++ b/jdk/src/windows/native/sun/windows/awt_Toolkit.cpp Tue Sep 27 13:38:29 2011 +0400
@@ -733,26 +733,13 @@
return 0;
}
case WM_AWT_DISPOSE: {
- BOOL canDispose = TRUE;
- CriticalSection &syncCS = AwtToolkit::GetInstance().GetSyncCS();
- int shouldEnterCriticalSection = (int)lParam;
- if (shouldEnterCriticalSection == 1) {
- canDispose = syncCS.TryEnter();
- }
- if (canDispose) {
- if(wParam != NULL) {
- jobject self = (jobject)wParam;
- AwtObject *o = (AwtObject *) JNI_GET_PDATA(self);
- env->DeleteGlobalRef(self);
- if(o != NULL && theAwtObjectList.Remove(o)) {
- o->Dispose();
- }
- if (shouldEnterCriticalSection) {
- syncCS.Leave();
- }
+ if(wParam != NULL) {
+ jobject self = (jobject)wParam;
+ AwtObject *o = (AwtObject *) JNI_GET_PDATA(self);
+ env->DeleteGlobalRef(self);
+ if(o != NULL && theAwtObjectList.Remove(o)) {
+ o->Dispose();
}
- } else {
- AwtToolkit::GetInstance().PostMessage(WM_AWT_DISPOSE, wParam, lParam);
}
return 0;
}
@@ -1340,25 +1327,46 @@
while (!m_breakMessageLoop && (*lpPeekMessageFunc)(msg)) {
foundOne = TRUE;
- if (msg.message == WM_QUIT) {
- m_breakMessageLoop = TRUE;
- m_messageLoopResult = static_cast<UINT>(msg.wParam);
- if (m_messageLoopResult == EXIT_ALL_ENCLOSING_LOOPS)
- ::PostQuitMessage(static_cast<int>(msg.wParam)); // make sure all loops exit
- break;
- }
- else if (msg.message != WM_NULL) {
- /*
- * The AWT in standalone mode (that is, dynamically loaded from the
- * Java VM) doesn't have any translation tables to worry about, so
- * TranslateAccelerator isn't called.
- */
-
- ::TranslateMessage(&msg);
- ::DispatchMessage(&msg);
+ ProcessMsg(msg);
+ }
+ return foundOne;
+}
+
+void AwtToolkit::PumpToDestroy(class AwtComponent* p)
+{
+ MSG msg;
+
+ DASSERT(AwtToolkit::PrimaryIdleFunc != NULL);
+ DASSERT(AwtToolkit::CommonPeekMessageFunc != NULL);
+
+ while (p->IsDestroyPaused() && !m_breakMessageLoop) {
+
+ PrimaryIdleFunc();
+
+ while (p->IsDestroyPaused() && !m_breakMessageLoop && CommonPeekMessageFunc(msg)) {
+ ProcessMsg(msg);
}
}
- return foundOne;
+}
+
+void AwtToolkit::ProcessMsg(MSG& msg)
+{
+ if (msg.message == WM_QUIT) {
+ m_breakMessageLoop = TRUE;
+ m_messageLoopResult = static_cast<UINT>(msg.wParam);
+ if (m_messageLoopResult == EXIT_ALL_ENCLOSING_LOOPS)
+ ::PostQuitMessage(static_cast<int>(msg.wParam)); // make sure all loops exit
+ }
+ else if (msg.message != WM_NULL) {
+ /*
+ * The AWT in standalone mode (that is, dynamically loaded from the
+ * Java VM) doesn't have any translation tables to worry about, so
+ * TranslateAccelerator isn't called.
+ */
+
+ ::TranslateMessage(&msg);
+ ::DispatchMessage(&msg);
+ }
}
VOID CALLBACK
--- a/jdk/src/windows/native/sun/windows/awt_Toolkit.h Mon Sep 26 15:40:05 2011 -0700
+++ b/jdk/src/windows/native/sun/windows/awt_Toolkit.h Tue Sep 27 13:38:29 2011 +0400
@@ -305,6 +305,8 @@
UINT MessageLoop(IDLEPROC lpIdleFunc, PEEKMESSAGEPROC lpPeekMessageFunc);
BOOL PumpWaitingMessages(PEEKMESSAGEPROC lpPeekMessageFunc);
+ void PumpToDestroy(class AwtComponent* p);
+ void ProcessMsg(MSG& msg);
BOOL PreProcessMsg(MSG& msg);
BOOL PreProcessMouseMsg(class AwtComponent* p, MSG& msg);
BOOL PreProcessKeyMsg(class AwtComponent* p, MSG& msg);