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 "jni_util.h"
27
28 #import <AppKit/AppKit.h>
29 #import <JavaNativeFoundation/JavaNativeFoundation.h>
30
31 #import "CTrayIcon.h"
32 #import "ThreadUtilities.h"
33 #include "GeomUtilities.h"
34 #import "LWCToolkit.h"
35
36 #define kImageInset 4.0
37
38 /**
39 * If the image of the specified size won't fit into the status bar,
40 * then scale it down proprtionally. Otherwise, leave it as is.
41 */
42 static NSSize ScaledImageSizeForStatusBar(NSSize imageSize, BOOL autosize) {
43 NSRect imageRect = NSMakeRect(0.0, 0.0, imageSize.width, imageSize.height);
44
45 // There is a black line at the bottom of the status bar
46 // that we don't want to cover with image pixels.
47 CGFloat desiredSize = [[NSStatusBar systemStatusBar] thickness] - 1.0;
48 if (autosize) {
49 imageRect.size.width = desiredSize;
58 }
59
60 @implementation AWTTrayIcon
61
62 - (id) initWithPeer:(jobject)thePeer {
63 if (!(self = [super init])) return nil;
64
65 peer = thePeer;
66
67 theItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength];
68 [theItem retain];
69
70 view = [[AWTTrayIconView alloc] initWithTrayIcon:self];
71 [theItem setView:view];
72
73 return self;
74 }
75
76 -(void) dealloc {
77 JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
78 JNFDeleteGlobalRef(env, peer);
79
80 [[NSStatusBar systemStatusBar] removeStatusItem: theItem];
81
82 // Its a bad idea to force the item to release our view by setting
83 // the item's view to nil: it can lead to a crash in some scenarios.
84 // The item will release the view later on, so just set the view's image
85 // and tray icon to nil since we are done with it.
86 [view setImage: nil];
87 [view setTrayIcon: nil];
88 [view release];
89
90 [theItem release];
91
92 [super dealloc];
93 }
94
95 - (void) setTooltip:(NSString *) tooltip{
96 [view setToolTip:tooltip];
97 }
98
129
130 NSPoint eventLocation = [event locationInWindow];
131 NSPoint localPoint = [view convertPoint: eventLocation fromView: nil];
132 localPoint.y = [view bounds].size.height - localPoint.y;
133
134 NSPoint absP = [NSEvent mouseLocation];
135 NSEventType type = [event type];
136
137 absP = ConvertNSScreenPoint(NULL, absP);
138 jint clickCount;
139
140 clickCount = [event clickCount];
141
142 jdouble deltaX = [event deltaX];
143 jdouble deltaY = [event deltaY];
144 if ([AWTToolkit hasPreciseScrollingDeltas: event]) {
145 deltaX = [event scrollingDeltaX] * 0.1;
146 deltaY = [event scrollingDeltaY] * 0.1;
147 }
148
149 static JNF_CLASS_CACHE(jc_NSEvent, "sun/lwawt/macosx/NSEvent");
150 static JNF_CTOR_CACHE(jctor_NSEvent, jc_NSEvent, "(IIIIIIIIDDI)V");
151 jobject jEvent = JNFNewObject(env, jctor_NSEvent,
152 [event type],
153 [event modifierFlags],
154 clickCount,
155 [event buttonNumber],
156 (jint)localPoint.x, (jint)localPoint.y,
157 (jint)absP.x, (jint)absP.y,
158 deltaY,
159 deltaX,
160 [AWTToolkit scrollStateWithEvent: event]);
161 CHECK_NULL(jEvent);
162
163 static JNF_CLASS_CACHE(jc_TrayIcon, "sun/lwawt/macosx/CTrayIcon");
164 static JNF_MEMBER_CACHE(jm_handleMouseEvent, jc_TrayIcon, "handleMouseEvent", "(Lsun/lwawt/macosx/NSEvent;)V");
165 JNFCallVoidMethod(env, peer, jm_handleMouseEvent, jEvent);
166 (*env)->DeleteLocalRef(env, jEvent);
167 }
168
169 @end //AWTTrayIcon
170 //================================================
171
172 @implementation AWTTrayIconView
173
174 -(id)initWithTrayIcon:(AWTTrayIcon *)theTrayIcon {
175 self = [super initWithFrame:NSMakeRect(0, 0, 1, 1)];
176
177 [self setTrayIcon: theTrayIcon];
178 isHighlighted = NO;
179 image = nil;
180 trackingArea = nil;
181
182 [self addTrackingArea];
183
184 return self;
185 }
251 drawRect.origin.y = 1.0;
252 }
253 drawRect = NSIntegralRect(drawRect);
254
255 [trayIcon.theItem drawStatusBarBackgroundInRect:bounds
256 withHighlight:isHighlighted];
257 [image drawInRect:drawRect
258 fromRect:NSZeroRect
259 operation:NSCompositeSourceOver
260 fraction:1.0
261 ];
262 }
263
264 - (void)mouseDown:(NSEvent *)event {
265 [trayIcon deliverJavaMouseEvent: event];
266
267 // don't show the menu on ctrl+click: it triggers ACTION event, like right click
268 if (([event modifierFlags] & NSControlKeyMask) == 0) {
269 //find CTrayIcon.getPopupMenuModel method and call it to get popup menu ptr.
270 JNIEnv *env = [ThreadUtilities getJNIEnv];
271 static JNF_CLASS_CACHE(jc_CTrayIcon, "sun/lwawt/macosx/CTrayIcon");
272 static JNF_MEMBER_CACHE(jm_getPopupMenuModel, jc_CTrayIcon, "getPopupMenuModel", "()J");
273 jlong res = JNFCallLongMethod(env, trayIcon.peer, jm_getPopupMenuModel);
274
275 if (res != 0) {
276 CPopupMenu *cmenu = jlong_to_ptr(res);
277 NSMenu* menu = [cmenu menu];
278 [menu setDelegate:self];
279 [trayIcon.theItem popUpStatusItemMenu:menu];
280 [self setNeedsDisplay:YES];
281 }
282 }
283 }
284
285 - (void) mouseUp:(NSEvent *)event {
286 [trayIcon deliverJavaMouseEvent: event];
287 }
288
289 - (void) mouseDragged:(NSEvent *)event {
290 [trayIcon deliverJavaMouseEvent: event];
291 }
292
293 - (void) mouseMoved: (NSEvent *)event {
314 [trayIcon deliverJavaMouseEvent: event];
315 }
316
317 - (void) otherMouseDragged:(NSEvent *)event {
318 [trayIcon deliverJavaMouseEvent: event];
319 }
320
321
322 @end //AWTTrayIconView
323 //================================================
324
325 /*
326 * Class: sun_lwawt_macosx_CTrayIcon
327 * Method: nativeCreate
328 * Signature: ()J
329 */
330 JNIEXPORT jlong JNICALL Java_sun_lwawt_macosx_CTrayIcon_nativeCreate
331 (JNIEnv *env, jobject peer) {
332 __block AWTTrayIcon *trayIcon = nil;
333
334 JNF_COCOA_ENTER(env);
335
336 jobject thePeer = JNFNewGlobalRef(env, peer);
337 [ThreadUtilities performOnMainThreadWaiting:YES block:^(){
338 trayIcon = [[AWTTrayIcon alloc] initWithPeer:thePeer];
339 }];
340
341 JNF_COCOA_EXIT(env);
342
343 return ptr_to_jlong(trayIcon);
344 }
345
346
347 /*
348 * Class: java_awt_TrayIcon
349 * Method: initIDs
350 * Signature: ()V
351 */
352 JNIEXPORT void JNICALL Java_java_awt_TrayIcon_initIDs
353 (JNIEnv *env, jclass cls) {
354 //Do nothing.
355 }
356
357 /*
358 * Class: sun_lwawt_macosx_CTrayIcon
359 * Method: nativeSetToolTip
360 * Signature: (JLjava/lang/String;)V
361 */
362 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CTrayIcon_nativeSetToolTip
363 (JNIEnv *env, jobject self, jlong model, jstring jtooltip) {
364 JNF_COCOA_ENTER(env);
365
366 AWTTrayIcon *icon = jlong_to_ptr(model);
367 NSString *tooltip = JNFJavaToNSString(env, jtooltip);
368 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
369 [icon setTooltip:tooltip];
370 }];
371
372 JNF_COCOA_EXIT(env);
373 }
374
375 /*
376 * Class: sun_lwawt_macosx_CTrayIcon
377 * Method: setNativeImage
378 * Signature: (JJZ)V
379 */
380 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CTrayIcon_setNativeImage
381 (JNIEnv *env, jobject self, jlong model, jlong imagePtr, jboolean autosize) {
382 JNF_COCOA_ENTER(env);
383
384 AWTTrayIcon *icon = jlong_to_ptr(model);
385 [ThreadUtilities performOnMainThreadWaiting:YES block:^(){
386 [icon setImage:jlong_to_ptr(imagePtr) sizing:autosize];
387 }];
388
389 JNF_COCOA_EXIT(env);
390 }
391
392 JNIEXPORT jobject JNICALL
393 Java_sun_lwawt_macosx_CTrayIcon_nativeGetIconLocation
394 (JNIEnv *env, jobject self, jlong model) {
395 jobject jpt = NULL;
396
397 JNF_COCOA_ENTER(env);
398
399 __block NSPoint pt = NSZeroPoint;
400 AWTTrayIcon *icon = jlong_to_ptr(model);
401 [ThreadUtilities performOnMainThreadWaiting:YES block:^(){
402 NSPoint loc = [icon getLocationOnScreen];
403 pt = ConvertNSScreenPoint(env, loc);
404 }];
405
406 jpt = NSToJavaPoint(env, pt);
407
408 JNF_COCOA_EXIT(env);
409
410 return jpt;
411 }
412
413 JNIEXPORT void JNICALL
414 Java_sun_lwawt_macosx_CTrayIcon_nativeShowNotification
415 (JNIEnv *env, jobject self, jlong model, jobject jcaption, jobject jtext,
416 long nsimage) {
417 JNF_COCOA_ENTER(env);
418
419 AWTTrayIcon *icon = jlong_to_ptr(model);
420 NSString *caption = JNFJavaToNSString(env, jcaption);
421 NSString *text = JNFJavaToNSString(env, jtext);
422 NSImage * contentImage = jlong_to_ptr(nsimage);
423
424 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
425 NSUserNotification *notification = [[NSUserNotification alloc] init];
426 notification.title = caption;
427 notification.informativeText = text;
428 notification.contentImage = contentImage;
429 notification.soundName = NSUserNotificationDefaultSoundName;
430
431 [[NSUserNotificationCenter defaultUserNotificationCenter]
432 deliverNotification:notification];
433 }];
434
435 JNF_COCOA_EXIT(env);
436 }
|
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 "jni_util.h"
27
28 #import <AppKit/AppKit.h>
29
30 #import "CTrayIcon.h"
31 #import "ThreadUtilities.h"
32 #include "GeomUtilities.h"
33 #import "LWCToolkit.h"
34
35 #define kImageInset 4.0
36
37 /**
38 * If the image of the specified size won't fit into the status bar,
39 * then scale it down proprtionally. Otherwise, leave it as is.
40 */
41 static NSSize ScaledImageSizeForStatusBar(NSSize imageSize, BOOL autosize) {
42 NSRect imageRect = NSMakeRect(0.0, 0.0, imageSize.width, imageSize.height);
43
44 // There is a black line at the bottom of the status bar
45 // that we don't want to cover with image pixels.
46 CGFloat desiredSize = [[NSStatusBar systemStatusBar] thickness] - 1.0;
47 if (autosize) {
48 imageRect.size.width = desiredSize;
57 }
58
59 @implementation AWTTrayIcon
60
61 - (id) initWithPeer:(jobject)thePeer {
62 if (!(self = [super init])) return nil;
63
64 peer = thePeer;
65
66 theItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength];
67 [theItem retain];
68
69 view = [[AWTTrayIconView alloc] initWithTrayIcon:self];
70 [theItem setView:view];
71
72 return self;
73 }
74
75 -(void) dealloc {
76 JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
77 (*env)->DeleteGlobalRef(env, peer);
78
79 [[NSStatusBar systemStatusBar] removeStatusItem: theItem];
80
81 // Its a bad idea to force the item to release our view by setting
82 // the item's view to nil: it can lead to a crash in some scenarios.
83 // The item will release the view later on, so just set the view's image
84 // and tray icon to nil since we are done with it.
85 [view setImage: nil];
86 [view setTrayIcon: nil];
87 [view release];
88
89 [theItem release];
90
91 [super dealloc];
92 }
93
94 - (void) setTooltip:(NSString *) tooltip{
95 [view setToolTip:tooltip];
96 }
97
128
129 NSPoint eventLocation = [event locationInWindow];
130 NSPoint localPoint = [view convertPoint: eventLocation fromView: nil];
131 localPoint.y = [view bounds].size.height - localPoint.y;
132
133 NSPoint absP = [NSEvent mouseLocation];
134 NSEventType type = [event type];
135
136 absP = ConvertNSScreenPoint(NULL, absP);
137 jint clickCount;
138
139 clickCount = [event clickCount];
140
141 jdouble deltaX = [event deltaX];
142 jdouble deltaY = [event deltaY];
143 if ([AWTToolkit hasPreciseScrollingDeltas: event]) {
144 deltaX = [event scrollingDeltaX] * 0.1;
145 deltaY = [event scrollingDeltaY] * 0.1;
146 }
147
148 DECLARE_CLASS(jc_NSEvent, "sun/lwawt/macosx/NSEvent");
149 DECLARE_METHOD(jctor_NSEvent, jc_NSEvent, "<init>", "(IIIIIIIIDDI)V");
150 jobject jEvent = (*env)->NewObject(env, jc_NSEvent, jctor_NSEvent,
151 [event type],
152 [event modifierFlags],
153 clickCount,
154 [event buttonNumber],
155 (jint)localPoint.x, (jint)localPoint.y,
156 (jint)absP.x, (jint)absP.y,
157 deltaY,
158 deltaX,
159 [AWTToolkit scrollStateWithEvent: event]);
160 CHECK_NULL(jEvent);
161
162 DECLARE_CLASS(jc_TrayIcon, "sun/lwawt/macosx/CTrayIcon");
163 DECLARE_METHOD(jm_handleMouseEvent, jc_TrayIcon, "handleMouseEvent", "(Lsun/lwawt/macosx/NSEvent;)V");
164 (*env)->CallVoidMethod(env, peer, jm_handleMouseEvent, jEvent);
165 CHECK_EXCEPTION();
166 (*env)->DeleteLocalRef(env, jEvent);
167 }
168
169 @end //AWTTrayIcon
170 //================================================
171
172 @implementation AWTTrayIconView
173
174 -(id)initWithTrayIcon:(AWTTrayIcon *)theTrayIcon {
175 self = [super initWithFrame:NSMakeRect(0, 0, 1, 1)];
176
177 [self setTrayIcon: theTrayIcon];
178 isHighlighted = NO;
179 image = nil;
180 trackingArea = nil;
181
182 [self addTrackingArea];
183
184 return self;
185 }
251 drawRect.origin.y = 1.0;
252 }
253 drawRect = NSIntegralRect(drawRect);
254
255 [trayIcon.theItem drawStatusBarBackgroundInRect:bounds
256 withHighlight:isHighlighted];
257 [image drawInRect:drawRect
258 fromRect:NSZeroRect
259 operation:NSCompositeSourceOver
260 fraction:1.0
261 ];
262 }
263
264 - (void)mouseDown:(NSEvent *)event {
265 [trayIcon deliverJavaMouseEvent: event];
266
267 // don't show the menu on ctrl+click: it triggers ACTION event, like right click
268 if (([event modifierFlags] & NSControlKeyMask) == 0) {
269 //find CTrayIcon.getPopupMenuModel method and call it to get popup menu ptr.
270 JNIEnv *env = [ThreadUtilities getJNIEnv];
271 DECLARE_CLASS(jc_CTrayIcon, "sun/lwawt/macosx/CTrayIcon");
272 DECLARE_METHOD(jm_getPopupMenuModel, jc_CTrayIcon, "getPopupMenuModel", "()J");
273 jlong res = (*env)->CallLongMethod(env, trayIcon.peer, jm_getPopupMenuModel);
274 CHECK_EXCEPTION();
275
276 if (res != 0) {
277 CPopupMenu *cmenu = jlong_to_ptr(res);
278 NSMenu* menu = [cmenu menu];
279 [menu setDelegate:self];
280 [trayIcon.theItem popUpStatusItemMenu:menu];
281 [self setNeedsDisplay:YES];
282 }
283 }
284 }
285
286 - (void) mouseUp:(NSEvent *)event {
287 [trayIcon deliverJavaMouseEvent: event];
288 }
289
290 - (void) mouseDragged:(NSEvent *)event {
291 [trayIcon deliverJavaMouseEvent: event];
292 }
293
294 - (void) mouseMoved: (NSEvent *)event {
315 [trayIcon deliverJavaMouseEvent: event];
316 }
317
318 - (void) otherMouseDragged:(NSEvent *)event {
319 [trayIcon deliverJavaMouseEvent: event];
320 }
321
322
323 @end //AWTTrayIconView
324 //================================================
325
326 /*
327 * Class: sun_lwawt_macosx_CTrayIcon
328 * Method: nativeCreate
329 * Signature: ()J
330 */
331 JNIEXPORT jlong JNICALL Java_sun_lwawt_macosx_CTrayIcon_nativeCreate
332 (JNIEnv *env, jobject peer) {
333 __block AWTTrayIcon *trayIcon = nil;
334
335 JNI_COCOA_ENTER(env);
336
337 jobject thePeer = (*env)->NewGlobalRef(env, peer);
338 [ThreadUtilities performOnMainThreadWaiting:YES block:^(){
339 trayIcon = [[AWTTrayIcon alloc] initWithPeer:thePeer];
340 }];
341
342 JNI_COCOA_EXIT(env);
343
344 return ptr_to_jlong(trayIcon);
345 }
346
347
348 /*
349 * Class: java_awt_TrayIcon
350 * Method: initIDs
351 * Signature: ()V
352 */
353 JNIEXPORT void JNICALL Java_java_awt_TrayIcon_initIDs
354 (JNIEnv *env, jclass cls) {
355 //Do nothing.
356 }
357
358 /*
359 * Class: sun_lwawt_macosx_CTrayIcon
360 * Method: nativeSetToolTip
361 * Signature: (JLjava/lang/String;)V
362 */
363 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CTrayIcon_nativeSetToolTip
364 (JNIEnv *env, jobject self, jlong model, jstring jtooltip) {
365 JNI_COCOA_ENTER(env);
366
367 AWTTrayIcon *icon = jlong_to_ptr(model);
368 NSString *tooltip = JavaStringToNSString(env, jtooltip);
369 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
370 [icon setTooltip:tooltip];
371 }];
372
373 JNI_COCOA_EXIT(env);
374 }
375
376 /*
377 * Class: sun_lwawt_macosx_CTrayIcon
378 * Method: setNativeImage
379 * Signature: (JJZ)V
380 */
381 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CTrayIcon_setNativeImage
382 (JNIEnv *env, jobject self, jlong model, jlong imagePtr, jboolean autosize) {
383 JNI_COCOA_ENTER(env);
384
385 AWTTrayIcon *icon = jlong_to_ptr(model);
386 [ThreadUtilities performOnMainThreadWaiting:YES block:^(){
387 [icon setImage:jlong_to_ptr(imagePtr) sizing:autosize];
388 }];
389
390 JNI_COCOA_EXIT(env);
391 }
392
393 JNIEXPORT jobject JNICALL
394 Java_sun_lwawt_macosx_CTrayIcon_nativeGetIconLocation
395 (JNIEnv *env, jobject self, jlong model) {
396 jobject jpt = NULL;
397
398 JNI_COCOA_ENTER(env);
399
400 __block NSPoint pt = NSZeroPoint;
401 AWTTrayIcon *icon = jlong_to_ptr(model);
402 [ThreadUtilities performOnMainThreadWaiting:YES block:^(){
403 NSPoint loc = [icon getLocationOnScreen];
404 pt = ConvertNSScreenPoint(env, loc);
405 }];
406
407 jpt = NSToJavaPoint(env, pt);
408
409 JNI_COCOA_EXIT(env);
410
411 return jpt;
412 }
413
414 JNIEXPORT void JNICALL
415 Java_sun_lwawt_macosx_CTrayIcon_nativeShowNotification
416 (JNIEnv *env, jobject self, jlong model, jobject jcaption, jobject jtext,
417 long nsimage) {
418 JNI_COCOA_ENTER(env);
419
420 AWTTrayIcon *icon = jlong_to_ptr(model);
421 NSString *caption = JavaStringToNSString(env, jcaption);
422 NSString *text = JavaStringToNSString(env, jtext);
423 NSImage * contentImage = jlong_to_ptr(nsimage);
424
425 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
426 NSUserNotification *notification = [[NSUserNotification alloc] init];
427 notification.title = caption;
428 notification.informativeText = text;
429 notification.contentImage = contentImage;
430 notification.soundName = NSUserNotificationDefaultSoundName;
431
432 [[NSUserNotificationCenter defaultUserNotificationCenter]
433 deliverNotification:notification];
434 }];
435
436 JNI_COCOA_EXIT(env);
437 }
|