1 /*
   2  * Copyright (c) 2011, 2014, 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 #import "common.h"
  27 #import "com_sun_glass_events_KeyEvent.h"
  28 #import "com_sun_glass_ui_mac_MacMenuBarDelegate.h"
  29 #import "com_sun_glass_ui_mac_MacMenuDelegate.h"
  30 
  31 #import "GlassMacros.h"
  32 #import "GlassMenu.h"
  33 #import "GlassHelper.h"
  34 #import "GlassKey.h"
  35 
  36 //#define VERBOSE
  37 #ifndef VERBOSE
  38     #define LOG(MSG, ...)
  39 #else
  40     #define LOG(MSG, ...) GLASS_LOG(MSG, ## __VA_ARGS__);
  41 #endif
  42 
  43 static jmethodID jMenuActionMethod = 0;
  44 static jmethodID jMenuOpeningMethod = 0;
  45 static jmethodID jMenuClosedMethod = 0;
  46 static jmethodID jMenuValidateMethod = 0;
  47 static jfieldID  jDelegateMenuField = 0;
  48 
  49 @interface NSMenuItem (SPI)
  50 
  51 // Apple's SPI
  52 - setAppleMenu:(NSMenuItem*)item;
  53 
  54 @end
  55 
  56 @implementation GlassMenubar
  57 
  58 - (id)init
  59 {
  60     self = [super init];
  61     if (self != nil)
  62     {
  63         self->menu = [[NSMenu allocWithZone:[NSMenu menuZone]] initWithTitle:@"Menubar"];
  64     }
  65     return self;
  66 }
  67 
  68 - (void)dealloc
  69 {
  70     NSLog(@"GlassMenubar dealloc: %p", self);
  71     [super dealloc];
  72 }
  73 
  74 @end
  75 
  76 @implementation GlassMenu
  77 
  78 - (id)initWithJavajdelegate:(jobject)jdelegate jtitle:(jstring)jtitle jenabled:(jboolean)jenabled
  79 {
  80     self = [super init];
  81     if (self != nil)
  82     {
  83         GET_MAIN_JENV;
  84         self->jDelegate = (*env)->NewGlobalRef(env, jdelegate);
  85         NSString* title = [GlassHelper nsStringWithJavaString:jtitle withEnv:env];
  86         LOG("initWithJavajdelegate: jdelegate %p jtitle %s",
  87             jdelegate, [title UTF8String]);
  88 
  89         self->item = [[NSMenuItem allocWithZone:[NSMenu menuZone]] initWithTitle:title
  90                                                                           action:NULL
  91                                                                    keyEquivalent:@""];
  92         [self->item setEnabled:(BOOL)jenabled];
  93         [self->item setTarget:self];
  94 
  95         self->menu = [[NSMenu allocWithZone:[NSMenu menuZone]] initWithTitle:[self->item title]];
  96         [self->menu setDelegate: self];
  97     }
  98     return self;
  99 }
 100 
 101 - (id)initWithJavajdelegate:(jobject)jdelegate jtitle:(jstring)jtitle
 102                   jshortcut:(jchar)jshortcut jmodifiers:(int)jmodifiers jicon:(jobject)jicon
 103                    jenabled:(jboolean)jenabled jchecked:(jboolean)jchecked jcallback:(jobject)jcallback;
 104 {
 105     self = [super init];
 106     if (self != nil)
 107     {
 108         GET_MAIN_JENV;
 109         self->jDelegate = (*env)->NewGlobalRef(env, jdelegate);
 110         if (jcallback != NULL)
 111         {
 112             self->jCallback = (*env)->NewGlobalRef(env, jcallback);
 113         }
 114         
 115         NSString *shortcut = @"";
 116         NSString *title = [GlassHelper nsStringWithJavaString:jtitle withEnv:env];
 117         LOG("initWithJavajdelegate: jdelegate %p jcallback %p jtitle %s",
 118             jdelegate, jcallback, [title UTF8String]);
 119 
 120         self->item = [[NSMenuItem allocWithZone:[NSMenu menuZone]] initWithTitle:title
 121                                                                           action:@selector(action:)
 122                                                                    keyEquivalent:shortcut];
 123         if (jshortcut != '\0')
 124         {
 125             [self _setShortcut:jshortcut modifiers:jmodifiers];
 126         }
 127         [self->item setEnabled:(BOOL)jenabled];
 128         [self _setChecked:(BOOL)jchecked];
 129 
 130         if (jicon != NULL) {
 131             [self _setPixels:jicon];
 132         }
 133         [self->item setTarget:self];
 134     }
 135     return self;
 136 }
 137 
 138 - (void)dealloc
 139 {
 140     GET_MAIN_JENV;
 141     
 142     if (env != NULL)
 143     {
 144             if (self->jDelegate != NULL) 
 145         {
 146             (*env)->DeleteGlobalRef(env, self->jDelegate);
 147             self->jDelegate = NULL;
 148         }
 149             if (self->jCallback != NULL) 
 150         {
 151             (*env)->DeleteGlobalRef(env, self->jCallback);
 152             self->jCallback = NULL;
 153         }
 154     }
 155     
 156     [self->item release];
 157     
 158     [super dealloc];
 159 }
 160 
 161 - (void)action:(id)sender
 162 {
 163     if (self->jCallback != NULL)
 164     {
 165         GET_MAIN_JENV;
 166         if (env != NULL)
 167         {
 168             (*env)->CallVoidMethod(env, self->jCallback, jMenuActionMethod, NULL);
 169         }
 170     }
 171 }
 172 
 173 // RT-37304: do not use menuNeedsUpdate here, even though Cocoa prohibits
 174 // changing the menu structure during menuWillOpen...
 175 - (void)menuWillOpen: (NSMenu *)menu
 176 {
 177     GET_MAIN_JENV;
 178     if (env != NULL)
 179     {
 180         jobject jmenu = (*env)->GetObjectField(env, jDelegate, jDelegateMenuField);
 181         (*env)->CallVoidMethod(env, jmenu, jMenuOpeningMethod, NULL);
 182     }
 183 }
 184 
 185 - (void)menuDidClose: (NSMenu *)menu
 186 {
 187     GET_MAIN_JENV;
 188     if (env != NULL)
 189     {
 190         jobject jmenu = (*env)->GetObjectField(env, jDelegate, jDelegateMenuField);
 191         (*env)->CallVoidMethod(env, jmenu, jMenuClosedMethod, NULL);
 192     }
 193 }
 194 
 195 #pragma mark NSMenuValidation
 196 
 197 - (BOOL)validateMenuItem:(NSMenuItem *)menuItem
 198 {
 199     LOG("validateMenuItem: %s action: %p", [[menuItem title] UTF8String], [menuItem action]);
 200     GET_MAIN_JENV;
 201     if (env != NULL)
 202     {
 203         GlassMenu *glassTargetItem = (GlassMenu *)[menuItem target];
 204         (*env)->CallVoidMethod(env, self->jCallback, jMenuValidateMethod, NULL);
 205 
 206         return ([glassTargetItem->item isEnabled]);
 207     }
 208     return YES;
 209 }
 210 
 211 - (void)_setShortcut:(jchar)jshortcut modifiers:(jint)jmodifiers
 212 {
 213     NSString *shortcut = GetStringForJavaKey(jshortcut);
 214     LOG("_setShortcut %c -> %s", jshortcut, [shortcut UTF8String]);
 215     
 216     NSUInteger modifier = 0;
 217     if ((jmodifiers & com_sun_glass_events_KeyEvent_MODIFIER_COMMAND) != 0)
 218     {
 219         modifier = modifier | NSCommandKeyMask;
 220     }
 221     if ((jmodifiers & com_sun_glass_events_KeyEvent_MODIFIER_SHIFT) != 0)
 222     {
 223         modifier = modifier | NSShiftKeyMask;
 224     }
 225     if ((jmodifiers & com_sun_glass_events_KeyEvent_MODIFIER_CONTROL) != 0)
 226     {
 227         modifier = modifier | NSControlKeyMask;
 228     }
 229     if ((jmodifiers & com_sun_glass_events_KeyEvent_MODIFIER_OPTION) != 0)
 230     {
 231         modifier = modifier | NSAlternateKeyMask;
 232     }
 233     if ((jmodifiers & com_sun_glass_events_KeyEvent_MODIFIER_FUNCTION) != 0)
 234     {
 235         modifier = modifier | NSFunctionKeyMask;
 236         if (jshortcut >= com_sun_glass_events_KeyEvent_VK_F1 &&
 237             jshortcut <= com_sun_glass_events_KeyEvent_VK_F12) {
 238             int delta = jshortcut - com_sun_glass_events_KeyEvent_VK_F1;
 239             shortcut = [NSString stringWithFormat:@"%C", (unsigned short)(NSF1FunctionKey + delta)];
 240         } else if (jshortcut >= com_sun_glass_events_KeyEvent_VK_F13 &&
 241                    jshortcut <= com_sun_glass_events_KeyEvent_VK_F24) {
 242             int delta = jshortcut - com_sun_glass_events_KeyEvent_VK_F13;
 243             shortcut = [NSString stringWithFormat:@"%C", (unsigned short)(NSF13FunctionKey + delta)];
 244         }
 245     }
 246     [self->item setKeyEquivalent:shortcut];
 247     [self->item setKeyEquivalentModifierMask:modifier];
 248 }
 249 
 250 - (void)_setChecked:(BOOL)checked
 251 {
 252     [self->item setState:(checked ? NSOnState : NSOffState)];
 253 }
 254 
 255 - (void)_setPixels:(jobject)pixels
 256 {
 257     GET_MAIN_JENV;
 258     if (pixels != NULL)
 259     {
 260         pixels = (*env)->NewGlobalRef(env, pixels);
 261         NSImage *image = NULL;
 262         (*env)->CallVoidMethod(env, pixels, jPixelsAttachData, ptr_to_jlong(&image));
 263         if (image != NULL)
 264         {
 265             [self->item setImage: image];
 266             [image release];
 267         }
 268         (*env)->DeleteGlobalRef(env, pixels);
 269     }
 270     else
 271     {
 272         [self->item setImage: nil];
 273     }
 274 }
 275 
 276 @end
 277 
 278 #pragma mark --- JNI
 279 
 280 /*
 281  * Class:     com_sun_glass_ui_mac_MacMenuBarDelegate
 282  * Method:    _createMenuBar
 283  * Signature: ()J
 284  */
 285 JNIEXPORT jlong JNICALL Java_com_sun_glass_ui_mac_MacMenuBarDelegate__1createMenuBar
 286 (JNIEnv *env, jobject jMenuBarDelegate)
 287 {
 288     LOG("Java_com_sun_glass_ui_mac_MacMenuBarDelegate__1createMenuBar");
 289     
 290     jlong value = 0L;
 291     
 292     GLASS_ASSERT_MAIN_JAVA_THREAD(env);
 293     GLASS_POOL_ENTER;
 294     {
 295         GlassMenubar *menubar = [[GlassMenubar allocWithZone:[NSMenu menuZone]] init];
 296         value = ptr_to_jlong(menubar);
 297     }
 298     GLASS_POOL_EXIT;
 299     GLASS_CHECK_EXCEPTION(env);
 300     
 301     return value;
 302 }
 303 
 304 /*
 305  * Class:     com_sun_glass_ui_mac_MacMenuBarDelegate
 306  * Method:    _insert
 307  * Signature: (JJI)V
 308  */
 309 JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacMenuBarDelegate__1insert
 310 (JNIEnv *env, jobject jMenuDelegate, jlong jMenubarPtr, jlong jMenuPtr, jint jPos)
 311 {
 312     LOG("Java_com_sun_glass_ui_mac_MacMenuBarDelegate__1insert");
 313     
 314     GLASS_ASSERT_MAIN_JAVA_THREAD(env);
 315     GLASS_POOL_ENTER;
 316     {
 317         GlassMenubar *menubar = (GlassMenubar *)jlong_to_ptr(jMenubarPtr);
 318         GlassMenu *glassmenu = (GlassMenu *)jlong_to_ptr(jMenuPtr);
 319 
 320         [menubar->menu insertItem:glassmenu->item atIndex:jPos];
 321         [menubar->menu setSubmenu:glassmenu->menu forItem:glassmenu->item];
 322 
 323         [glassmenu->menu setAutoenablesItems:YES];
 324 
 325         if ([[glassmenu->item title] compare:@"Apple"] == NSOrderedSame)
 326         {
 327             [NSApp performSelector:@selector(setAppleMenu:) withObject:glassmenu->item];
 328         }
 329         
 330         [[NSApp mainMenu] update];
 331     }
 332     GLASS_POOL_EXIT;
 333     GLASS_CHECK_EXCEPTION(env);
 334 }
 335 
 336 /*
 337  * Class:     com_sun_glass_ui_mac_MacMenuBarDelegate
 338  * Method:    _remove
 339  * Signature: (JJI)V
 340  */
 341 JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacMenuBarDelegate__1remove
 342 (JNIEnv *env, jobject jMenuDelegate, jlong jMenubarPtr, jlong jMenuPtr, jint jPos)
 343 {
 344     LOG("Java_com_sun_glass_ui_mac_MacMenuBarDelegate__1remove del %p mb %p mp %p pos %d",
 345         jMenuDelegate, jMenubarPtr, jMenuPtr, jPos);
 346     
 347     GLASS_ASSERT_MAIN_JAVA_THREAD(env);
 348     GLASS_POOL_ENTER;
 349     {
 350         GlassMenubar *menubar = (GlassMenubar *)jlong_to_ptr(jMenubarPtr);
 351         GlassMenu *glassmenu = (GlassMenu *)jlong_to_ptr(jMenuPtr);
 352         if ([menubar->menu indexOfItem: glassmenu->item] != -1) {
 353             [menubar->menu removeItem:glassmenu->item];
 354         }
 355         [[NSApp mainMenu] update];
 356     }
 357     GLASS_POOL_EXIT;
 358     GLASS_CHECK_EXCEPTION(env);
 359 }
 360 
 361 /*
 362  * Class:     com_sun_glass_ui_mac_MacMenuDelegate
 363  * Method:    _initIDs
 364  * Signature: ()V
 365  */
 366 JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacMenuDelegate__1initIDs
 367 (JNIEnv *env, jclass jMenuDelegateClass)
 368 {
 369     jclass jCallbackClass = [GlassHelper ClassForName:"com.sun.glass.ui.MenuItem$Callback" withEnv:env];
 370     jclass jMenuClass = [GlassHelper ClassForName:"com.sun.glass.ui.Menu" withEnv:env];
 371     
 372     jMenuActionMethod  = (*env)->GetMethodID(env, jCallbackClass,   "action",  "()V");
 373     if ((*env)->ExceptionCheck(env)) return;
 374     jMenuValidateMethod = (*env)->GetMethodID(env, jCallbackClass,   "validate",  "()V");
 375     if ((*env)->ExceptionCheck(env)) return;
 376     jMenuOpeningMethod = (*env)->GetMethodID(env, jMenuClass, "notifyMenuOpening", "()V");
 377     if ((*env)->ExceptionCheck(env)) return;
 378     jMenuClosedMethod  = (*env)->GetMethodID(env, jMenuClass, "notifyMenuClosed",  "()V");
 379     if ((*env)->ExceptionCheck(env)) return;
 380     jDelegateMenuField = (*env)->GetFieldID(env,  jMenuDelegateClass, "menu", "Lcom/sun/glass/ui/Menu;");
 381 }
 382 
 383 /*
 384  * Class:     com_sun_glass_ui_mac_MacMenuDelegate
 385  * Method:    _createMenu
 386  * Signature: (Ljava/lang/String;Z)J
 387  */
 388 JNIEXPORT jlong JNICALL Java_com_sun_glass_ui_mac_MacMenuDelegate__1createMenu
 389 (JNIEnv *env, jobject jMenuDelegate, jstring jTitle, jboolean jEnabled)
 390 {
 391     jlong value = 0L;
 392     
 393     GLASS_ASSERT_MAIN_JAVA_THREAD(env);
 394     GLASS_POOL_ENTER;
 395     {
 396         GlassMenu *menu = [[GlassMenu alloc] initWithJavajdelegate:jMenuDelegate
 397                                                             jtitle:jTitle
 398                                                           jenabled:jEnabled];
 399         value = ptr_to_jlong(menu);
 400     }
 401     GLASS_POOL_EXIT;
 402     GLASS_CHECK_EXCEPTION(env);
 403     
 404     NSString* title = [GlassHelper nsStringWithJavaString:jTitle withEnv:env];
 405     LOG("Java_com_sun_glass_ui_mac_MacMenuDelegate__1createMenu md %p title %s --> jMenuPtr %p ",
 406         jMenuDelegate, [title UTF8String], value);
 407 
 408     return value;
 409 }
 410 
 411 /*
 412  * Class:     com_sun_glass_ui_mac_MacMenuDelegate
 413  * Method:    _createMenuItem
 414  * Signature: (Ljava/lang/String;CILcom/sun/glass/ui/Pixels;ZZLcom/sun/glass/ui/MenuItem$Callback;)J
 415  */
 416 JNIEXPORT jlong JNICALL Java_com_sun_glass_ui_mac_MacMenuDelegate__1createMenuItem
 417 (JNIEnv *env, jobject jMenuDelegate, jstring jTitle, jchar jShortcutKey, jint jShortcutModifiers,
 418  jobject jIcon, jboolean jEnabled, jboolean jChecked, jobject jCallback)
 419 {
 420     jlong value = 0L;
 421     
 422     GLASS_ASSERT_MAIN_JAVA_THREAD(env);
 423     GLASS_POOL_ENTER;
 424     {
 425         GlassMenu *menuItem = [[GlassMenu alloc] initWithJavajdelegate:jMenuDelegate
 426                                                                 jtitle:jTitle jshortcut:jShortcutKey
 427                                                             jmodifiers:jShortcutModifiers jicon:jIcon
 428                                                               jenabled:jEnabled jchecked:jChecked
 429                                                              jcallback:jCallback];
 430         value = ptr_to_jlong(menuItem);
 431     }
 432     GLASS_POOL_EXIT;
 433     GLASS_CHECK_EXCEPTION(env);
 434     
 435     NSString* title = [GlassHelper nsStringWithJavaString:jTitle withEnv:env];
 436     LOG("Java_com_sun_glass_ui_mac_MacMenuDelegate__1createMenuItem md %p title %s --> %p, value",
 437         jMenuDelegate, [title UTF8String], value);
 438 
 439     return value;
 440 }
 441 
 442 /*
 443  * Class:     com_sun_glass_ui_mac_MacMenuDelegate
 444  * Method:    _insert
 445  * Signature: (JJI)V
 446  */
 447 JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacMenuDelegate__1insert
 448 (JNIEnv *env, jobject jMenuDelegate, jlong jMenuPtr, jlong jSubmenuPtr, jint jPos)
 449 {
 450     LOG("Java_com_sun_glass_ui_mac_MacMenuDelegate__1insert del %p mp %p smp %p pos %d",
 451         jMenuDelegate, jMenuPtr, jSubmenuPtr, jPos);
 452 
 453     GLASS_ASSERT_MAIN_JAVA_THREAD(env);
 454     GLASS_POOL_ENTER;
 455     {
 456         GlassMenu *menu = (GlassMenu *)jlong_to_ptr(jMenuPtr);
 457 
 458         if (jSubmenuPtr != 0)
 459         {
 460             GlassMenu *submenu = (GlassMenu *)jlong_to_ptr(jSubmenuPtr);
 461             [menu->menu insertItem:submenu->item atIndex:jPos];
 462             [menu->menu setSubmenu:submenu->menu forItem:submenu->item];
 463 
 464             [submenu->menu setAutoenablesItems:YES];
 465         }
 466         else
 467         {
 468             [menu->menu addItem:[NSMenuItem separatorItem]];
 469         }
 470     }
 471     GLASS_POOL_EXIT;
 472     GLASS_CHECK_EXCEPTION(env);
 473 }
 474 
 475 /*
 476  * Class:     com_sun_glass_ui_mac_MacMenuDelegate
 477  * Method:    _remove
 478  * Signature: (JJI)V
 479  */
 480 JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacMenuDelegate__1remove
 481 (JNIEnv *env, jobject jMenuDelegate, jlong jMenuPtr, jlong jSubmenuPtr, jint jPos)
 482 {
 483     LOG("Java_com_sun_glass_ui_mac_MacMenuDelegate__1remove del %p mp %p smp %p pos %d",
 484         jMenuDelegate, jMenuPtr, jSubmenuPtr, jPos);
 485 
 486     GLASS_ASSERT_MAIN_JAVA_THREAD(env);
 487     GLASS_POOL_ENTER;
 488     {
 489         GlassMenu *menu = (GlassMenu *)jlong_to_ptr(jMenuPtr);
 490         if (jSubmenuPtr != 0)
 491         {
 492             GlassMenu *submenu = (GlassMenu *)jlong_to_ptr(jSubmenuPtr);
 493             LOG("Java_com_sun_glass_ui_mac_MacMenuDelegate__1remove: submenu %p subitem %p subindex %d",
 494                 submenu, submenu->item, [menu->menu indexOfItem: submenu->item]);
 495 
 496             if ([menu->menu indexOfItem: submenu->item] != -1) {
 497                 [menu->menu removeItem:submenu->item];
 498             }
 499         }
 500         else
 501         {
 502             LOG("Java_com_sun_glass_ui_mac_MacMenuDelegate__1remove: at index %d", jPos);
 503             [menu->menu removeItemAtIndex:jPos];
 504         }
 505         [[NSApp mainMenu] update];
 506     }
 507     GLASS_POOL_EXIT;
 508     GLASS_CHECK_EXCEPTION(env);
 509 }
 510 
 511 /*
 512  * Class:     com_sun_glass_ui_mac_MacMenuDelegate
 513  * Method:    _setTitle
 514  * Signature: (JLjava/lang/String;)V
 515  */
 516 JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacMenuDelegate__1setTitle
 517 (JNIEnv *env, jobject jMenuDelegate, jlong jMenuPtr, jstring jTitle)
 518 {
 519     LOG("Java_com_sun_glass_ui_mac_MacMenuDelegate__1setTitle");
 520     
 521     GLASS_ASSERT_MAIN_JAVA_THREAD(env);
 522     GLASS_POOL_ENTER;
 523     {
 524         GlassMenu *menu = (GlassMenu *)jlong_to_ptr(jMenuPtr);
 525         [menu->item setTitle:[GlassHelper nsStringWithJavaString:jTitle withEnv:env]];
 526     }
 527     GLASS_POOL_EXIT;
 528     GLASS_CHECK_EXCEPTION(env);
 529 }
 530 
 531 /*
 532  * Class:     com_sun_glass_ui_mac_MacMenuDelegate
 533  * Method:    _setShortcut
 534  * Signature: (JCI)V
 535  */
 536 JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacMenuDelegate__1setShortcut
 537 (JNIEnv *env, jobject jMenuDelegate, jlong jMenuPtr, jchar jShortcut, jint jModifiers)
 538 {
 539     LOG("Java_com_sun_glass_ui_mac_MacMenuDelegate__1setShortcut");
 540     
 541     GLASS_ASSERT_MAIN_JAVA_THREAD(env);
 542     GLASS_POOL_ENTER;
 543     {
 544         GlassMenu *menu = (GlassMenu *)jlong_to_ptr(jMenuPtr);
 545         [menu _setShortcut:jShortcut modifiers:jModifiers];
 546     }
 547     GLASS_POOL_EXIT;
 548     GLASS_CHECK_EXCEPTION(env);
 549 }
 550 
 551 /*
 552  * Class:     com_sun_glass_ui_mac_MacMenuDelegate
 553  * Method:    _setEnabled
 554  * Signature: (JZ)V
 555  */
 556 JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacMenuDelegate__1setEnabled
 557 (JNIEnv *env, jobject jMenuDelegate, jlong jMenuPtr, jboolean jEnabled)
 558 {
 559     LOG("Java_com_sun_glass_ui_mac_MacMenuDelegate__1setEnabled");
 560     
 561     GLASS_ASSERT_MAIN_JAVA_THREAD(env);
 562     GLASS_POOL_ENTER;
 563     {
 564         GlassMenu *menu = (GlassMenu *)jlong_to_ptr(jMenuPtr);
 565         [menu->item setEnabled:(BOOL)jEnabled];
 566     }
 567     GLASS_POOL_EXIT;
 568     GLASS_CHECK_EXCEPTION(env);
 569 }
 570 
 571 /*
 572  * Class:     com_sun_glass_ui_mac_MacMenuDelegate
 573  * Method:    _setChecked
 574  * Signature: (JZ)V
 575  */
 576 JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacMenuDelegate__1setChecked
 577 (JNIEnv *env, jobject jMenuDelegate, jlong jMenuPtr, jboolean jChecked)
 578 {
 579     LOG("Java_com_sun_glass_ui_mac_MacMenuDelegate__1setChecked");
 580     
 581     GLASS_ASSERT_MAIN_JAVA_THREAD(env);
 582     GLASS_POOL_ENTER;
 583     {
 584         GlassMenu *menu = (GlassMenu *)jlong_to_ptr(jMenuPtr);
 585         [menu _setChecked:(BOOL)jChecked];
 586     }
 587     GLASS_POOL_EXIT;
 588     GLASS_CHECK_EXCEPTION(env);
 589 }
 590 
 591 /*
 592  * Class:     com_sun_glass_ui_mac_MacMenuDelegate
 593  * Method:    _setCallback
 594  * Signature: (JLcom/sun/glass/ui/MenuItem$Callback;)V
 595  */
 596 JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacMenuDelegate__1setCallback
 597 (JNIEnv *env, jobject jMenuDelegate, jlong jMenuPtr, jobject jCallback)
 598 {
 599     LOG("Java_com_sun_glass_ui_mac_MacMenuDelegate__1setCallback");
 600     
 601     GLASS_ASSERT_MAIN_JAVA_THREAD(env);
 602     GLASS_POOL_ENTER;
 603     {
 604         GlassMenu *menu = (GlassMenu *)jlong_to_ptr(jMenuPtr);
 605         GET_MAIN_JENV;
 606         (*env)->DeleteGlobalRef(env, menu->jCallback);
 607         if (jCallback != NULL)
 608         {
 609             menu->jCallback = (*env)->NewGlobalRef(env, jCallback);
 610         }
 611     }
 612     GLASS_POOL_EXIT;
 613     GLASS_CHECK_EXCEPTION(env);
 614 }
 615 
 616 /*
 617  * Class:     com_sun_glass_ui_mac_MacMenuDelegate
 618  * Method:    _setPixels
 619  * Signature: (JLcom/sun/glass/ui/Pixels;)V
 620  */
 621 JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacMenuDelegate__1setPixels
 622 (JNIEnv *env, jobject jMenuDelegate, jlong jMenuPtr, jobject jPixels)
 623 {
 624     LOG("Java_com_sun_glass_ui_mac_MacMenuDelegate__1setPixels");
 625     
 626     GLASS_ASSERT_MAIN_JAVA_THREAD(env);
 627     GLASS_POOL_ENTER;
 628     {
 629         GlassMenu *menu = (GlassMenu *)jlong_to_ptr(jMenuPtr);
 630         [menu _setPixels:jPixels];
 631     }
 632     GLASS_POOL_EXIT;
 633     GLASS_CHECK_EXCEPTION(env);
 634 }