Path: blob/master/src/java.desktop/macosx/native/libosxui/ScreenMenu.m
41149 views
/*1* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425#import "ScreenMenu.h"2627#import "com_apple_laf_ScreenMenu.h"28#import "java_awt_Event.h"29#import "java_awt_event_KeyEvent.h"30#import "java_awt_event_InputEvent.h"31#import "java_awt_event_MouseEvent.h"3233#import <JavaRuntimeSupport/JavaRuntimeSupport.h>3435#import "ThreadUtilities.h"36#import "CMenuBar.h"37#import "JNIUtilities.h"3839static jclass sjc_ScreenMenu = NULL;40#define GET_SCREENMENU_CLASS() \41GET_CLASS(sjc_ScreenMenu, "com/apple/laf/ScreenMenu");4243static jint ns2awtModifiers(NSUInteger keyMods) {44jint result = 0;45if (keyMods & NSShiftKeyMask) result |= java_awt_Event_SHIFT_MASK;46if (keyMods & NSControlKeyMask) result |= java_awt_Event_CTRL_MASK;47if (keyMods & NSAlternateKeyMask) result |= java_awt_Event_ALT_MASK;48if (keyMods & NSCommandKeyMask) result |= java_awt_Event_META_MASK;49return result;50}5152static jint ns2awtMouseButton(NSInteger mouseButton) {53switch (mouseButton) {54case 1: return java_awt_event_InputEvent_BUTTON1_MASK;55case 2: return java_awt_event_InputEvent_BUTTON2_MASK;56case 3: return java_awt_event_InputEvent_BUTTON3_MASK;57}58return 0;59}606162@interface NativeToJavaDelegate : NSObject <JRSMenuDelegate, NSMenuDelegate>63{64@public65NSMenu *nsmenu;66jobject javaObject;67}6869@property (nonatomic, retain) NSMenu *nsmenu;70@property (nonatomic) jobject javaObject;7172- (id)initFromMenu:(NSMenu *)menu javaObj:(jobject)obj;73- (NSMenu*)menu;74@end757677@implementation NativeToJavaDelegate7879@synthesize nsmenu;80@synthesize javaObject;8182- (id)initFromMenu:(NSMenu *)aMenu javaObj:(jobject)obj83{84self = [super init];85if (self) {86self.nsmenu = aMenu;87self.javaObject = obj;88}89return self;90}9192- (NSMenu *)menu {93return self.nsmenu;94}9596- (void)menuWillOpen:(NSMenu *)menu97{98if (self.javaObject == nil) {99#ifdef DEBUG100NSLog(@"_javaObject is NULL: (%s - %s : %d)", __FILE__, __FUNCTION__, __LINE__);101#endif102return;103}104105JNIEnv *env = [ThreadUtilities getJNIEnv];106JNI_COCOA_ENTER(env);107//NSLog(@"menuWillOpen %@", [menu title]);108GET_SCREENMENU_CLASS();109DECLARE_METHOD(jm_ScreenMenu_invokeOpenLater, sjc_ScreenMenu, "invokeOpenLater", "()V");110(*env)->CallVoidMethod(env, self.javaObject, jm_ScreenMenu_invokeOpenLater);111CHECK_EXCEPTION();112JNI_COCOA_EXIT(env);113114}115116- (void)menuDidClose:(NSMenu *)menu117{118if (self.javaObject == nil) {119#ifdef DEBUG120NSLog(@"_javaObject is NULL: (%s - %s : %d)", __FILE__, __FUNCTION__, __LINE__);121#endif122return;123}124125JNIEnv *env = [ThreadUtilities getJNIEnv];126JNI_COCOA_ENTER(env);127//NSLog(@"menuDidClose %@", [menu title]);128GET_SCREENMENU_CLASS();129DECLARE_METHOD(jm_ScreenMenu_invokeMenuClosing, sjc_ScreenMenu, "invokeMenuClosing", "()V");130(*env)->CallVoidMethod(env, self.javaObject, jm_ScreenMenu_invokeMenuClosing);131CHECK_EXCEPTION();132JNI_COCOA_EXIT(env);133}134135136- (void)handleJavaMenuItemTargetedAtIndex:(NSUInteger)menuIndex rect:(NSRect)rect137{138if (self.javaObject== nil) {139#ifdef DEBUG140NSLog(@"_javaObject is NULL: (%s - %s : %d)", __FILE__, __FUNCTION__, __LINE__);141#endif142return;143}144145JNIEnv *env = [ThreadUtilities getJNIEnv];146JNI_COCOA_ENTER(env);147// Send that to Java so we can test which item was hit.148GET_SCREENMENU_CLASS();149DECLARE_METHOD(jm_ScreenMenu_updateSelectedItem, sjc_ScreenMenu, "handleItemTargeted", "(IIIII)V");150(*env)->CallVoidMethod(env, self.javaObject, jm_ScreenMenu_updateSelectedItem, menuIndex,151NSMinY(rect), NSMinX(rect), NSMaxY(rect), NSMaxX(rect));152CHECK_EXCEPTION();153154JNI_COCOA_EXIT(env);155}156157/*158* The input is an NSTimeInterval (a double representing seconds and fractions of seconds)159* 0.0 means midnight Jan 1, 2001.160* The output is a Java long representing time in milliseconds since midnight Jan 1st 1970.161* There is a Cocoa constant representing that difference : NSTimeIntervalSince1970162*/163static jlong NSTimeIntervalToJavaMilliseconds(NSTimeInterval interval) {164NSTimeInterval interval1970 = interval + NSTimeIntervalSince1970;165return (jlong)(interval1970 * 1000);166}167168// Called from event handler callback169- (void)handleJavaMouseEvent:(NSEvent *)event170{171NSInteger kind = [event type];172jint javaKind = 0;173174switch (kind) {175case NSLeftMouseUp: case NSRightMouseUp: case NSOtherMouseUp:176javaKind = java_awt_event_MouseEvent_MOUSE_RELEASED;177break;178case NSLeftMouseDown: case NSRightMouseDown: case NSOtherMouseDown:179javaKind = java_awt_event_MouseEvent_MOUSE_PRESSED;180break;181case NSMouseMoved:182javaKind = java_awt_event_MouseEvent_MOUSE_MOVED;183break;184case NSLeftMouseDragged: case NSRightMouseDragged: case NSOtherMouseDragged:185javaKind = java_awt_event_MouseEvent_MOUSE_DRAGGED;186break;187}188189// Get the coordinates of the mouse in global coordinates (must be global, since our tracking rects are global.)190NSPoint globalPoint = [event locationInWindow];191jint javaX = globalPoint.x;192jint javaY = globalPoint.y;193194// Convert the event modifiers into Java modifiers195jint javaModifiers = ns2awtModifiers([event modifierFlags]) | ns2awtMouseButton([event buttonNumber]);196197// Get the event time198jlong javaWhen = NSTimeIntervalToJavaMilliseconds([event timestamp]);199200// Call the mouse event handler, which will generate Java mouse events.201JNIEnv *env = [ThreadUtilities getJNIEnv];202JNI_COCOA_ENTER(env);203GET_SCREENMENU_CLASS();204DECLARE_METHOD(jm_ScreenMenu_handleMouseEvent, sjc_ScreenMenu, "handleMouseEvent", "(IIIIJ)V");205(*env)->CallVoidMethod(env, self.javaObject, jm_ScreenMenu_handleMouseEvent,206javaKind, javaX, javaY, javaModifiers, javaWhen);207CHECK_EXCEPTION();208JNI_COCOA_EXIT(env);209}210211@end212213214/*215* Class: com_apple_laf_ScreenMenu216* Method: addMenuListeners217* Signature: (Lcom/apple/laf/ScreenMenu;J[J)V218*/219JNIEXPORT jlong JNICALL Java_com_apple_laf_ScreenMenu_addMenuListeners220(JNIEnv *env, jclass clz, jobject listener, jlong nativeMenu)221{222NativeToJavaDelegate *delegate = nil;223224JNI_COCOA_ENTER(env);225226jobject listenerRef = (*env)->NewGlobalRef(env, listener);227NSMenu *menu = jlong_to_ptr(nativeMenu);228229delegate = [[[NativeToJavaDelegate alloc] initFromMenu:menu javaObj:listenerRef] autorelease];230CFRetain(delegate); // GC231232[ThreadUtilities performOnMainThreadWaiting:YES block:^{233NSMenu *menu = delegate.nsmenu;234if ([menu isJavaMenu]) {235[menu setDelegate:delegate];236[menu setJavaMenuDelegate:delegate];237}238}];239240JNI_COCOA_EXIT(env);241242return ptr_to_jlong(delegate);243}244245/*246* Class: com_apple_laf_ScreenMenu247* Method: removeMenuListeners248* Signature: (JJ)V249*/250JNIEXPORT void JNICALL Java_com_apple_laf_ScreenMenu_removeMenuListeners251(JNIEnv *env, jclass clz, jlong fModelPtr)252{253if (fModelPtr == 0L) return;254255JNI_COCOA_ENTER(env);256257NativeToJavaDelegate *delegate = (NativeToJavaDelegate *)jlong_to_ptr(fModelPtr);258259[ThreadUtilities performOnMainThreadWaiting:YES block:^{260NSMenu *menu = delegate.nsmenu;261[menu setJavaMenuDelegate:nil];262[menu setDelegate:nil];263delegate.nsmenu = nil;264}];265266(*env)->DeleteGlobalRef(env, delegate.javaObject);267delegate.javaObject = nil;268269CFRelease(delegate); // GC270271JNI_COCOA_EXIT(env);272}273274275