diff --git a/src/share/classes/java/awt/Menu.java b/src/share/classes/java/awt/Menu.java index 629371868d1f3c8507b8b6c5b8ea6b9a7d90050d..cfe70f975b6557dbad025dccc1747264d56e7b21 100644 --- a/src/share/classes/java/awt/Menu.java +++ b/src/share/classes/java/awt/Menu.java @@ -411,9 +411,9 @@ public class Menu extends MenuItem implements MenuContainer, Accessible { items.removeElementAt(index); MenuPeer peer = (MenuPeer)this.peer; if (peer != null) { + peer.delItem(index); mi.removeNotify(); mi.parent = null; - peer.delItem(index); } } } diff --git a/src/share/classes/java/awt/MenuBar.java b/src/share/classes/java/awt/MenuBar.java index afaa35d687dc7582c026a7798fd7383f4147efa6..7624b9d370cd68cc007a50252ab3eed4744d0f17 100644 --- a/src/share/classes/java/awt/MenuBar.java +++ b/src/share/classes/java/awt/MenuBar.java @@ -222,7 +222,6 @@ public class MenuBar extends MenuComponent implements MenuContainer, Accessible if (m.parent != null) { m.parent.remove(m); } - menus.addElement(m); m.parent = this; MenuBarPeer peer = (MenuBarPeer)this.peer; @@ -232,6 +231,7 @@ public class MenuBar extends MenuComponent implements MenuContainer, Accessible } peer.addMenu(m); } + menus.addElement(m); return m; } } @@ -248,9 +248,9 @@ public class MenuBar extends MenuComponent implements MenuContainer, Accessible menus.removeElementAt(index); MenuBarPeer peer = (MenuBarPeer)this.peer; if (peer != null) { + peer.delMenu(index); m.removeNotify(); m.parent = null; - peer.delMenu(index); } if (helpMenu == m) { helpMenu = null; diff --git a/src/share/classes/java/awt/MenuComponent.java b/src/share/classes/java/awt/MenuComponent.java index e1b3a7d6fc1cb87f3337657163d60cec49b6dd21..71a6f09b8ecdd30b5bc1c8a77b5bfe3bc51ccf51 100644 --- a/src/share/classes/java/awt/MenuComponent.java +++ b/src/share/classes/java/awt/MenuComponent.java @@ -75,7 +75,7 @@ public abstract class MenuComponent implements java.io.Serializable { * @see #setFont(Font) * @see #getFont() */ - Font font; + volatile Font font; /** * The menu component's name, which defaults to null. @@ -292,11 +292,13 @@ public abstract class MenuComponent implements java.io.Serializable { * @see java.awt.font.TextAttribute */ public void setFont(Font f) { - font = f; - //Fixed 6312943: NullPointerException in method MenuComponent.setFont(Font) - MenuComponentPeer peer = this.peer; - if (peer != null) { - peer.setFont(f); + synchronized (getTreeLock()) { + font = f; + //Fixed 6312943: NullPointerException in method MenuComponent.setFont(Font) + MenuComponentPeer peer = this.peer; + if (peer != null) { + peer.setFont(f); + } } } diff --git a/src/windows/classes/sun/awt/windows/WMenuItemPeer.java b/src/windows/classes/sun/awt/windows/WMenuItemPeer.java index 5a581193b8d516ec204d07a82ff3385cbf4bd234..2175bc6a22cc7027366220047079f5b984778215 100644 --- a/src/windows/classes/sun/awt/windows/WMenuItemPeer.java +++ b/src/windows/classes/sun/awt/windows/WMenuItemPeer.java @@ -71,7 +71,7 @@ class WMenuItemPeer extends WObjectPeer implements MenuItemPeer { enable(false); } - public void readShortcutLabel() { + private void readShortcutLabel() { //Fix for 6288578: PIT. Windows: Shortcuts displayed for the menuitems in a popup menu WMenuPeer ancestor = parent; while (ancestor != null && !(ancestor instanceof WMenuBarPeer)) { @@ -115,7 +115,7 @@ class WMenuItemPeer extends WObjectPeer implements MenuItemPeer { readShortcutLabel(); } - protected void checkMenuCreation() + void checkMenuCreation() { // fix for 5088782: check if menu peer is created successfully if (pData == 0) diff --git a/src/windows/classes/sun/awt/windows/WObjectPeer.java b/src/windows/classes/sun/awt/windows/WObjectPeer.java index c066ab57d23503651c9e67cc4e5c51dbca6acd42..f20f279d8c4bf874f8918841e52d1528f075dfab 100644 --- a/src/windows/classes/sun/awt/windows/WObjectPeer.java +++ b/src/windows/classes/sun/awt/windows/WObjectPeer.java @@ -34,16 +34,16 @@ abstract class WObjectPeer { } // The Windows handle for the native widget. - long pData; + volatile long pData; // if the native peer has been destroyed - boolean destroyed = false; + private volatile boolean destroyed; // The associated AWT object. - Object target; + volatile Object target; private volatile boolean disposed; // set from JNI if any errors in creating the peer occur - protected Error createError = null; + volatile Error createError = null; // used to synchronize the state of this peer private final Object stateLock = new Object(); diff --git a/src/windows/native/sun/windows/awt_Component.cpp b/src/windows/native/sun/windows/awt_Component.cpp index 0bb4539af2e766452b4f752c92e313e87f3c4ace..dfae30ef19dabee75684deded6a98b03c6d00cc2 100644 --- a/src/windows/native/sun/windows/awt_Component.cpp +++ b/src/windows/native/sun/windows/awt_Component.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2016, 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 @@ -3766,7 +3766,10 @@ void AwtComponent::OpenCandidateWindow(int x, int y) HWND hWnd = GetHWnd(); HWND hTop = GetTopLevelParentForWindow(hWnd); ::ClientToScreen(hTop, &p); - + if (!m_bitsCandType) { + SetCandidateWindow(m_bitsCandType, x - p.x, y - p.y); + return; + } for (int iCandType=0; iCandType<32; iCandType++, bits<<=1) { if ( m_bitsCandType & bits ) SetCandidateWindow(iCandType, x - p.x, y - p.y); @@ -3784,7 +3787,7 @@ void AwtComponent::SetCandidateWindow(int iCandType, int x, int y) HIMC hIMC = ImmGetContext(hwnd); CANDIDATEFORM cf; cf.dwIndex = iCandType; - cf.dwStyle = CFS_CANDIDATEPOS; + cf.dwStyle = CFS_POINT; cf.ptCurrentPos.x = x; cf.ptCurrentPos.y = y; @@ -3816,8 +3819,12 @@ MsgRouting AwtComponent::WmImeSetContext(BOOL fSet, LPARAM *lplParam) MsgRouting AwtComponent::WmImeNotify(WPARAM subMsg, LPARAM bitsCandType) { - if (!m_useNativeCompWindow && subMsg == IMN_OPENCANDIDATE) { - m_bitsCandType = bitsCandType; + if (!m_useNativeCompWindow) { + if (subMsg == IMN_OPENCANDIDATE) { + m_bitsCandType = subMsg; + } else if (subMsg != IMN_SETCANDIDATEPOS) { + m_bitsCandType = 0; + } InquireCandidatePosition(); return mrConsume; } @@ -4078,14 +4085,14 @@ HWND AwtComponent::GetProxyFocusOwner() return (HWND)NULL; } -/* Call DefWindowProc for the focus proxy, if any */ +/* Redirects message to the focus proxy, if any */ void AwtComponent::CallProxyDefWindowProc(UINT message, WPARAM wParam, LPARAM lParam, LRESULT &retVal, MsgRouting &mr) { if (mr != mrConsume) { HWND proxy = GetProxyFocusOwner(); if (proxy != NULL && ::IsWindowEnabled(proxy)) { - retVal = ComCtl32Util::GetInstance().DefWindowProc(NULL, proxy, message, wParam, lParam); + retVal = ::DefWindowProc(proxy, message, wParam, lParam); mr = mrConsume; } } @@ -4164,7 +4171,7 @@ MsgRouting AwtComponent::WmDrawItem(UINT ctrlId, DRAWITEMSTRUCT &drawInfo) JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); if (drawInfo.CtlType == ODT_MENU) { - if (drawInfo.itemData != 0) { + if (IsMenu((HMENU)drawInfo.hwndItem) && drawInfo.itemData != 0) { AwtMenu* menu = (AwtMenu*)(drawInfo.itemData); menu->DrawItem(drawInfo); } diff --git a/src/windows/native/sun/windows/awt_Menu.cpp b/src/windows/native/sun/windows/awt_Menu.cpp index 8bea41c88e3e87a55c5fa7907bd6ef264a4fe2d1..2b576fafc33b42cc560940d35cd2bdde9d38768d 100644 --- a/src/windows/native/sun/windows/awt_Menu.cpp +++ b/src/windows/native/sun/windows/awt_Menu.cpp @@ -34,6 +34,13 @@ /* IMPORTANT! Read the README.JNI file for notes on JNI converted AWT code. */ +/***********************************************************************/ +// struct for _DelItem() method +struct DelItemStruct { + jobject menuitem; + jint index; +}; + /************************************************************************ * AwtMenuItem fields */ @@ -64,7 +71,6 @@ void AwtMenu::Dispose() ::DestroyMenu(m_hMenu); m_hMenu = NULL; } - AwtMenuItem::Dispose(); } @@ -73,7 +79,7 @@ LPCTSTR AwtMenu::GetClassName() { } /* Create a new AwtMenu object and menu. */ -AwtMenu* AwtMenu::Create(jobject self, AwtMenu* parentMenu) +AwtMenu* AwtMenu::Create(jobject self, jobject parent) { JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); @@ -85,6 +91,9 @@ AwtMenu* AwtMenu::Create(jobject self, AwtMenu* parentMenu) return NULL; } + JNI_CHECK_NULL_GOTO(parent, "peer", done); + AwtMenu* parentMenu = (AwtMenu*) JNI_GET_PDATA(parent); + target = env->GetObjectField(self, AwtObject::targetID); JNI_CHECK_NULL_GOTO(target, "null target", done); @@ -119,6 +128,46 @@ done: return menu; } +void AwtMenu::_AddSeparator(void *param) +{ + if (AwtToolkit::IsMainThread()) { + JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); + + jobject self = (jobject)param; + AwtMenu *m = NULL; + PDATA pData; + JNI_CHECK_PEER_GOTO(self, ret); + m = (AwtMenu *)pData; + m->AddSeparator(); +ret: + env->DeleteGlobalRef(self); + } else { + AwtToolkit::GetInstance().InvokeFunction(AwtMenu::_AddSeparator, param); + } +} + +void AwtMenu::_DelItem(void *param) +{ + if (AwtToolkit::IsMainThread()) { + JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); + + DelItemStruct *dis = (DelItemStruct*) param; + jobject self = dis->menuitem; + jint index = dis->index; + + AwtMenu *m = NULL; + PDATA pData; + JNI_CHECK_PEER_GOTO(self, ret); + m = (AwtMenu *)pData; + m->DeleteItem(static_cast(index)); +ret: + env->DeleteGlobalRef(self); + delete dis; + } else { + AwtToolkit::GetInstance().InvokeFunction(AwtMenu::_DelItem, param); + } +} + void AwtMenu::UpdateLayout() { UpdateLayout(GetHMenu()); @@ -239,6 +288,7 @@ AwtMenuItem* AwtMenu::GetItem(jobject target, jint index) } jobject menuItem = env->CallObjectMethod(target, AwtMenu::getItemMID, index); + if (!menuItem) return NULL; // menu item was removed concurrently DASSERT(!safe_ExceptionOccurred(env)); jobject wMenuItemPeer = GetPeerForTarget(env, menuItem); @@ -264,9 +314,9 @@ void AwtMenu::DrawItems(DRAWITEMSTRUCT& drawInfo) } /* target is a java.awt.Menu */ jobject target = GetTarget(env); - + if(!target || env->ExceptionCheck()) return; int nCount = CountItem(target); - for (int i = 0; i < nCount; i++) { + for (int i = 0; i < nCount && !env->ExceptionCheck(); i++) { AwtMenuItem* awtMenuItem = GetItem(target, i); if (awtMenuItem != NULL) { SendDrawItem(awtMenuItem, drawInfo); @@ -294,8 +344,9 @@ void AwtMenu::MeasureItems(HDC hDC, MEASUREITEMSTRUCT& measureInfo) } /* target is a java.awt.Menu */ jobject target = GetTarget(env); + if(!target || env->ExceptionCheck()) return; int nCount = CountItem(target); - for (int i = 0; i < nCount; i++) { + for (int i = 0; i < nCount && !env->ExceptionCheck(); i++) { AwtMenuItem* awtMenuItem = GetItem(target, i); if (awtMenuItem != NULL) { SendMeasureItem(awtMenuItem, hDC, measureInfo); @@ -321,24 +372,6 @@ BOOL AwtMenu::IsTopMenu() return (GetMenuBar() == GetMenuContainer()); } -LRESULT AwtMenu::WinThreadExecProc(ExecuteArgs * args) -{ - switch( args->cmdId ) { - case MENU_ADDSEPARATOR: - this->AddSeparator(); - break; - - case MENU_DELITEM: - this->DeleteItem(static_cast(args->param1)); - break; - - default: - AwtMenuItem::WinThreadExecProc(args); - break; - } - return 0L; -} - /************************************************************************ * WMenuPeer native methods */ @@ -380,15 +413,14 @@ Java_sun_awt_windows_WMenuPeer_addSeparator(JNIEnv *env, jobject self) { TRY; - PDATA pData; - JNI_CHECK_PEER_RETURN(self); + jobject selfGlobalRef = env->NewGlobalRef(self); - AwtObject::WinThreadExec(self, AwtMenu::MENU_ADDSEPARATOR); + AwtToolkit::GetInstance().SyncCall(AwtMenu::_AddSeparator, selfGlobalRef); + // selfGlobalRef is deleted in _AddSeparator CATCH_BAD_ALLOC; } - /* * Class: sun_awt_windows_WMenuPeer * Method: delItem @@ -400,10 +432,12 @@ Java_sun_awt_windows_WMenuPeer_delItem(JNIEnv *env, jobject self, { TRY; - PDATA pData; - JNI_CHECK_PEER_RETURN(self); + DelItemStruct *dis = new DelItemStruct; + dis->menuitem = env->NewGlobalRef(self); + dis->index = index; - AwtObject::WinThreadExec(self, AwtMenu::MENU_DELITEM, index); + AwtToolkit::GetInstance().SyncCall(AwtMenu::_DelItem, dis); + // global refs and dis are deleted in _DelItem CATCH_BAD_ALLOC; } @@ -419,13 +453,8 @@ Java_sun_awt_windows_WMenuPeer_createMenu(JNIEnv *env, jobject self, { TRY; - PDATA pData; - JNI_CHECK_PEER_RETURN(menuBar); - - AwtMenuBar* awtMenuBar = (AwtMenuBar *)pData; - AwtToolkit::CreateComponent(self, awtMenuBar, - (AwtToolkit::ComponentFactory)AwtMenu::Create,FALSE); - JNI_CHECK_PEER_CREATION_RETURN(self); + AwtToolkit::CreateComponent(self, menuBar, + (AwtToolkit::ComponentFactory)AwtMenu::Create); CATCH_BAD_ALLOC; } @@ -441,13 +470,8 @@ Java_sun_awt_windows_WMenuPeer_createSubMenu(JNIEnv *env, jobject self, { TRY; - PDATA pData; - JNI_CHECK_PEER_RETURN(menu); - - AwtMenu* awtMenu = (AwtMenu *)pData; - AwtToolkit::CreateComponent(self, awtMenu, - (AwtToolkit::ComponentFactory)AwtMenu::Create,FALSE); - JNI_CHECK_PEER_CREATION_RETURN(self); + AwtToolkit::CreateComponent(self, menu, + (AwtToolkit::ComponentFactory)AwtMenu::Create); CATCH_BAD_ALLOC; } diff --git a/src/windows/native/sun/windows/awt_Menu.h b/src/windows/native/sun/windows/awt_Menu.h index f0070921b12760da4d3f935347ceae45b4638725..c156433716ad69385544a4038cdd3ecd7970b100 100644 --- a/src/windows/native/sun/windows/awt_Menu.h +++ b/src/windows/native/sun/windows/awt_Menu.h @@ -42,13 +42,6 @@ class AwtMenuBar; class AwtMenu : public AwtMenuItem { public: - // id's for methods executed on toolkit thread - enum { - MENU_ADDSEPARATOR = MENUITEM_LAST+1, - MENU_DELITEM, - MENU_LAST - }; - /* method ids for java.awt.Menu */ static jmethodID countItemsMID; static jmethodID getItemMID; @@ -61,7 +54,7 @@ public: virtual LPCTSTR GetClassName(); /* Create a new AwtMenu. This must be run on the main thread. */ - static AwtMenu* Create(jobject self, AwtMenu* parentMenu); + static AwtMenu* Create(jobject self, jobject parent); INLINE HMENU GetHMenu() { return m_hMenu; } INLINE void SetHMenu(HMENU hMenu) { @@ -94,9 +87,9 @@ public: void MeasureItem(HDC hDC, MEASUREITEMSTRUCT& measureInfo); void MeasureItems(HDC hDC, MEASUREITEMSTRUCT& measureInfo); - virtual LRESULT WinThreadExecProc(ExecuteArgs * args); - // invoked on Toolkit thread + static void _AddSeparator(void *param); + static void _DelItem(void *param); static void _CreateMenu(void *param); static void _CreateSubMenu(void *param); virtual BOOL IsSeparator() { return FALSE; } diff --git a/src/windows/native/sun/windows/awt_MenuBar.cpp b/src/windows/native/sun/windows/awt_MenuBar.cpp index f6e69c3f652d3a66476b93441f5dcc25279b96c4..2801d4ced0ee67a0e09fb676200453b6c165f5a6 100644 --- a/src/windows/native/sun/windows/awt_MenuBar.cpp +++ b/src/windows/native/sun/windows/awt_MenuBar.cpp @@ -29,6 +29,12 @@ /* IMPORTANT! Read the README.JNI file for notes on JNI converted AWT code. */ +/***********************************************************************/ +// struct for _DelItem() method +struct DelItemStruct { + jobject menuitem; + jint index; +}; /***********************************************************************/ // struct for _AddMenu() method struct AddMenuStruct { @@ -130,18 +136,6 @@ HWND AwtMenuBar::GetOwnerHWnd() return myFrame->GetHWnd(); } -void AwtMenuBar::SendDrawItem(AwtMenuItem* awtMenuItem, - DRAWITEMSTRUCT& drawInfo) -{ - awtMenuItem->DrawItem(drawInfo); -} - -void AwtMenuBar::SendMeasureItem(AwtMenuItem* awtMenuItem, - HDC hDC, MEASUREITEMSTRUCT& measureInfo) -{ - awtMenuItem->MeasureItem(hDC, measureInfo); -} - int AwtMenuBar::CountItem(jobject menuBar) { JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); @@ -159,13 +153,16 @@ AwtMenuItem* AwtMenuBar::GetItem(jobject target, long index) } jobject menu = env->CallObjectMethod(target, AwtMenuBar::getMenuMID,index); + if (!menu) return NULL; // menu item was removed concurrently DASSERT(!safe_ExceptionOccurred(env)); jobject menuItemPeer = GetPeerForTarget(env, menu); PDATA pData; - JNI_CHECK_PEER_RETURN_NULL(menuItemPeer); - AwtMenuItem* awtMenuItem = (AwtMenuItem*)pData; + AwtMenuItem* awtMenuItem = NULL; + JNI_CHECK_PEER_GOTO(menuItemPeer, done); + awtMenuItem = (AwtMenuItem*)pData; +done: env->DeleteLocalRef(menu); env->DeleteLocalRef(menuItemPeer); @@ -212,20 +209,6 @@ void AwtMenuBar::RedrawMenuBar() { VERIFY(::DrawMenuBar(GetOwnerHWnd())); } -LRESULT AwtMenuBar::WinThreadExecProc(ExecuteArgs * args) -{ - switch( args->cmdId ) { - case MENUBAR_DELITEM: - this->DeleteItem(static_cast(args->param1)); - break; - - default: - AwtMenu::WinThreadExecProc(args); - break; - } - return 0L; -} - void AwtMenuBar::_AddMenu(void *param) { JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); @@ -254,6 +237,28 @@ ret: delete ams; } +void AwtMenuBar::_DelItem(void *param) +{ + if (AwtToolkit::IsMainThread()) { + JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); + + DelItemStruct *dis = (DelItemStruct*) param; + jobject self = dis->menuitem; + jint index = dis->index; + + AwtMenuBar *m = NULL; + PDATA pData; + JNI_CHECK_PEER_GOTO(self, ret); + m = (AwtMenuBar *)pData; + m->DeleteItem(static_cast(index)); +ret: + env->DeleteGlobalRef(self); + delete dis; + } else { + AwtToolkit::GetInstance().InvokeFunction(AwtMenuBar::_DelItem, param); + } +} + /************************************************************************ * MenuBar native methods */ @@ -322,9 +327,12 @@ Java_sun_awt_windows_WMenuBarPeer_delMenu(JNIEnv *env, jobject self, { TRY; - PDATA pData; - JNI_CHECK_PEER_RETURN(self); - AwtObject::WinThreadExec(self, AwtMenuBar::MENUBAR_DELITEM, (LPARAM)index); + DelItemStruct *dis = new DelItemStruct; + dis->menuitem = env->NewGlobalRef(self); + dis->index = index; + + AwtToolkit::GetInstance().SyncCall(AwtMenuBar::_DelItem, dis); + // global refs and dis are deleted in _DelItem CATCH_BAD_ALLOC; } @@ -343,9 +351,6 @@ Java_sun_awt_windows_WMenuBarPeer_create(JNIEnv *env, jobject self, AwtToolkit::CreateComponent(self, frame, (AwtToolkit::ComponentFactory) AwtMenuBar::Create); - PDATA pData; - JNI_CHECK_PEER_CREATION_RETURN(self); - CATCH_BAD_ALLOC; } diff --git a/src/windows/native/sun/windows/awt_MenuBar.h b/src/windows/native/sun/windows/awt_MenuBar.h index 797cf0a58bda99015cc88eece6338f5b8080bd03..3e60a9b399aa4360a199f4949a4356508508fdb3 100644 --- a/src/windows/native/sun/windows/awt_MenuBar.h +++ b/src/windows/native/sun/windows/awt_MenuBar.h @@ -42,10 +42,6 @@ class AwtFrame; class AwtMenuBar : public AwtMenu { public: - // id's for methods executed on toolkit thread - enum MenuExecIds { - MENUBAR_DELITEM = MENU_LAST+1 - }; /* java.awt.MenuBar method ids */ static jmethodID getMenuCountMID; @@ -73,20 +69,15 @@ public: AwtMenuItem* GetItem(jobject target, long index); int CountItem(jobject menuBar); - void SendDrawItem(AwtMenuItem* awtMenuItem, - DRAWITEMSTRUCT& drawInfo); - void SendMeasureItem(AwtMenuItem* awtMenuItem, - HDC hDC, MEASUREITEMSTRUCT& measureInfo); void DrawItem(DRAWITEMSTRUCT& drawInfo); void MeasureItem(HDC hDC, MEASUREITEMSTRUCT& measureInfo); void AddItem(AwtMenuItem* item); void DeleteItem(UINT index); - virtual LRESULT WinThreadExecProc(ExecuteArgs * args); - // called on Toolkit thread static void _AddMenu(void *param); + static void _DelItem(void *param); protected: AwtFrame* m_frame; }; diff --git a/src/windows/native/sun/windows/awt_MenuItem.cpp b/src/windows/native/sun/windows/awt_MenuItem.cpp index cb0f380c7158584acd63064b361ec453ef3be11d..36b395c2501083954f2f73a7d8da7cfed30f23b7 100644 --- a/src/windows/native/sun/windows/awt_MenuItem.cpp +++ b/src/windows/native/sun/windows/awt_MenuItem.cpp @@ -50,6 +50,16 @@ struct SetLabelStruct { jobject menuitem; jstring label; }; +// struct for _SetEnable() method +struct SetEnableStruct { + jobject menuitem; + jboolean isEnabled; +}; +// struct for _setState() method +struct SetStateStruct { + jobject menuitem; + jboolean isChecked; +}; /************************************************************************ * AwtMenuItem fields */ @@ -104,6 +114,7 @@ void AwtMenuItem::RemoveCmdID() { if (m_freeId) { AwtToolkit::GetInstance().RemoveCmdID( GetID() ); + m_freeId = FALSE; } } void AwtMenuItem::Dispose() @@ -112,6 +123,7 @@ void AwtMenuItem::Dispose() JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); if (m_peerObject != NULL) { + JNI_SET_DESTROYED(m_peerObject); JNI_SET_PDATA(m_peerObject, NULL); env->DeleteGlobalRef(m_peerObject); m_peerObject = NULL; @@ -205,13 +217,12 @@ AwtMenuItem* AwtMenuItem::Create(jobject peer, jobject menuPeer) if (env->EnsureLocalCapacity(1) < 0) { return NULL; } - PDATA pData; - JNI_CHECK_PEER_RETURN_NULL(menuPeer); + JNI_CHECK_NULL_RETURN_NULL(menuPeer, "peer"); /* target is a java.awt.MenuItem */ target = env->GetObjectField(peer, AwtObject::targetID); - AwtMenu* menu = (AwtMenu *)pData; + AwtMenu* menu = (AwtMenu *)JNI_GET_PDATA(menuPeer); item = new AwtMenuItem(); jboolean isCheckbox = (jboolean)env->GetBooleanField(peer, AwtMenuItem::isCheckboxID); @@ -222,7 +233,9 @@ AwtMenuItem* AwtMenuItem::Create(jobject peer, jobject menuPeer) item->LinkObjects(env, peer); item->SetMenuContainer(menu); item->SetNewID(); - menu->AddItem(item); + if (menu != NULL) { + menu->AddItem(item); + } } catch (...) { env->DeleteLocalRef(target); throw; @@ -763,30 +776,6 @@ void AwtMenuItem::UpdateContainerLayout() { } } -LRESULT AwtMenuItem::WinThreadExecProc(ExecuteArgs * args) -{ - switch( args->cmdId ) { - case MENUITEM_ENABLE: - { - BOOL isEnabled = (BOOL)args->param1; - this->Enable(isEnabled); - } - break; - - case MENUITEM_SETSTATE: - { - BOOL isChecked = (BOOL)args->param1; - this->SetState(isChecked); - } - break; - - default: - AwtObject::WinThreadExecProc(args); - break; - } - return 0L; -} - void AwtMenuItem::_SetLabel(void *param) { if (AwtToolkit::IsMainThread()) { JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); @@ -886,6 +875,53 @@ ret: } } +void AwtMenuItem::_SetEnable(void *param) +{ + if (AwtToolkit::IsMainThread()) { + JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); + + SetEnableStruct *ses = (SetEnableStruct*) param; + jobject self = ses->menuitem; + jboolean isEnabled = ses->isEnabled; + + AwtMenuItem *m = NULL; + + PDATA pData; + JNI_CHECK_PEER_GOTO(self, ret); + + m = (AwtMenuItem *)pData; + + m->Enable(isEnabled); +ret: + env->DeleteGlobalRef(self); + delete ses; + } else { + AwtToolkit::GetInstance().InvokeFunction(AwtMenuItem::_SetEnable, param); + } +} + +void AwtMenuItem::_SetState(void *param) +{ + if (AwtToolkit::IsMainThread()) { + JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); + + SetStateStruct *sts = (SetStateStruct*) param; + jobject self = sts->menuitem; + jboolean isChecked = sts->isChecked; + + AwtMenuItem *m = NULL; + + PDATA pData; + JNI_CHECK_PEER_GOTO(self, ret); + m = (AwtMenuItem *)pData; + m->SetState(isChecked); +ret: + env->DeleteGlobalRef(self); + delete sts; + } else { + AwtToolkit::GetInstance().InvokeFunction(AwtMenuItem::_SetState, param); + } +} BOOL AwtMenuItem::IsSeparator() { JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); if (env->EnsureLocalCapacity(2) < 0) { @@ -1049,13 +1085,9 @@ Java_sun_awt_windows_WMenuItemPeer_create(JNIEnv *env, jobject self, { TRY; - JNI_CHECK_NULL_RETURN(menu, "null Menu"); AwtToolkit::CreateComponent(self, menu, (AwtToolkit::ComponentFactory) AwtMenuItem::Create); - PDATA pData; - JNI_CHECK_PEER_CREATION_RETURN(self); - CATCH_BAD_ALLOC; } @@ -1070,9 +1102,12 @@ Java_sun_awt_windows_WMenuItemPeer_enable(JNIEnv *env, jobject self, { TRY; - PDATA pData; - JNI_CHECK_PEER_RETURN(self); - AwtObject::WinThreadExec(self, AwtMenuItem::MENUITEM_ENABLE, (LPARAM)on ); + SetEnableStruct *ses = new SetEnableStruct; + ses->menuitem = env->NewGlobalRef(self); + ses->isEnabled = on; + + AwtToolkit::GetInstance().SyncCall(AwtMenuItem::_SetEnable, ses); + // global refs and ses are deleted in _SetEnable CATCH_BAD_ALLOC; } @@ -1111,9 +1146,12 @@ Java_sun_awt_windows_WCheckboxMenuItemPeer_setState(JNIEnv *env, jobject self, { TRY; - PDATA pData; - JNI_CHECK_PEER_RETURN(self); - AwtObject::WinThreadExec(self, AwtMenuItem::MENUITEM_SETSTATE, (LPARAM)on); + SetStateStruct *sts = new SetStateStruct; + sts->menuitem = env->NewGlobalRef(self); + sts->isChecked = on; + + AwtToolkit::GetInstance().SyncCall(AwtMenuItem::_SetState, sts); + // global refs and sts are deleted in _SetState CATCH_BAD_ALLOC; } diff --git a/src/windows/native/sun/windows/awt_MenuItem.h b/src/windows/native/sun/windows/awt_MenuItem.h index e06a146a5b39274f3d8d64cc61e55aaa2d4d67c2..9bbb1fe2c9df7ff0b1efba54811de49b519994cb 100644 --- a/src/windows/native/sun/windows/awt_MenuItem.h +++ b/src/windows/native/sun/windows/awt_MenuItem.h @@ -45,13 +45,6 @@ class AwtMenu; class AwtMenuItem : public AwtObject { public: - // id's for methods executed on toolkit thread - enum { - MENUITEM_ENABLE, - MENUITEM_SETSTATE, - MENUITEM_LAST - }; - /* java.awt.MenuComponent fields */ static jfieldID fontID; static jfieldID appContextID; @@ -154,13 +147,14 @@ public: */ MsgRouting WmNotify(UINT notifyCode); - virtual LRESULT WinThreadExecProc(ExecuteArgs * args); virtual BOOL IsDisabledAndPopup() { return FALSE; } virtual BOOL IsSeparator(); // invoked on Toolkit thread + static void _SetState(void *param); + static void _SetEnable(void *param); static void _SetLabel(void *param); static void _UpdateLayout(void *param); diff --git a/src/windows/native/sun/windows/awt_PopupMenu.cpp b/src/windows/native/sun/windows/awt_PopupMenu.cpp index 0a04e0e8db5d0058c59309bdabb93ca3028c9837..4cfb6d7eb201f4e878b7e9a250d902118da0fec0 100644 --- a/src/windows/native/sun/windows/awt_PopupMenu.cpp +++ b/src/windows/native/sun/windows/awt_PopupMenu.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2016, 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 @@ -65,7 +65,7 @@ LPCTSTR AwtPopupMenu::GetClassName() { } /* Create a new AwtPopupMenu object and menu. */ -AwtPopupMenu* AwtPopupMenu::Create(jobject self, AwtComponent* parent) +AwtPopupMenu* AwtPopupMenu::Create(jobject self, jobject parent) { JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); @@ -77,6 +77,9 @@ AwtPopupMenu* AwtPopupMenu::Create(jobject self, AwtComponent* parent) return NULL; } + JNI_CHECK_NULL_GOTO(parent, "peer", done); + AwtComponent* awtParent = (AwtComponent*) JNI_GET_PDATA(parent); + target = env->GetObjectField(self, AwtObject::targetID); JNI_CHECK_NULL_GOTO(target, "null target", done); @@ -94,7 +97,7 @@ AwtPopupMenu* AwtPopupMenu::Create(jobject self, AwtComponent* parent) popupMenu->SetHMenu(hMenu); popupMenu->LinkObjects(env, self); - popupMenu->SetParent(parent); + popupMenu->SetParent(awtParent); } catch (...) { env->DeleteLocalRef(target); throw; @@ -274,12 +277,8 @@ Java_sun_awt_windows_WPopupMenuPeer_createMenu(JNIEnv *env, jobject self, { TRY; - PDATA pData; - JNI_CHECK_PEER_RETURN(parent); - AwtComponent* awtParent = (AwtComponent *)pData; AwtToolkit::CreateComponent( - self, awtParent, (AwtToolkit::ComponentFactory)AwtPopupMenu::Create, FALSE); - JNI_CHECK_PEER_CREATION_RETURN(self); + self, parent, (AwtToolkit::ComponentFactory)AwtPopupMenu::Create); CATCH_BAD_ALLOC; } diff --git a/src/windows/native/sun/windows/awt_PopupMenu.h b/src/windows/native/sun/windows/awt_PopupMenu.h index f149b7521684f34694e6f0e6c478a6692faf55e4..15670ec077af362f49cddfbca9fec5e246da9338 100644 --- a/src/windows/native/sun/windows/awt_PopupMenu.h +++ b/src/windows/native/sun/windows/awt_PopupMenu.h @@ -47,7 +47,7 @@ public: virtual LPCTSTR GetClassName(); /* Create a new AwtPopupMenu. This must be run on the main thread. */ - static AwtPopupMenu* Create(jobject self, AwtComponent* parent); + static AwtPopupMenu* Create(jobject self, jobject parent); /* Display the popup modally. */ void Show(JNIEnv *env, jobject event, BOOL isTrayIconPopup); diff --git a/src/windows/native/sun/windows/awt_new.cpp b/src/windows/native/sun/windows/awt_new.cpp index e5adec25b56a4a8dea9d7ba36b02e17f6fbee6b1..b2d133f2350003d464f89bdf66393f5b35ea5c77 100644 --- a/src/windows/native/sun/windows/awt_new.cpp +++ b/src/windows/native/sun/windows/awt_new.cpp @@ -172,6 +172,9 @@ safe_ExceptionOccurred(JNIEnv *env) throw (std::bad_alloc) { env->ExceptionClear(); // rethrow exception env->Throw(xcp); + // temp solution to reveal all concurrency issues in jtreg and JCK + // we will switch it back to silent mode before the release + env->ExceptionDescribe(); return xcp; } } diff --git a/test/java/awt/Frame/FrameResize/ShowChildWhileResizingTest.java b/test/java/awt/Frame/FrameResize/ShowChildWhileResizingTest.java new file mode 100644 index 0000000000000000000000000000000000000000..ee722f442367b67d57e8e9299fca2359ad1f16e7 --- /dev/null +++ b/test/java/awt/Frame/FrameResize/ShowChildWhileResizingTest.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2015 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + @bug 8079595 + @summary Resizing dialog which is JWindow parent makes JVM crash + @author Semyon Sadetsky + */ + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.InputEvent; + +public class ShowChildWhileResizingTest { + + private static Window dialog; + private static Timer timer; + private static Point point; + + public static void main(String[] args) throws Exception { + dialog = new Frame(); + dialog.add(new JPanel()); + dialog.setVisible(true); + dialog.setBounds(100, 100, 200, 200); + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + final Window dependentWindow = new JWindow(dialog); + JPanel panel = new JPanel(); + panel.add(new JButton("button")); + dependentWindow.add(panel); + dependentWindow.setVisible(true); + dependentWindow.setBounds(0, 0, 50, 50); + timer = new Timer(100, new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + dependentWindow + .setVisible(!dependentWindow.isVisible()); + } + }); + timer.start(); + } + + }); + + Robot robot = new Robot(); + robot.setAutoDelay(5); + robot.delay(300); + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + point = dialog.getLocationOnScreen(); + } + }); + robot.mouseMove(point.x + 200 - dialog.getInsets().right/2, + point.y + 200 - dialog.getInsets().bottom/2); + robot.mousePress(InputEvent.BUTTON1_MASK); + for(int i = 0; i < 100; i++) { + robot.mouseMove(point.x + 200 + i, point.y + 200 + i); + } + robot.mouseRelease(InputEvent.BUTTON1_MASK); + timer.stop(); + dialog.dispose(); + System.out.println("ok"); + } +}