8167110: Windows peering issue

Reviewed-by: ssadetsky, mschoene, prr
This commit is contained in:
Sergey Bylokhov 2016-11-19 13:10:18 +03:00
parent f53059ee3e
commit d9bb0f0d39
11 changed files with 194 additions and 156 deletions

View File

@ -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)

View File

@ -36,14 +36,14 @@ abstract class WObjectPeer {
// The Windows handle for the native widget.
volatile long pData;
// if the native peer has been destroyed
volatile 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();

View File

@ -4220,7 +4220,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);
}

View File

@ -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<UINT>(index));
ret:
env->DeleteGlobalRef(self);
delete dis;
} else {
AwtToolkit::GetInstance().InvokeFunction(AwtMenu::_DelItem, param);
}
}
void AwtMenu::UpdateLayout()
{
UpdateLayout(GetHMenu());
@ -323,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<UINT>(args->param1));
break;
default:
AwtMenuItem::WinThreadExecProc(args);
break;
}
return 0L;
}
/************************************************************************
* WMenuPeer native methods
*/
@ -382,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
@ -402,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;
}
@ -421,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;
}
@ -443,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;
}

View File

@ -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; }

View File

@ -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);
@ -164,9 +158,9 @@ AwtMenuItem* AwtMenuBar::GetItem(jobject target, long index)
jobject menuItemPeer = GetPeerForTarget(env, menu);
PDATA pData;
AwtMenuItem* awtMenuItem = NULL;
JNI_CHECK_PEER_GOTO(menuItemPeer, done);
AwtMenuItem* awtMenuItem = (AwtMenuItem*)pData;
awtMenuItem = (AwtMenuItem*)pData;
done:
env->DeleteLocalRef(menu);
@ -215,20 +209,6 @@ void AwtMenuBar::RedrawMenuBar() {
VERIFY(::DrawMenuBar(GetOwnerHWnd()));
}
LRESULT AwtMenuBar::WinThreadExecProc(ExecuteArgs * args)
{
switch( args->cmdId ) {
case MENUBAR_DELITEM:
this->DeleteItem(static_cast<UINT>(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);
@ -257,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<UINT>(index));
ret:
env->DeleteGlobalRef(self);
delete dis;
} else {
AwtToolkit::GetInstance().InvokeFunction(AwtMenuBar::_DelItem, param);
}
}
/************************************************************************
* MenuBar native methods
*/
@ -325,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;
}
@ -346,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;
}

View File

@ -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;
};

View File

@ -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()
@ -206,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);
@ -223,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;
@ -764,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);
@ -887,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) {
@ -1050,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;
}
@ -1071,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;
}
@ -1112,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;
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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);