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 "ScreenMenu.h"
27
28 #import "com_apple_laf_ScreenMenu.h"
29 #import "java_awt_Event.h"
30 #import "java_awt_event_KeyEvent.h"
31 #import "java_awt_event_InputEvent.h"
32 #import "java_awt_event_MouseEvent.h"
33
34 #import <JavaNativeFoundation/JavaNativeFoundation.h>
35 #import <JavaRuntimeSupport/JavaRuntimeSupport.h>
36
37 #import "ThreadUtilities.h"
38 #import "CMenuBar.h"
39
40 static JNF_CLASS_CACHE(sjc_ScreenMenu, "com/apple/laf/ScreenMenu");
41
42 static jint ns2awtModifiers(NSUInteger keyMods) {
43 jint result = 0;
44 if (keyMods & NSShiftKeyMask) result |= java_awt_Event_SHIFT_MASK;
45 if (keyMods & NSControlKeyMask) result |= java_awt_Event_CTRL_MASK;
46 if (keyMods & NSAlternateKeyMask) result |= java_awt_Event_ALT_MASK;
47 if (keyMods & NSCommandKeyMask) result |= java_awt_Event_META_MASK;
48 return result;
49 }
50
51 static jint ns2awtMouseButton(NSInteger mouseButton) {
52 switch (mouseButton) {
53 case 1: return java_awt_event_InputEvent_BUTTON1_MASK;
54 case 2: return java_awt_event_InputEvent_BUTTON2_MASK;
55 case 3: return java_awt_event_InputEvent_BUTTON3_MASK;
56 }
57 return 0;
58 }
59
60
61 @interface NativeToJavaDelegate : NSObject <JRSMenuDelegate, NSMenuDelegate>
62 {
63 @public
64 NSMenu *nsmenu;
65 JNFJObjectWrapper *javaObjectWrapper;
66 }
67
68 @property (nonatomic, retain) NSMenu *nsmenu;
69 @property (nonatomic, retain) JNFJObjectWrapper *javaObjectWrapper;
70
71 - (id)initFromMenu:(NSMenu *)menu javaObj:(JNFJObjectWrapper *)obj;
72 - (NSMenu*)menu;
73 @end
74
75
76 @implementation NativeToJavaDelegate
77
78 @synthesize nsmenu;
79 @synthesize javaObjectWrapper;
80
81 - (id)initFromMenu:(NSMenu *)aMenu javaObj:(JNFJObjectWrapper *)obj
82 {
83 self = [super init];
84 if (self) {
85 self.nsmenu = aMenu;
86 self.javaObjectWrapper = obj;
87 }
88 return self;
89 }
90
91 - (NSMenu *)menu {
92 return self.nsmenu;
93 }
94
95 - (void)menuWillOpen:(NSMenu *)menu
96 {
97 if (self.javaObjectWrapper == nil) {
98 #ifdef DEBUG
99 NSLog(@"_javaObject is NULL: (%s - %s : %d)", __FILE__, __FUNCTION__, __LINE__);
100 #endif
101 return;
102 }
103
104 JNIEnv *env = [ThreadUtilities getJNIEnv];
105 JNF_COCOA_ENTER(env);
106 //NSLog(@"menuWillOpen %@", [menu title]);
107 static JNF_MEMBER_CACHE(jm_ScreenMenu_invokeOpenLater, sjc_ScreenMenu, "invokeOpenLater", "()V");
108 JNFCallVoidMethod(env, [self.javaObjectWrapper jObject], jm_ScreenMenu_invokeOpenLater); // AWT_THREADING Safe (AWTRunLoopMode)
109 JNF_COCOA_EXIT(env);
110
111 }
112
113 - (void)menuDidClose:(NSMenu *)menu
114 {
115 if (self.javaObjectWrapper == nil) {
116 #ifdef DEBUG
117 NSLog(@"_javaObject is NULL: (%s - %s : %d)", __FILE__, __FUNCTION__, __LINE__);
118 #endif
119 return;
120 }
121
122 JNIEnv *env = [ThreadUtilities getJNIEnv];
123 JNF_COCOA_ENTER(env);
124 //NSLog(@"menuDidClose %@", [menu title]);
125 static JNF_MEMBER_CACHE(jm_ScreenMenu_invokeMenuClosing, sjc_ScreenMenu, "invokeMenuClosing", "()V");
126 JNFCallVoidMethod(env, [self.javaObjectWrapper jObject], jm_ScreenMenu_invokeMenuClosing); // AWT_THREADING Safe (AWTRunLoopMode)
127 JNF_COCOA_EXIT(env);
128 }
129
130
131 - (void)handleJavaMenuItemTargetedAtIndex:(NSUInteger)menuIndex rect:(NSRect)rect
132 {
133 if (self.javaObjectWrapper == nil) {
134 #ifdef DEBUG
135 NSLog(@"_javaObject is NULL: (%s - %s : %d)", __FILE__, __FUNCTION__, __LINE__);
136 #endif
137 return;
138 }
139
140 JNIEnv *env = [ThreadUtilities getJNIEnv];
141 JNF_COCOA_ENTER(env);
142 // Send that to Java so we can test which item was hit.
143 static JNF_MEMBER_CACHE(jm_ScreenMenu_updateSelectedItem, sjc_ScreenMenu, "handleItemTargeted", "(IIIII)V");
144 JNFCallVoidMethod(env, [self.javaObjectWrapper jObject], jm_ScreenMenu_updateSelectedItem, menuIndex,
145 NSMinY(rect), NSMinX(rect), NSMaxY(rect), NSMaxX(rect)); // AWT_THREADING Safe (AWTRunLoopMode)
146
147 JNF_COCOA_EXIT(env);
148 }
149
150
151 // Called from event handler callback
152 - (void)handleJavaMouseEvent:(NSEvent *)event
153 {
154 NSInteger kind = [event type];
155 jint javaKind = 0;
156
157 switch (kind) {
158 case NSLeftMouseUp: case NSRightMouseUp: case NSOtherMouseUp:
159 javaKind = java_awt_event_MouseEvent_MOUSE_RELEASED;
160 break;
161 case NSLeftMouseDown: case NSRightMouseDown: case NSOtherMouseDown:
162 javaKind = java_awt_event_MouseEvent_MOUSE_PRESSED;
163 break;
164 case NSMouseMoved:
165 javaKind = java_awt_event_MouseEvent_MOUSE_MOVED;
166 break;
167 case NSLeftMouseDragged: case NSRightMouseDragged: case NSOtherMouseDragged:
168 javaKind = java_awt_event_MouseEvent_MOUSE_DRAGGED;
169 break;
170 }
171
172 // Get the coordinates of the mouse in global coordinates (must be global, since our tracking rects are global.)
173 NSPoint globalPoint = [event locationInWindow];
174 jint javaX = globalPoint.x;
175 jint javaY = globalPoint.y;
176
177 // Convert the event modifiers into Java modifiers
178 jint javaModifiers = ns2awtModifiers([event modifierFlags]) | ns2awtMouseButton([event buttonNumber]);
179
180 // Get the event time
181 jlong javaWhen = JNFNSTimeIntervalToJavaMillis([event timestamp]);
182
183 // Call the mouse event handler, which will generate Java mouse events.
184 JNIEnv *env = [ThreadUtilities getJNIEnv];
185 JNF_COCOA_ENTER(env);
186 static JNF_MEMBER_CACHE(jm_ScreenMenu_handleMouseEvent, sjc_ScreenMenu, "handleMouseEvent", "(IIIIJ)V");
187 JNFCallVoidMethod(env, [self.javaObjectWrapper jObject], jm_ScreenMenu_handleMouseEvent, javaKind, javaX, javaY, javaModifiers, javaWhen); // AWT_THREADING Safe (AWTRunLoopMode)
188 JNF_COCOA_EXIT(env);
189 }
190
191 @end
192
193
194 /*
195 * Class: com_apple_laf_ScreenMenu
196 * Method: addMenuListeners
197 * Signature: (Lcom/apple/laf/ScreenMenu;J[J)V
198 */
199 JNIEXPORT jlong JNICALL Java_com_apple_laf_ScreenMenu_addMenuListeners
200 (JNIEnv *env, jclass clz, jobject listener, jlong nativeMenu)
201 {
202 NativeToJavaDelegate *delegate = nil;
203
204 JNF_COCOA_ENTER(env);
205
206 JNFJObjectWrapper *wrapper = [JNFJObjectWrapper wrapperWithJObject:listener withEnv:env];
207 NSMenu *menu = jlong_to_ptr(nativeMenu);
208
209 delegate = [[[NativeToJavaDelegate alloc] initFromMenu:menu javaObj:wrapper] autorelease];
210 CFRetain(delegate); // GC
211
212 [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^{
213 NSMenu *menu = delegate.nsmenu;
214 if ([menu isJavaMenu]) {
215 [menu setDelegate:delegate];
216 [menu setJavaMenuDelegate:delegate];
217 }
218 }];
219
220 JNF_COCOA_EXIT(env);
221
222 return ptr_to_jlong(delegate);
223 }
224
225 /*
226 * Class: com_apple_laf_ScreenMenu
227 * Method: removeMenuListeners
228 * Signature: (JJ)V
229 */
230 JNIEXPORT void JNICALL Java_com_apple_laf_ScreenMenu_removeMenuListeners
231 (JNIEnv *env, jclass clz, jlong fModelPtr)
232 {
233 if (fModelPtr == 0L) return;
234
235 JNF_COCOA_ENTER(env);
236
237 NativeToJavaDelegate *delegate = (NativeToJavaDelegate *)jlong_to_ptr(fModelPtr);
238
239 [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^{
240 NSMenu *menu = delegate.nsmenu;
241 [menu setJavaMenuDelegate:nil];
242 [menu setDelegate:nil];
243 delegate.nsmenu = nil;
244 delegate.javaObjectWrapper = nil;
245 }];
246
247 CFRelease(delegate); // GC
248
249 JNF_COCOA_EXIT(env);
250 }
|
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 "ScreenMenu.h"
27
28 #import "com_apple_laf_ScreenMenu.h"
29 #import "java_awt_Event.h"
30 #import "java_awt_event_KeyEvent.h"
31 #import "java_awt_event_InputEvent.h"
32 #import "java_awt_event_MouseEvent.h"
33
34 #import <JavaRuntimeSupport/JavaRuntimeSupport.h>
35
36 #import "ThreadUtilities.h"
37 #import "CMenuBar.h"
38 #import "JNIUtilities.h"
39
40 static jclass sjc_ScreenMenu = NULL;
41 #define GET_SCREENMENU_CLASS() \
42 GET_CLASS(sjc_ScreenMenu, "com/apple/laf/ScreenMenu");
43
44 static jint ns2awtModifiers(NSUInteger keyMods) {
45 jint result = 0;
46 if (keyMods & NSShiftKeyMask) result |= java_awt_Event_SHIFT_MASK;
47 if (keyMods & NSControlKeyMask) result |= java_awt_Event_CTRL_MASK;
48 if (keyMods & NSAlternateKeyMask) result |= java_awt_Event_ALT_MASK;
49 if (keyMods & NSCommandKeyMask) result |= java_awt_Event_META_MASK;
50 return result;
51 }
52
53 static jint ns2awtMouseButton(NSInteger mouseButton) {
54 switch (mouseButton) {
55 case 1: return java_awt_event_InputEvent_BUTTON1_MASK;
56 case 2: return java_awt_event_InputEvent_BUTTON2_MASK;
57 case 3: return java_awt_event_InputEvent_BUTTON3_MASK;
58 }
59 return 0;
60 }
61
62
63 @interface NativeToJavaDelegate : NSObject <JRSMenuDelegate, NSMenuDelegate>
64 {
65 @public
66 NSMenu *nsmenu;
67 jobject javaObject;
68 }
69
70 @property (nonatomic, retain) NSMenu *nsmenu;
71 @property (nonatomic) jobject javaObject;
72
73 - (id)initFromMenu:(NSMenu *)menu javaObj:(jobject)obj;
74 - (NSMenu*)menu;
75 @end
76
77
78 @implementation NativeToJavaDelegate
79
80 @synthesize nsmenu;
81 @synthesize javaObject;
82
83 - (id)initFromMenu:(NSMenu *)aMenu javaObj:(jobject)obj
84 {
85 self = [super init];
86 if (self) {
87 self.nsmenu = aMenu;
88 self.javaObject = obj;
89 }
90 return self;
91 }
92
93 - (NSMenu *)menu {
94 return self.nsmenu;
95 }
96
97 - (void)menuWillOpen:(NSMenu *)menu
98 {
99 if (self.javaObject == nil) {
100 #ifdef DEBUG
101 NSLog(@"_javaObject is NULL: (%s - %s : %d)", __FILE__, __FUNCTION__, __LINE__);
102 #endif
103 return;
104 }
105
106 JNIEnv *env = [ThreadUtilities getJNIEnv];
107 JNI_COCOA_ENTER(env);
108 //NSLog(@"menuWillOpen %@", [menu title]);
109 GET_SCREENMENU_CLASS();
110 DECLARE_METHOD(jm_ScreenMenu_invokeOpenLater, sjc_ScreenMenu, "invokeOpenLater", "()V");
111 (*env)->CallVoidMethod(env, self.javaObject, jm_ScreenMenu_invokeOpenLater);
112 CHECK_EXCEPTION();
113 JNI_COCOA_EXIT(env);
114
115 }
116
117 - (void)menuDidClose:(NSMenu *)menu
118 {
119 if (self.javaObject == nil) {
120 #ifdef DEBUG
121 NSLog(@"_javaObject is NULL: (%s - %s : %d)", __FILE__, __FUNCTION__, __LINE__);
122 #endif
123 return;
124 }
125
126 JNIEnv *env = [ThreadUtilities getJNIEnv];
127 JNI_COCOA_ENTER(env);
128 //NSLog(@"menuDidClose %@", [menu title]);
129 GET_SCREENMENU_CLASS();
130 DECLARE_METHOD(jm_ScreenMenu_invokeMenuClosing, sjc_ScreenMenu, "invokeMenuClosing", "()V");
131 (*env)->CallVoidMethod(env, self.javaObject, jm_ScreenMenu_invokeMenuClosing);
132 CHECK_EXCEPTION();
133 JNI_COCOA_EXIT(env);
134 }
135
136
137 - (void)handleJavaMenuItemTargetedAtIndex:(NSUInteger)menuIndex rect:(NSRect)rect
138 {
139 if (self.javaObject== nil) {
140 #ifdef DEBUG
141 NSLog(@"_javaObject is NULL: (%s - %s : %d)", __FILE__, __FUNCTION__, __LINE__);
142 #endif
143 return;
144 }
145
146 JNIEnv *env = [ThreadUtilities getJNIEnv];
147 JNI_COCOA_ENTER(env);
148 // Send that to Java so we can test which item was hit.
149 GET_SCREENMENU_CLASS();
150 DECLARE_METHOD(jm_ScreenMenu_updateSelectedItem, sjc_ScreenMenu, "handleItemTargeted", "(IIIII)V");
151 (*env)->CallVoidMethod(env, self.javaObject, jm_ScreenMenu_updateSelectedItem, menuIndex,
152 NSMinY(rect), NSMinX(rect), NSMaxY(rect), NSMaxX(rect));
153 CHECK_EXCEPTION();
154
155 JNI_COCOA_EXIT(env);
156 }
157
158 /*
159 * The input is an NSTimeInterval (a double representing seconds and fractions of seconds)
160 * 0.0 means midnight Jan 1, 2001.
161 * The output is a Java long representing time in milliseconds since midnight Jan 1st 1970.
162 * There is a Cocoa constant representing that difference : NSTimeIntervalSince1970
163 */
164 static jlong NSTimeIntervalToJavaMilliseconds(NSTimeInterval interval) {
165 NSTimeInterval interval1970 = interval + NSTimeIntervalSince1970;
166 return (jlong)(interval1970 * 1000);
167 }
168
169 // Called from event handler callback
170 - (void)handleJavaMouseEvent:(NSEvent *)event
171 {
172 NSInteger kind = [event type];
173 jint javaKind = 0;
174
175 switch (kind) {
176 case NSLeftMouseUp: case NSRightMouseUp: case NSOtherMouseUp:
177 javaKind = java_awt_event_MouseEvent_MOUSE_RELEASED;
178 break;
179 case NSLeftMouseDown: case NSRightMouseDown: case NSOtherMouseDown:
180 javaKind = java_awt_event_MouseEvent_MOUSE_PRESSED;
181 break;
182 case NSMouseMoved:
183 javaKind = java_awt_event_MouseEvent_MOUSE_MOVED;
184 break;
185 case NSLeftMouseDragged: case NSRightMouseDragged: case NSOtherMouseDragged:
186 javaKind = java_awt_event_MouseEvent_MOUSE_DRAGGED;
187 break;
188 }
189
190 // Get the coordinates of the mouse in global coordinates (must be global, since our tracking rects are global.)
191 NSPoint globalPoint = [event locationInWindow];
192 jint javaX = globalPoint.x;
193 jint javaY = globalPoint.y;
194
195 // Convert the event modifiers into Java modifiers
196 jint javaModifiers = ns2awtModifiers([event modifierFlags]) | ns2awtMouseButton([event buttonNumber]);
197
198 // Get the event time
199 jlong javaWhen = NSTimeIntervalToJavaMilliseconds([event timestamp]);
200
201 // Call the mouse event handler, which will generate Java mouse events.
202 JNIEnv *env = [ThreadUtilities getJNIEnv];
203 JNI_COCOA_ENTER(env);
204 GET_SCREENMENU_CLASS();
205 DECLARE_METHOD(jm_ScreenMenu_handleMouseEvent, sjc_ScreenMenu, "handleMouseEvent", "(IIIIJ)V");
206 (*env)->CallVoidMethod(env, self.javaObject, jm_ScreenMenu_handleMouseEvent,
207 javaKind, javaX, javaY, javaModifiers, javaWhen);
208 CHECK_EXCEPTION();
209 JNI_COCOA_EXIT(env);
210 }
211
212 @end
213
214
215 /*
216 * Class: com_apple_laf_ScreenMenu
217 * Method: addMenuListeners
218 * Signature: (Lcom/apple/laf/ScreenMenu;J[J)V
219 */
220 JNIEXPORT jlong JNICALL Java_com_apple_laf_ScreenMenu_addMenuListeners
221 (JNIEnv *env, jclass clz, jobject listener, jlong nativeMenu)
222 {
223 NativeToJavaDelegate *delegate = nil;
224
225 JNI_COCOA_ENTER(env);
226
227 jobject listenerRef = (*env)->NewGlobalRef(env, listener);
228 NSMenu *menu = jlong_to_ptr(nativeMenu);
229
230 delegate = [[[NativeToJavaDelegate alloc] initFromMenu:menu javaObj:listenerRef] autorelease];
231 CFRetain(delegate); // GC
232
233 [ThreadUtilities performOnMainThreadWaiting:YES block:^{
234 NSMenu *menu = delegate.nsmenu;
235 if ([menu isJavaMenu]) {
236 [menu setDelegate:delegate];
237 [menu setJavaMenuDelegate:delegate];
238 }
239 }];
240
241 JNI_COCOA_EXIT(env);
242
243 return ptr_to_jlong(delegate);
244 }
245
246 /*
247 * Class: com_apple_laf_ScreenMenu
248 * Method: removeMenuListeners
249 * Signature: (JJ)V
250 */
251 JNIEXPORT void JNICALL Java_com_apple_laf_ScreenMenu_removeMenuListeners
252 (JNIEnv *env, jclass clz, jlong fModelPtr)
253 {
254 if (fModelPtr == 0L) return;
255
256 JNI_COCOA_ENTER(env);
257
258 NativeToJavaDelegate *delegate = (NativeToJavaDelegate *)jlong_to_ptr(fModelPtr);
259
260 [ThreadUtilities performOnMainThreadWaiting:YES block:^{
261 NSMenu *menu = delegate.nsmenu;
262 [menu setJavaMenuDelegate:nil];
263 [menu setDelegate:nil];
264 delegate.nsmenu = nil;
265 }];
266
267 (*env)->DeleteGlobalRef(env, delegate.javaObject);
268 delegate.javaObject = nil;
269
270 CFRelease(delegate); // GC
271
272 JNI_COCOA_EXIT(env);
273 }
|