1 /* 2 * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 #include "awt_MenuBar.h" 27 #include "awt_Frame.h" 28 29 /* IMPORTANT! Read the README.JNI file for notes on JNI converted AWT code. 30 */ 31 32 /***********************************************************************/ 33 // struct for _DelItem() method 34 struct DelItemStruct { 35 jobject menuitem; 36 jint index; 37 }; 38 /***********************************************************************/ 39 // struct for _AddMenu() method 40 struct AddMenuStruct { 41 jobject menubar; 42 jobject menu; 43 }; 44 /************************************************************************ 45 * AwtMenuBar fields 46 */ 47 48 jmethodID AwtMenuBar::getMenuMID; 49 jmethodID AwtMenuBar::getMenuCountMID; 50 51 52 /************************************************************************ 53 * AwtMenuBar methods 54 */ 55 56 57 AwtMenuBar::AwtMenuBar() { 58 m_frame = NULL; 59 } 60 61 AwtMenuBar::~AwtMenuBar() 62 { 63 } 64 65 void AwtMenuBar::Dispose() 66 { 67 if (m_frame != NULL && m_frame->GetMenuBar() == this) { 68 m_frame->SetMenuBar(NULL); 69 } 70 m_frame = NULL; 71 72 AwtMenu::Dispose(); 73 } 74 75 LPCTSTR AwtMenuBar::GetClassName() { 76 return TEXT("SunAwtMenuBar"); 77 } 78 79 /* Create a new AwtMenuBar object and menu. */ 80 AwtMenuBar* AwtMenuBar::Create(jobject self, jobject framePeer) 81 { 82 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 83 84 jobject target = NULL; 85 AwtMenuBar* menuBar = NULL; 86 87 try { 88 if (env->EnsureLocalCapacity(1) < 0) { 89 return NULL; 90 } 91 92 /* target is a java.awt.MenuBar */ 93 target = env->GetObjectField(self, AwtObject::targetID); 94 JNI_CHECK_NULL_GOTO(target, "null target", done); 95 96 menuBar = new AwtMenuBar(); 97 98 SetLastError(0); 99 HMENU hMenu = ::CreateMenu(); 100 // fix for 5088782 101 if (!CheckMenuCreation(env, self, hMenu)) 102 { 103 env->DeleteLocalRef(target); 104 return NULL; 105 } 106 107 menuBar->SetHMenu(hMenu); 108 109 menuBar->LinkObjects(env, self); 110 if (framePeer != NULL) { 111 PDATA pData; 112 JNI_CHECK_PEER_GOTO(framePeer, done); 113 menuBar->m_frame = (AwtFrame *)pData; 114 } else { 115 menuBar->m_frame = NULL; 116 } 117 } catch (...) { 118 env->DeleteLocalRef(target); 119 throw; 120 } 121 122 done: 123 if (target != NULL) { 124 env->DeleteLocalRef(target); 125 } 126 127 return menuBar; 128 } 129 130 HWND AwtMenuBar::GetOwnerHWnd() 131 { 132 AwtFrame *myFrame = m_frame; 133 if (myFrame == NULL) 134 return NULL; 135 else 136 return myFrame->GetHWnd(); 137 } 138 139 int AwtMenuBar::CountItem(jobject menuBar) 140 { 141 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 142 jint nCount = env->CallIntMethod(menuBar, AwtMenuBar::getMenuCountMID); 143 DASSERT(!safe_ExceptionOccurred(env)); 144 145 return nCount; 146 } 147 148 AwtMenuItem* AwtMenuBar::GetItem(jobject target, long index) 149 { 150 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 151 if (env->EnsureLocalCapacity(2) < 0) { 152 return NULL; 153 } 154 155 jobject menu = env->CallObjectMethod(target, AwtMenuBar::getMenuMID,index); 156 if (!menu) return NULL; // menu item was removed concurrently 157 DASSERT(!safe_ExceptionOccurred(env)); 158 159 jobject menuItemPeer = GetPeerForTarget(env, menu); 160 PDATA pData; 161 AwtMenuItem* awtMenuItem = NULL; 162 JNI_CHECK_PEER_GOTO(menuItemPeer, done); 163 awtMenuItem = (AwtMenuItem*)pData; 164 165 done: 166 env->DeleteLocalRef(menu); 167 env->DeleteLocalRef(menuItemPeer); 168 169 return awtMenuItem; 170 } 171 172 void AwtMenuBar::DrawItem(DRAWITEMSTRUCT& drawInfo) 173 { 174 DASSERT(drawInfo.CtlType == ODT_MENU); 175 AwtMenu::DrawItems(drawInfo); 176 } 177 178 void AwtMenuBar::MeasureItem(HDC hDC, 179 MEASUREITEMSTRUCT& measureInfo) 180 { 181 DASSERT(measureInfo.CtlType == ODT_MENU); 182 AwtMenu::MeasureItem(hDC, measureInfo); 183 } 184 185 void AwtMenuBar::AddItem(AwtMenuItem* item) 186 { 187 AwtMenu::AddItem(item); 188 HWND hOwnerWnd = GetOwnerHWnd(); 189 if (hOwnerWnd != NULL) { 190 VERIFY(::InvalidateRect(hOwnerWnd,0,TRUE)); 191 } 192 } 193 194 void AwtMenuBar::DeleteItem(UINT index) 195 { 196 AwtMenu::DeleteItem(index); 197 HWND hOwnerWnd = GetOwnerHWnd(); 198 if (hOwnerWnd != NULL) { 199 VERIFY(::InvalidateRect(hOwnerWnd,0,TRUE)); 200 } 201 RedrawMenuBar(); 202 } 203 204 /** 205 * If the menu changes after the system has created the window, 206 * this function must be called to draw the changed menu bar. 207 */ 208 void AwtMenuBar::RedrawMenuBar() { 209 HWND hOwnerWnd = GetOwnerHWnd(); 210 if (hOwnerWnd != NULL) { 211 VERIFY(::DrawMenuBar(hOwnerWnd)); 212 } 213 } 214 215 void AwtMenuBar::_AddMenu(void *param) 216 { 217 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 218 219 AddMenuStruct *ams = (AddMenuStruct *)param; 220 jobject self = ams->menubar; 221 jobject menu = ams->menu; 222 223 AwtMenuBar *m = NULL; 224 225 PDATA pData; 226 JNI_CHECK_PEER_GOTO(self, ret); 227 JNI_CHECK_NULL_GOTO(menu, "null menu", ret); 228 m = (AwtMenuBar *)pData; 229 if (::IsWindow(m->GetOwnerHWnd())) 230 { 231 /* The menu was already created and added during peer creation -- redraw */ 232 m->RedrawMenuBar(); 233 } 234 ret: 235 env->DeleteGlobalRef(self); 236 if (menu != NULL) { 237 env->DeleteGlobalRef(menu); 238 } 239 240 delete ams; 241 } 242 243 void AwtMenuBar::_DelItem(void *param) 244 { 245 if (AwtToolkit::IsMainThread()) { 246 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 247 248 DelItemStruct *dis = (DelItemStruct*) param; 249 jobject self = dis->menuitem; 250 jint index = dis->index; 251 252 AwtMenuBar *m = NULL; 253 PDATA pData; 254 JNI_CHECK_PEER_GOTO(self, ret); 255 m = (AwtMenuBar *)pData; 256 m->DeleteItem(static_cast<UINT>(index)); 257 ret: 258 env->DeleteGlobalRef(self); 259 delete dis; 260 } else { 261 AwtToolkit::GetInstance().InvokeFunction(AwtMenuBar::_DelItem, param); 262 } 263 } 264 265 /************************************************************************ 266 * MenuBar native methods 267 */ 268 269 extern "C" { 270 271 /* 272 * Class: java_awt_MenuBar 273 * Method: initIDs 274 * Signature: ()V 275 */ 276 JNIEXPORT void JNICALL 277 Java_java_awt_MenuBar_initIDs(JNIEnv *env, jclass cls) 278 { 279 TRY; 280 281 AwtMenuBar::getMenuCountMID = env->GetMethodID(cls, "getMenuCountImpl", "()I"); 282 DASSERT(AwtMenuBar::getMenuCountMID != NULL); 283 CHECK_NULL(AwtMenuBar::getMenuCountMID); 284 285 AwtMenuBar::getMenuMID = env->GetMethodID(cls, "getMenuImpl", 286 "(I)Ljava/awt/Menu;"); 287 DASSERT(AwtMenuBar::getMenuMID != NULL); 288 289 CATCH_BAD_ALLOC; 290 } 291 292 } /* extern "C" */ 293 294 295 /************************************************************************ 296 * WMenuBarPeer native methods 297 */ 298 299 extern "C" { 300 301 /* 302 * Class: sun_awt_windows_WMenuBarPeer 303 * Method: addMenu 304 * Signature: (Ljava/awt/Menu;)V 305 */ 306 JNIEXPORT void JNICALL 307 Java_sun_awt_windows_WMenuBarPeer_addMenu(JNIEnv *env, jobject self, 308 jobject menu) 309 { 310 TRY; 311 312 AddMenuStruct *ams = new AddMenuStruct; 313 ams->menubar = env->NewGlobalRef(self); 314 ams->menu = env->NewGlobalRef(menu); 315 316 AwtToolkit::GetInstance().SyncCall(AwtMenuBar::_AddMenu, ams); 317 // global refs and ams are deleted in _AddMenu() 318 319 CATCH_BAD_ALLOC; 320 } 321 322 /* 323 * Class: sun_awt_windows_WMenuBarPeer 324 * Method: delMenu 325 * Signature: (I)V 326 */ 327 JNIEXPORT void JNICALL 328 Java_sun_awt_windows_WMenuBarPeer_delMenu(JNIEnv *env, jobject self, 329 jint index) 330 { 331 TRY; 332 333 DelItemStruct *dis = new DelItemStruct; 334 dis->menuitem = env->NewGlobalRef(self); 335 dis->index = index; 336 337 AwtToolkit::GetInstance().SyncCall(AwtMenuBar::_DelItem, dis); 338 // global refs and dis are deleted in _DelItem 339 340 CATCH_BAD_ALLOC; 341 } 342 343 /* 344 * Class: sun_awt_windows_WMenuBarPeer 345 * Method: create 346 * Signature: (Lsun/awt/windows/WFramePeer;)V 347 */ 348 JNIEXPORT void JNICALL 349 Java_sun_awt_windows_WMenuBarPeer_create(JNIEnv *env, jobject self, 350 jobject frame) 351 { 352 TRY; 353 354 AwtToolkit::CreateComponent(self, frame, 355 (AwtToolkit::ComponentFactory) 356 AwtMenuBar::Create); 357 CATCH_BAD_ALLOC; 358 } 359 360 } /* extern "C" */