# HG changeset patch # User serb # Date 1310743506 -14400 # Node ID 0674614189ba646e7e1d6e56001ee3e6a4f0dff7 # Parent 67449ffe59914defaf12f5c9a4c1b0ed250c5c50 4717864: setFont() does not update Fonts of Menus already on screen Reviewed-by: art, bagiras diff -r 67449ffe5991 -r 0674614189ba jdk/src/windows/classes/sun/awt/windows/WMenuItemPeer.java --- 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); } } diff -r 67449ffe5991 -r 0674614189ba jdk/src/windows/native/sun/windows/awt_Menu.cpp --- 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(); } diff -r 67449ffe5991 -r 0674614189ba jdk/src/windows/native/sun/windows/awt_Menu.h --- 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; }; diff -r 67449ffe5991 -r 0674614189ba jdk/src/windows/native/sun/windows/awt_MenuBar.cpp --- 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); diff -r 67449ffe5991 -r 0674614189ba jdk/src/windows/native/sun/windows/awt_MenuBar.h --- 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); diff -r 67449ffe5991 -r 0674614189ba jdk/src/windows/native/sun/windows/awt_MenuItem.cpp --- 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 */ diff -r 67449ffe5991 -r 0674614189ba jdk/src/windows/native/sun/windows/awt_MenuItem.h --- 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 */