diff --git a/src/windows/classes/sun/awt/windows/WComponentPeer.java b/src/windows/classes/sun/awt/windows/WComponentPeer.java index 01eb239961b3626f9b802fdc4e965188d1205015..a482fd9ca86fc155e280b4b86c65605872f42e9c 100644 --- a/src/windows/classes/sun/awt/windows/WComponentPeer.java +++ b/src/windows/classes/sun/awt/windows/WComponentPeer.java @@ -615,6 +615,14 @@ public abstract class WComponentPeer extends WObjectPeer _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()); diff --git a/src/windows/native/sun/windows/awt_Component.cpp b/src/windows/native/sun/windows/awt_Component.cpp index a6ada9cb92dea10e5ab331394b75fa730e434ae8..57d1733756e2e517c97289fc35da18c443a62690 100644 --- a/src/windows/native/sun/windows/awt_Component.cpp +++ b/src/windows/native/sun/windows/awt_Component.cpp @@ -183,6 +183,7 @@ jmethodID AwtComponent::isEnabledMID; 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 @@ AwtComponent::AwtComponent() m_hCursorCache = NULL; m_bSubclassed = FALSE; + m_bPauseDestroy = FALSE; m_MessagesProcessing = 0; m_wheelRotationAmount = 0; @@ -319,6 +321,12 @@ void AwtComponent::Dispose() 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 @@ LRESULT AwtComponent::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) 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 @@ LRESULT AwtComponent::DefWindowProc(UINT msg, WPARAM wParam, LPARAM lParam) */ 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 @@ Java_java_awt_Component_initIDs(JNIEnv *env, jclass cls) 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 @@ Java_java_awt_Component_initIDs(JNIEnv *env, jclass cls) DASSERT(AwtComponent::getLocationOnScreenMID); DASSERT(AwtComponent::replaceSurfaceDataMID); DASSERT(AwtComponent::replaceSurfaceDataLaterMID); + DASSERT(AwtComponent::disposeLaterMID); + CATCH_BAD_ALLOC; } diff --git a/src/windows/native/sun/windows/awt_Component.h b/src/windows/native/sun/windows/awt_Component.h index ece5c3b3bce90fbf38a3cd0aa01fba9a26a56cb8..3257c5175163627d4a08c428dab73d560e423074 100644 --- a/src/windows/native/sun/windows/awt_Component.h +++ b/src/windows/native/sun/windows/awt_Component.h @@ -119,6 +119,7 @@ public: 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 @@ public: 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 @@ public: return m_MessagesProcessing == 0; } + BOOL IsDestroyPaused() const { + return m_bPauseDestroy; + } + protected: static AwtComponent* GetComponentImpl(HWND hWnd); @@ -752,6 +758,7 @@ private: UINT m_mouseButtonClickAllowed; BOOL m_bSubclassed; + BOOL m_bPauseDestroy; COLORREF m_colorForeground; COLORREF m_colorBackground; diff --git a/src/windows/native/sun/windows/awt_Toolkit.cpp b/src/windows/native/sun/windows/awt_Toolkit.cpp index 00f9b325abb2ab1c09056d3b83a7ac3b0d08e082..913540399b540e4c71a9d09f88492b54dc4087f8 100644 --- a/src/windows/native/sun/windows/awt_Toolkit.cpp +++ b/src/windows/native/sun/windows/awt_Toolkit.cpp @@ -733,26 +733,13 @@ LRESULT CALLBACK AwtToolkit::WndProc(HWND hWnd, UINT message, 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,27 +1327,48 @@ BOOL AwtToolkit::PumpWaitingMessages(PEEKMESSAGEPROC lpPeekMessageFunc) while (!m_breakMessageLoop && (*lpPeekMessageFunc)(msg)) { foundOne = TRUE; - if (msg.message == WM_QUIT) { - m_breakMessageLoop = TRUE; - m_messageLoopResult = static_cast(msg.wParam); - if (m_messageLoopResult == EXIT_ALL_ENCLOSING_LOOPS) - ::PostQuitMessage(static_cast(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); + } + } +} + +void AwtToolkit::ProcessMsg(MSG& msg) +{ + if (msg.message == WM_QUIT) { + m_breakMessageLoop = TRUE; + m_messageLoopResult = static_cast(msg.wParam); + if (m_messageLoopResult == EXIT_ALL_ENCLOSING_LOOPS) + ::PostQuitMessage(static_cast(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 AwtToolkit::PrimaryIdleFunc() { AwtToolkit::SetBusy(FALSE); diff --git a/src/windows/native/sun/windows/awt_Toolkit.h b/src/windows/native/sun/windows/awt_Toolkit.h index 3ebd465caca2bee26d6f9fb7f3e202cb00917591..f3e7e74138b44c22d599296d1bf843e50d3401b5 100644 --- a/src/windows/native/sun/windows/awt_Toolkit.h +++ b/src/windows/native/sun/windows/awt_Toolkit.h @@ -305,6 +305,8 @@ public: 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);