1 /*
   2  * Copyright (c) 2011, 2016, 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:NSDefaultMallocZone()] initWithTitle:@"Menubar"];
  64     }
  65     return self;
  66 }
  67 
  68 - (void)dealloc
  69 {
  70     LOG("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 alloc] initWithTitle:title
  90                                                 action:NULL
  91                                          keyEquivalent:@""];
  92         [self->item setEnabled:(BOOL)jenabled];
  93         [self->item setTarget:self];
  94 
  95         self->menu = [[NSMenu alloc] 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 alloc] 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 alloc] 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     if (!jCallbackClass) {
 371         return;
 372     }
 373     jclass jMenuClass = [GlassHelper ClassForName:"com.sun.glass.ui.Menu" withEnv:env];
 374     if (!jMenuClass) {
 375         return;
 376     }
 377 
 378     jMenuActionMethod  = (*env)->GetMethodID(env, jCallbackClass,   "action",  "()V");
 379     if ((*env)->ExceptionCheck(env)) return;
 380     jMenuValidateMethod = (*env)->GetMethodID(env, jCallbackClass,   "validate",  "()V");
 381     if ((*env)->ExceptionCheck(env)) return;
 382     jMenuOpeningMethod = (*env)->GetMethodID(env, jMenuClass, "notifyMenuOpening", "()V");
 383     if ((*env)->ExceptionCheck(env)) return;
 384     jMenuClosedMethod  = (*env)->GetMethodID(env, jMenuClass, "notifyMenuClosed",  "()V");
 385     if ((*env)->ExceptionCheck(env)) return;
 386     jDelegateMenuField = (*env)->GetFieldID(env,  jMenuDelegateClass, "menu", "Lcom/sun/glass/ui/Menu;");
 387 }
 388 
 389 /*
 390  * Class:     com_sun_glass_ui_mac_MacMenuDelegate
 391  * Method:    _createMenu
 392  * Signature: (Ljava/lang/String;Z)J
 393  */
 394 JNIEXPORT jlong JNICALL Java_com_sun_glass_ui_mac_MacMenuDelegate__1createMenu
 395 (JNIEnv *env, jobject jMenuDelegate, jstring jTitle, jboolean jEnabled)
 396 {
 397     jlong value = 0L;
 398 
 399     GLASS_ASSERT_MAIN_JAVA_THREAD(env);
 400     GLASS_POOL_ENTER;
 401     {
 402         GlassMenu *menu = [[GlassMenu alloc] initWithJavajdelegate:jMenuDelegate
 403                                                             jtitle:jTitle
 404                                                           jenabled:jEnabled];
 405         value = ptr_to_jlong(menu);
 406     }
 407     GLASS_POOL_EXIT;
 408     GLASS_CHECK_EXCEPTION(env);
 409 
 410     NSString* title = [GlassHelper nsStringWithJavaString:jTitle withEnv:env];
 411     LOG("Java_com_sun_glass_ui_mac_MacMenuDelegate__1createMenu md %p title %s --> jMenuPtr %p ",
 412         jMenuDelegate, [title UTF8String], value);
 413 
 414     return value;
 415 }
 416 
 417 /*
 418  * Class:     com_sun_glass_ui_mac_MacMenuDelegate
 419  * Method:    _createMenuItem
 420  * Signature: (Ljava/lang/String;CILcom/sun/glass/ui/Pixels;ZZLcom/sun/glass/ui/MenuItem$Callback;)J
 421  */
 422 JNIEXPORT jlong JNICALL Java_com_sun_glass_ui_mac_MacMenuDelegate__1createMenuItem
 423 (JNIEnv *env, jobject jMenuDelegate, jstring jTitle, jchar jShortcutKey, jint jShortcutModifiers,
 424  jobject jIcon, jboolean jEnabled, jboolean jChecked, jobject jCallback)
 425 {
 426     jlong value = 0L;
 427 
 428     GLASS_ASSERT_MAIN_JAVA_THREAD(env);
 429     GLASS_POOL_ENTER;
 430     {
 431         GlassMenu *menuItem = [[GlassMenu alloc] initWithJavajdelegate:jMenuDelegate
 432                                                                 jtitle:jTitle jshortcut:jShortcutKey
 433                                                             jmodifiers:jShortcutModifiers jicon:jIcon
 434                                                               jenabled:jEnabled jchecked:jChecked
 435                                                              jcallback:jCallback];
 436         value = ptr_to_jlong(menuItem);
 437     }
 438     GLASS_POOL_EXIT;
 439     GLASS_CHECK_EXCEPTION(env);
 440 
 441     NSString* title = [GlassHelper nsStringWithJavaString:jTitle withEnv:env];
 442     LOG("Java_com_sun_glass_ui_mac_MacMenuDelegate__1createMenuItem md %p title %s --> %p, value",
 443         jMenuDelegate, [title UTF8String], value);
 444 
 445     return value;
 446 }
 447 
 448 /*
 449  * Class:     com_sun_glass_ui_mac_MacMenuDelegate
 450  * Method:    _insert
 451  * Signature: (JJI)V
 452  */
 453 JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacMenuDelegate__1insert
 454 (JNIEnv *env, jobject jMenuDelegate, jlong jMenuPtr, jlong jSubmenuPtr, jint jPos)
 455 {
 456     LOG("Java_com_sun_glass_ui_mac_MacMenuDelegate__1insert del %p mp %p smp %p pos %d",
 457         jMenuDelegate, jMenuPtr, jSubmenuPtr, jPos);
 458 
 459     GLASS_ASSERT_MAIN_JAVA_THREAD(env);
 460     GLASS_POOL_ENTER;
 461     {
 462         GlassMenu *menu = (GlassMenu *)jlong_to_ptr(jMenuPtr);
 463 
 464         if (jSubmenuPtr != 0)
 465         {
 466             GlassMenu *submenu = (GlassMenu *)jlong_to_ptr(jSubmenuPtr);
 467             [menu->menu insertItem:submenu->item atIndex:jPos];
 468             [menu->menu setSubmenu:submenu->menu forItem:submenu->item];
 469 
 470             [submenu->menu setAutoenablesItems:YES];
 471         }
 472         else
 473         {
 474             [menu->menu addItem:[NSMenuItem separatorItem]];
 475         }
 476     }
 477     GLASS_POOL_EXIT;
 478     GLASS_CHECK_EXCEPTION(env);
 479 }
 480 
 481 /*
 482  * Class:     com_sun_glass_ui_mac_MacMenuDelegate
 483  * Method:    _remove
 484  * Signature: (JJI)V
 485  */
 486 JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacMenuDelegate__1remove
 487 (JNIEnv *env, jobject jMenuDelegate, jlong jMenuPtr, jlong jSubmenuPtr, jint jPos)
 488 {
 489     LOG("Java_com_sun_glass_ui_mac_MacMenuDelegate__1remove del %p mp %p smp %p pos %d",
 490         jMenuDelegate, jMenuPtr, jSubmenuPtr, jPos);
 491 
 492     GLASS_ASSERT_MAIN_JAVA_THREAD(env);
 493     GLASS_POOL_ENTER;
 494     {
 495         GlassMenu *menu = (GlassMenu *)jlong_to_ptr(jMenuPtr);
 496         if (jSubmenuPtr != 0)
 497         {
 498             GlassMenu *submenu = (GlassMenu *)jlong_to_ptr(jSubmenuPtr);
 499             LOG("Java_com_sun_glass_ui_mac_MacMenuDelegate__1remove: submenu %p subitem %p subindex %d",
 500                 submenu, submenu->item, [menu->menu indexOfItem: submenu->item]);
 501 
 502             if ([menu->menu indexOfItem: submenu->item] != -1) {
 503                 [menu->menu removeItem:submenu->item];
 504             }
 505         }
 506         else
 507         {
 508             LOG("Java_com_sun_glass_ui_mac_MacMenuDelegate__1remove: at index %d", jPos);
 509             [menu->menu removeItemAtIndex:jPos];
 510         }
 511         [[NSApp mainMenu] update];
 512     }
 513     GLASS_POOL_EXIT;
 514     GLASS_CHECK_EXCEPTION(env);
 515 }
 516 
 517 /*
 518  * Class:     com_sun_glass_ui_mac_MacMenuDelegate
 519  * Method:    _setTitle
 520  * Signature: (JLjava/lang/String;)V
 521  */
 522 JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacMenuDelegate__1setTitle
 523 (JNIEnv *env, jobject jMenuDelegate, jlong jMenuPtr, jstring jTitle)
 524 {
 525     LOG("Java_com_sun_glass_ui_mac_MacMenuDelegate__1setTitle");
 526 
 527     GLASS_ASSERT_MAIN_JAVA_THREAD(env);
 528     GLASS_POOL_ENTER;
 529     {
 530         GlassMenu *menu = (GlassMenu *)jlong_to_ptr(jMenuPtr);
 531         NSInteger index = [[NSApp mainMenu] indexOfItem: menu->item];
 532         NSString *title = [GlassHelper nsStringWithJavaString:jTitle withEnv:env];
 533         if (index != -1) {
 534             [[[[NSApp mainMenu] itemAtIndex:index] submenu] setTitle: title];
 535         } else {
 536             [menu->item setTitle:title];
 537         }
 538     }
 539     GLASS_POOL_EXIT;
 540     GLASS_CHECK_EXCEPTION(env);
 541 }
 542 
 543 /*
 544  * Class:     com_sun_glass_ui_mac_MacMenuDelegate
 545  * Method:    _setShortcut
 546  * Signature: (JCI)V
 547  */
 548 JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacMenuDelegate__1setShortcut
 549 (JNIEnv *env, jobject jMenuDelegate, jlong jMenuPtr, jchar jShortcut, jint jModifiers)
 550 {
 551     LOG("Java_com_sun_glass_ui_mac_MacMenuDelegate__1setShortcut");
 552 
 553     GLASS_ASSERT_MAIN_JAVA_THREAD(env);
 554     GLASS_POOL_ENTER;
 555     {
 556         GlassMenu *menu = (GlassMenu *)jlong_to_ptr(jMenuPtr);
 557         [menu _setShortcut:jShortcut modifiers:jModifiers];
 558     }
 559     GLASS_POOL_EXIT;
 560     GLASS_CHECK_EXCEPTION(env);
 561 }
 562 
 563 /*
 564  * Class:     com_sun_glass_ui_mac_MacMenuDelegate
 565  * Method:    _setEnabled
 566  * Signature: (JZ)V
 567  */
 568 JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacMenuDelegate__1setEnabled
 569 (JNIEnv *env, jobject jMenuDelegate, jlong jMenuPtr, jboolean jEnabled)
 570 {
 571     LOG("Java_com_sun_glass_ui_mac_MacMenuDelegate__1setEnabled");
 572 
 573     GLASS_ASSERT_MAIN_JAVA_THREAD(env);
 574     GLASS_POOL_ENTER;
 575     {
 576         GlassMenu *menu = (GlassMenu *)jlong_to_ptr(jMenuPtr);
 577         [menu->item setEnabled:(BOOL)jEnabled];
 578     }
 579     GLASS_POOL_EXIT;
 580     GLASS_CHECK_EXCEPTION(env);
 581 }
 582 
 583 /*
 584  * Class:     com_sun_glass_ui_mac_MacMenuDelegate
 585  * Method:    _setChecked
 586  * Signature: (JZ)V
 587  */
 588 JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacMenuDelegate__1setChecked
 589 (JNIEnv *env, jobject jMenuDelegate, jlong jMenuPtr, jboolean jChecked)
 590 {
 591     LOG("Java_com_sun_glass_ui_mac_MacMenuDelegate__1setChecked");
 592 
 593     GLASS_ASSERT_MAIN_JAVA_THREAD(env);
 594     GLASS_POOL_ENTER;
 595     {
 596         GlassMenu *menu = (GlassMenu *)jlong_to_ptr(jMenuPtr);
 597         [menu _setChecked:(BOOL)jChecked];
 598     }
 599     GLASS_POOL_EXIT;
 600     GLASS_CHECK_EXCEPTION(env);
 601 }
 602 
 603 /*
 604  * Class:     com_sun_glass_ui_mac_MacMenuDelegate
 605  * Method:    _setCallback
 606  * Signature: (JLcom/sun/glass/ui/MenuItem$Callback;)V
 607  */
 608 JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacMenuDelegate__1setCallback
 609 (JNIEnv *env, jobject jMenuDelegate, jlong jMenuPtr, jobject jCallback)
 610 {
 611     LOG("Java_com_sun_glass_ui_mac_MacMenuDelegate__1setCallback");
 612 
 613     GLASS_ASSERT_MAIN_JAVA_THREAD(env);
 614     GLASS_POOL_ENTER;
 615     {
 616         GlassMenu *menu = (GlassMenu *)jlong_to_ptr(jMenuPtr);
 617         GET_MAIN_JENV;
 618         (*env)->DeleteGlobalRef(env, menu->jCallback);
 619         if (jCallback != NULL)
 620         {
 621             menu->jCallback = (*env)->NewGlobalRef(env, jCallback);
 622         }
 623     }
 624     GLASS_POOL_EXIT;
 625     GLASS_CHECK_EXCEPTION(env);
 626 }
 627 
 628 /*
 629  * Class:     com_sun_glass_ui_mac_MacMenuDelegate
 630  * Method:    _setPixels
 631  * Signature: (JLcom/sun/glass/ui/Pixels;)V
 632  */
 633 JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacMenuDelegate__1setPixels
 634 (JNIEnv *env, jobject jMenuDelegate, jlong jMenuPtr, jobject jPixels)
 635 {
 636     LOG("Java_com_sun_glass_ui_mac_MacMenuDelegate__1setPixels");
 637 
 638     GLASS_ASSERT_MAIN_JAVA_THREAD(env);
 639     GLASS_POOL_ENTER;
 640     {
 641         GlassMenu *menu = (GlassMenu *)jlong_to_ptr(jMenuPtr);
 642         [menu _setPixels:jPixels];
 643     }
 644     GLASS_POOL_EXIT;
 645     GLASS_CHECK_EXCEPTION(env);
 646 }