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
AwtMenuBar()57 AwtMenuBar::AwtMenuBar() {
58 m_frame = NULL;
59 }
60
~AwtMenuBar()61 AwtMenuBar::~AwtMenuBar()
62 {
63 }
64
Dispose()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
GetClassName()75 LPCTSTR AwtMenuBar::GetClassName() {
76 return TEXT("SunAwtMenuBar");
77 }
78
79 /* Create a new AwtMenuBar object and menu. */
Create(jobject self,jobject framePeer)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
GetOwnerHWnd()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
CountItem(jobject menuBar)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
GetItem(jobject target,long index)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
DrawItem(DRAWITEMSTRUCT & drawInfo)172 void AwtMenuBar::DrawItem(DRAWITEMSTRUCT& drawInfo)
173 {
174 DASSERT(drawInfo.CtlType == ODT_MENU);
175 AwtMenu::DrawItems(drawInfo);
176 }
177
MeasureItem(HDC hDC,MEASUREITEMSTRUCT & measureInfo)178 void AwtMenuBar::MeasureItem(HDC hDC,
179 MEASUREITEMSTRUCT& measureInfo)
180 {
181 DASSERT(measureInfo.CtlType == ODT_MENU);
182 AwtMenu::MeasureItem(hDC, measureInfo);
183 }
184
AddItem(AwtMenuItem * item)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
DeleteItem(UINT index)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 */
RedrawMenuBar()208 void AwtMenuBar::RedrawMenuBar() {
209 HWND hOwnerWnd = GetOwnerHWnd();
210 if (hOwnerWnd != NULL) {
211 VERIFY(::DrawMenuBar(hOwnerWnd));
212 }
213 }
214
_AddMenu(void * param)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
_DelItem(void * param)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
Java_java_awt_MenuBar_initIDs(JNIEnv * env,jclass cls)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
Java_sun_awt_windows_WMenuBarPeer_addMenu(JNIEnv * env,jobject self,jobject menu)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
Java_sun_awt_windows_WMenuBarPeer_delMenu(JNIEnv * env,jobject self,jint index)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
Java_sun_awt_windows_WMenuBarPeer_create(JNIEnv * env,jobject self,jobject frame)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" */
361