4717864: setFont() does not update Fonts of Menus already on screen
Reviewed-by: art, bagiras
--- a/jdk/src/windows/classes/sun/awt/windows/WMenuItemPeer.java Fri Jul 15 19:24:09 2011 +0400
+++ b/jdk/src/windows/classes/sun/awt/windows/WMenuItemPeer.java Fri Jul 15 19:25:06 2011 +0400
@@ -183,7 +183,9 @@
*/
private static native void initIDs();
- // Needed for MenuComponentPeer.
- public void setFont(Font f) {
+ private native void _setFont(Font f);
+
+ public void setFont(final Font f) {
+ _setFont(f);
}
}
--- a/jdk/src/windows/native/sun/windows/awt_Menu.cpp Fri Jul 15 19:24:09 2011 +0400
+++ b/jdk/src/windows/native/sun/windows/awt_Menu.cpp Fri Jul 15 19:25:06 2011 +0400
@@ -119,6 +119,41 @@
return menu;
}
+void AwtMenu::UpdateLayout()
+{
+ UpdateLayout(GetHMenu());
+ RedrawMenuBar();
+}
+
+void AwtMenu::UpdateLayout(const HMENU hmenu)
+{
+ const int nMenuItemCount = ::GetMenuItemCount(hmenu);
+ static MENUITEMINFO mii;
+ for (int idx = 0; idx < nMenuItemCount; ++idx) {
+ memset(&mii, 0, sizeof(mii));
+ mii.cbSize = sizeof(mii);
+ mii.fMask = MIIM_CHECKMARKS | MIIM_DATA | MIIM_ID
+ | MIIM_STATE | MIIM_SUBMENU | MIIM_TYPE;
+ if (::GetMenuItemInfo(hmenu, idx, TRUE, &mii)) {
+ VERIFY(::RemoveMenu(hmenu, idx, MF_BYPOSITION));
+ VERIFY(::InsertMenuItem(hmenu, idx, TRUE, &mii));
+ if (mii.hSubMenu != NULL) {
+ UpdateLayout(mii.hSubMenu);
+ }
+ }
+ }
+}
+
+void AwtMenu::UpdateContainerLayout()
+{
+ AwtMenu* menu = GetMenuContainer();
+ if (menu != NULL) {
+ menu->UpdateLayout();
+ } else {
+ UpdateLayout();
+ }
+}
+
AwtMenuBar* AwtMenu::GetMenuBar() {
return (GetMenuContainer() == NULL) ? NULL : GetMenuContainer()->GetMenuBar();
}
--- a/jdk/src/windows/native/sun/windows/awt_Menu.h Fri Jul 15 19:24:09 2011 +0400
+++ b/jdk/src/windows/native/sun/windows/awt_Menu.h Fri Jul 15 19:25:06 2011 +0400
@@ -72,6 +72,8 @@
virtual AwtMenuBar* GetMenuBar();
void AddSeparator();
+ virtual void UpdateContainerLayout();
+ void UpdateLayout();
virtual void AddItem(AwtMenuItem *item);
virtual void DeleteItem(UINT index);
@@ -103,6 +105,7 @@
virtual void RemoveCmdID() { /* do nothing */ }
private:
+ void UpdateLayout(const HMENU hmenu);
HMENU m_hMenu;
};
--- a/jdk/src/windows/native/sun/windows/awt_MenuBar.cpp Fri Jul 15 19:24:09 2011 +0400
+++ b/jdk/src/windows/native/sun/windows/awt_MenuBar.cpp Fri Jul 15 19:25:06 2011 +0400
@@ -198,7 +198,15 @@
if (hOwnerWnd != NULL) {
VERIFY(::InvalidateRect(hOwnerWnd,0,TRUE));
}
- ::DrawMenuBar(GetOwnerHWnd());
+ RedrawMenuBar();
+}
+
+/**
+ * If the menu changes after the system has created the window,
+ * this function must be called to draw the changed menu bar.
+ */
+void AwtMenuBar::RedrawMenuBar() {
+ VERIFY(::DrawMenuBar(GetOwnerHWnd()));
}
LRESULT AwtMenuBar::WinThreadExecProc(ExecuteArgs * args)
@@ -232,7 +240,7 @@
if (::IsWindow(m->GetOwnerHWnd()))
{
/* The menu was already created and added during peer creation -- redraw */
- ::DrawMenuBar(m->GetOwnerHWnd());
+ m->RedrawMenuBar();
}
ret:
env->DeleteGlobalRef(self);
--- a/jdk/src/windows/native/sun/windows/awt_MenuBar.h Fri Jul 15 19:24:09 2011 +0400
+++ b/jdk/src/windows/native/sun/windows/awt_MenuBar.h Fri Jul 15 19:25:06 2011 +0400
@@ -65,6 +65,7 @@
INLINE AwtFrame* GetFrame() { return m_frame; }
virtual HWND GetOwnerHWnd();
+ virtual void RedrawMenuBar();
AwtMenuItem* GetItem(jobject target, long index);
int CountItem(jobject menuBar);
--- a/jdk/src/windows/native/sun/windows/awt_MenuItem.cpp Fri Jul 15 19:24:09 2011 +0400
+++ b/jdk/src/windows/native/sun/windows/awt_MenuItem.cpp Fri Jul 15 19:25:06 2011 +0400
@@ -626,7 +626,7 @@
mii.dwTypeData = (LPTSTR)(*sb);
// find index by menu item id
- int nMenuItemCount = ::GetMenuItemCount(hMenu);;
+ int nMenuItemCount = ::GetMenuItemCount(hMenu);
int idx;
for (idx = 0; (idx < nMenuItemCount); idx++) {
memset(&mii1, 0, sizeof(MENUITEMINFO));
@@ -639,10 +639,7 @@
::RemoveMenu(hMenu, idx, MF_BYPOSITION);
::InsertMenuItem(hMenu, idx, TRUE, &mii);
- // Redraw menu bar if it was affected.
- if (menu->GetMenuBar() == menu) {
- ::DrawMenuBar(menu->GetOwnerHWnd());
- }
+ RedrawMenuBar();
}
void AwtMenuItem::Enable(BOOL isEnabled)
@@ -658,10 +655,7 @@
MF_BYCOMMAND | (isEnabled ? MF_ENABLED : MF_GRAYED))
!= 0xFFFFFFFF);
- // Redraw menu bar if it was affected.
- if (menu->GetMenuBar() == menu) {
- ::DrawMenuBar(menu->GetOwnerHWnd());
- }
+ RedrawMenuBar();
}
void AwtMenuItem::SetState(BOOL isChecked)
@@ -676,23 +670,31 @@
MF_BYCOMMAND | (isChecked ? MF_CHECKED : MF_UNCHECKED))
!= 0xFFFFFFFF);
- // Redraw menu bar if it was affected.
- if (menu->GetMenuBar() == menu) {
- ::DrawMenuBar(menu->GetOwnerHWnd());
+ RedrawMenuBar();
+}
+
+/**
+ * If the menu changes after the system has created the window,
+ * this function must be called to draw the changed menu bar.
+ */
+void AwtMenuItem::RedrawMenuBar() {
+ AwtMenu* menu = GetMenuContainer();
+ if (menu != NULL && menu->GetMenuBar() == menu){
+ menu->RedrawMenuBar();
+ }
+}
+
+void AwtMenuItem::UpdateContainerLayout() {
+ AwtMenu* menu = GetMenuContainer();
+ if (menu != NULL) {
+ DASSERT(menu != NULL && GetID() >= 0);
+ menu->UpdateLayout();
}
}
LRESULT AwtMenuItem::WinThreadExecProc(ExecuteArgs * args)
{
switch( args->cmdId ) {
- case MENUITEM_SETLABEL:
- {
- LPCTSTR sb = (LPCTSTR)args->param1;
- DASSERT(!IsBadStringPtr(sb, 20));
- this->SetLabel(sb);
- }
- break;
-
case MENUITEM_ENABLE:
{
BOOL isEnabled = (BOOL)args->param1;
@@ -714,75 +716,98 @@
return 0L;
}
-void AwtMenuItem::_SetLabel(void *param)
-{
- JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
+void AwtMenuItem::_SetLabel(void *param) {
+ if (AwtToolkit::IsMainThread()) {
+ JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
- SetLabelStruct *sls = (SetLabelStruct *)param;
- jobject self = sls->menuitem;
- jstring label = sls->label;
+ SetLabelStruct *sls = (SetLabelStruct *)param;
+ jobject self = sls->menuitem;
+ jstring label = sls->label;
- int badAlloc = 0;
- AwtMenuItem *m = NULL;
+ int badAlloc = 0;
+ AwtMenuItem *m = NULL;
- PDATA pData;
- JNI_CHECK_PEER_GOTO(self, ret);
- m = (AwtMenuItem *)pData;
+ PDATA pData;
+ JNI_CHECK_PEER_GOTO(self, ret);
+ m = (AwtMenuItem *)pData;
// if (::IsWindow(m->GetOwnerHWnd()))
- {
- // fix for bug 4251036 MenuItem setLabel(null/"") behaves differently
- // under Win32 and Solaris
- jstring empty = NULL;
- if (JNU_IsNull(env, label))
{
- empty = JNU_NewStringPlatform(env, TEXT(""));
- }
- LPCTSTR labelPtr;
- if (empty != NULL)
- {
- labelPtr = JNU_GetStringPlatformChars(env, empty, 0);
- }
- else
- {
- labelPtr = JNU_GetStringPlatformChars(env, label, 0);
- }
- if (labelPtr == NULL)
- {
- badAlloc = 1;
- }
- else
- {
- ExecuteArgs args;
- args.cmdId = MENUITEM_SETLABEL;
- args.param1 = (LPARAM)labelPtr;
- m->WinThreadExecProc(&args);
+ // fix for bug 4251036 MenuItem setLabel(null/"") behaves differently
+ // under Win32 and Solaris
+ jstring empty = NULL;
+ if (JNU_IsNull(env, label))
+ {
+ empty = JNU_NewStringPlatform(env, TEXT(""));
+ }
+ LPCTSTR labelPtr;
if (empty != NULL)
{
- JNU_ReleaseStringPlatformChars(env, empty, labelPtr);
+ labelPtr = JNU_GetStringPlatformChars(env, empty, 0);
+ }
+ else
+ {
+ labelPtr = JNU_GetStringPlatformChars(env, label, 0);
+ }
+ if (labelPtr == NULL)
+ {
+ badAlloc = 1;
}
else
{
- JNU_ReleaseStringPlatformChars(env, label, labelPtr);
+ DASSERT(!IsBadStringPtr(labelPtr, 20));
+ m->SetLabel(labelPtr);
+ if (empty != NULL)
+ {
+ JNU_ReleaseStringPlatformChars(env, empty, labelPtr);
+ }
+ else
+ {
+ JNU_ReleaseStringPlatformChars(env, label, labelPtr);
+ }
+ }
+ if (empty != NULL)
+ {
+ env->DeleteLocalRef(empty);
}
}
- if (empty != NULL)
- {
- env->DeleteLocalRef(empty);
- }
- }
ret:
- env->DeleteGlobalRef(self);
- if (label != NULL)
- {
- env->DeleteGlobalRef(label);
+ env->DeleteGlobalRef(self);
+ if (label != NULL)
+ {
+ env->DeleteGlobalRef(label);
+ }
+
+ delete sls;
+
+ if (badAlloc)
+ {
+ throw std::bad_alloc();
+ }
+ } else {
+ AwtToolkit::GetInstance().InvokeFunction(AwtMenuItem::_SetLabel, param);
}
+}
- delete sls;
+void AwtMenuItem::_UpdateLayout(void *param)
+{
+ if (AwtToolkit::IsMainThread()) {
+ JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
+
+ jobject self = (jobject)param;
+
+ AwtMenuItem *m = NULL;
- if (badAlloc)
- {
- throw std::bad_alloc();
+ PDATA pData;
+ JNI_CHECK_PEER_GOTO(self, ret);
+
+ m = (AwtMenuItem *)pData;
+
+ m->UpdateContainerLayout();
+ret:
+ env->DeleteGlobalRef(self);
+ } else {
+ AwtToolkit::GetInstance().InvokeFunction(AwtMenuItem::_UpdateLayout, param);
}
}
@@ -883,8 +908,8 @@
/*
* Class: sun_awt_windows_WMenuItemPeer
- * Method: _setLabel
- * Signature: (Ljava/lang/String;)V
+ * Method: initIDs
+ * Signature: ()V
*/
JNIEXPORT void JNICALL
Java_sun_awt_windows_WMenuItemPeer_initIDs(JNIEnv *env, jclass cls)
@@ -927,6 +952,26 @@
/*
* Class: sun_awt_windows_WMenuItemPeer
+ * Method: _setFont
+ * Signature: (Ljava/awt/Font;)V
+ */
+JNIEXPORT void JNICALL
+Java_sun_awt_windows_WMenuItemPeer__1setFont(JNIEnv *env, jobject self, jobject)
+{
+ TRY;
+
+ jobject selfGlobalRef = env->NewGlobalRef(self);
+
+ // Current implementation of AwtMenuItem get font attribute from the peer
+ // directly, so we ignore it here, but update current menu layout.
+ AwtToolkit::GetInstance().SyncCall(AwtMenuItem::_UpdateLayout, selfGlobalRef);
+ // selfGlobalRef is deleted in _UpdateLayout
+
+ CATCH_BAD_ALLOC;
+}
+
+/*
+ * Class: sun_awt_windows_WMenuItemPeer
* Method: create
* Signature: (Lsun/awt/windows/WMenuPeer;)V
*/
--- a/jdk/src/windows/native/sun/windows/awt_MenuItem.h Fri Jul 15 19:24:09 2011 +0400
+++ b/jdk/src/windows/native/sun/windows/awt_MenuItem.h Fri Jul 15 19:25:06 2011 +0400
@@ -48,7 +48,6 @@
public:
// id's for methods executed on toolkit thread
enum {
- MENUITEM_SETLABEL,
MENUITEM_ENABLE,
MENUITEM_SETSTATE,
MENUITEM_LAST
@@ -78,7 +77,6 @@
virtual LPCTSTR GetClassName();
- void AwtMenuItem::LinkObjects(jobject peer);
static AwtMenuItem* Create(jobject self, jobject menu);
INLINE AwtMenu* GetMenuContainer() { return m_menuContainer; }
@@ -148,6 +146,8 @@
void SetLabel(LPCTSTR sb);
virtual void Enable(BOOL isEnabled);
+ virtual void UpdateContainerLayout();
+ virtual void RedrawMenuBar();
void SetState(BOOL isChecked);
/*
@@ -163,6 +163,7 @@
// invoked on Toolkit thread
static void _SetLabel(void *param);
+ static void _UpdateLayout(void *param);
protected:
AwtMenu* m_menuContainer; /* The menu object containing this item */