Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/macosx/native_NOTIOS/sun/awt/CTrayIcon.m
38829 views
/*1* Copyright (c) 2011, 2014, 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 <AppKit/AppKit.h>26#import <JavaNativeFoundation/JavaNativeFoundation.h>2728#import "CTrayIcon.h"29#import "ThreadUtilities.h"30#include "GeomUtilities.h"31#import "LWCToolkit.h"3233#define kImageInset 4.03435/**36* If the image of the specified size won't fit into the status bar,37* then scale it down proprtionally. Otherwise, leave it as is.38*/39static NSSize ScaledImageSizeForStatusBar(NSSize imageSize) {40NSRect imageRect = NSMakeRect(0.0, 0.0, imageSize.width, imageSize.height);4142// There is a black line at the bottom of the status bar43// that we don't want to cover with image pixels.44CGFloat desiredHeight = [[NSStatusBar systemStatusBar] thickness] - 1.0;45CGFloat scaleFactor = MIN(1.0, desiredHeight/imageSize.height);4647imageRect.size.width *= scaleFactor;48imageRect.size.height *= scaleFactor;49imageRect = NSIntegralRect(imageRect);5051return imageRect.size;52}5354@implementation AWTTrayIcon5556- (id) initWithPeer:(jobject)thePeer {57if (!(self = [super init])) return nil;5859peer = thePeer;6061theItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength];62[theItem retain];6364view = [[AWTTrayIconView alloc] initWithTrayIcon:self];65[theItem setView:view];6667return self;68}6970-(void) dealloc {71JNIEnv *env = [ThreadUtilities getJNIEnvUncached];72JNFDeleteGlobalRef(env, peer);7374[[NSStatusBar systemStatusBar] removeStatusItem: theItem];7576// Its a bad idea to force the item to release our view by setting77// the item's view to nil: it can lead to a crash in some scenarios.78// The item will release the view later on, so just set the view's image79// and tray icon to nil since we are done with it.80[view setImage: nil];81[view setTrayIcon: nil];82[view release];8384[theItem release];8586[super dealloc];87}8889- (void) setTooltip:(NSString *) tooltip{90[view setToolTip:tooltip];91}9293-(NSStatusItem *) theItem{94return theItem;95}9697- (jobject) peer{98return peer;99}100101- (void) setImage:(NSImage *) imagePtr sizing:(BOOL)autosize{102NSSize imageSize = [imagePtr size];103NSSize scaledSize = ScaledImageSizeForStatusBar(imageSize);104if (imageSize.width != scaledSize.width ||105imageSize.height != scaledSize.height) {106[imagePtr setSize: scaledSize];107}108109CGFloat itemLength = scaledSize.width + 2.0*kImageInset;110[theItem setLength:itemLength];111112[view setImage:imagePtr];113}114115- (NSPoint) getLocationOnScreen {116return [[view window] convertBaseToScreen: NSZeroPoint];117}118119-(void) deliverJavaMouseEvent: (NSEvent *) event {120[AWTToolkit eventCountPlusPlus];121122JNIEnv *env = [ThreadUtilities getJNIEnv];123124NSPoint eventLocation = [event locationInWindow];125NSPoint localPoint = [view convertPoint: eventLocation fromView: nil];126localPoint.y = [view bounds].size.height - localPoint.y;127128NSPoint absP = [NSEvent mouseLocation];129NSEventType type = [event type];130131NSRect screenRect = [[NSScreen mainScreen] frame];132absP.y = screenRect.size.height - absP.y;133jint clickCount;134135clickCount = [event clickCount];136137jdouble deltaX = [event deltaX];138jdouble deltaY = [event deltaY];139if ([AWTToolkit hasPreciseScrollingDeltas: event]) {140deltaX = [event scrollingDeltaX] * 0.1;141deltaY = [event scrollingDeltaY] * 0.1;142}143144static JNF_CLASS_CACHE(jc_NSEvent, "sun/lwawt/macosx/NSEvent");145static JNF_CTOR_CACHE(jctor_NSEvent, jc_NSEvent, "(IIIIIIIIDDI)V");146jobject jEvent = JNFNewObject(env, jctor_NSEvent,147[event type],148[event modifierFlags],149clickCount,150[event buttonNumber],151(jint)localPoint.x, (jint)localPoint.y,152(jint)absP.x, (jint)absP.y,153deltaY,154deltaX,155[AWTToolkit scrollStateWithEvent: event]);156if (jEvent == nil) {157// Unable to create event by some reason.158return;159}160161static JNF_CLASS_CACHE(jc_TrayIcon, "sun/lwawt/macosx/CTrayIcon");162static JNF_MEMBER_CACHE(jm_handleMouseEvent, jc_TrayIcon, "handleMouseEvent", "(Lsun/lwawt/macosx/NSEvent;)V");163JNFCallVoidMethod(env, peer, jm_handleMouseEvent, jEvent);164}165166@end //AWTTrayIcon167//================================================168169@implementation AWTTrayIconView170171-(id)initWithTrayIcon:(AWTTrayIcon *)theTrayIcon {172self = [super initWithFrame:NSMakeRect(0, 0, 1, 1)];173174[self setTrayIcon: theTrayIcon];175isHighlighted = NO;176image = nil;177178return self;179}180181-(void) dealloc {182[image release];183[super dealloc];184}185186- (void)setHighlighted:(BOOL)aFlag187{188if (isHighlighted != aFlag) {189isHighlighted = aFlag;190[self setNeedsDisplay:YES];191}192}193194- (void)setImage:(NSImage*)anImage {195[anImage retain];196[image release];197image = anImage;198199if (image != nil) {200[self setNeedsDisplay:YES];201}202}203204-(void)setTrayIcon:(AWTTrayIcon*)theTrayIcon {205trayIcon = theTrayIcon;206}207208- (void)menuWillOpen:(NSMenu *)menu209{210[self setHighlighted:YES];211}212213- (void)menuDidClose:(NSMenu *)menu214{215[menu setDelegate:nil];216[self setHighlighted:NO];217}218219- (void)drawRect:(NSRect)dirtyRect220{221if (image == nil) {222return;223}224225NSRect bounds = [self bounds];226NSSize imageSize = [image size];227228NSRect drawRect = {{ (bounds.size.width - imageSize.width) / 2.0,229(bounds.size.height - imageSize.height) / 2.0 }, imageSize};230231// don't cover bottom pixels of the status bar with the image232if (drawRect.origin.y < 1.0) {233drawRect.origin.y = 1.0;234}235drawRect = NSIntegralRect(drawRect);236237[trayIcon.theItem drawStatusBarBackgroundInRect:bounds238withHighlight:isHighlighted];239[image drawInRect:drawRect240fromRect:NSZeroRect241operation:NSCompositeSourceOver242fraction:1.0243];244}245246- (void)mouseDown:(NSEvent *)event {247[trayIcon deliverJavaMouseEvent: event];248249// don't show the menu on ctrl+click: it triggers ACTION event, like right click250if (([event modifierFlags] & NSControlKeyMask) == 0) {251//find CTrayIcon.getPopupMenuModel method and call it to get popup menu ptr.252JNIEnv *env = [ThreadUtilities getJNIEnv];253static JNF_CLASS_CACHE(jc_CTrayIcon, "sun/lwawt/macosx/CTrayIcon");254static JNF_MEMBER_CACHE(jm_getPopupMenuModel, jc_CTrayIcon, "getPopupMenuModel", "()J");255jlong res = JNFCallLongMethod(env, trayIcon.peer, jm_getPopupMenuModel);256257if (res != 0) {258CPopupMenu *cmenu = jlong_to_ptr(res);259NSMenu* menu = [cmenu menu];260[menu setDelegate:self];261[trayIcon.theItem popUpStatusItemMenu:menu];262[self setNeedsDisplay:YES];263}264}265}266267- (void) mouseUp:(NSEvent *)event {268[trayIcon deliverJavaMouseEvent: event];269}270271- (void) mouseDragged:(NSEvent *)event {272[trayIcon deliverJavaMouseEvent: event];273}274275- (void) rightMouseDown:(NSEvent *)event {276[trayIcon deliverJavaMouseEvent: event];277}278279- (void) rightMouseUp:(NSEvent *)event {280[trayIcon deliverJavaMouseEvent: event];281}282283- (void) rightMouseDragged:(NSEvent *)event {284[trayIcon deliverJavaMouseEvent: event];285}286287- (void) otherMouseDown:(NSEvent *)event {288[trayIcon deliverJavaMouseEvent: event];289}290291- (void) otherMouseUp:(NSEvent *)event {292[trayIcon deliverJavaMouseEvent: event];293}294295- (void) otherMouseDragged:(NSEvent *)event {296[trayIcon deliverJavaMouseEvent: event];297}298299300@end //AWTTrayIconView301//================================================302303/*304* Class: sun_lwawt_macosx_CTrayIcon305* Method: nativeCreate306* Signature: ()J307*/308JNIEXPORT jlong JNICALL Java_sun_lwawt_macosx_CTrayIcon_nativeCreate309(JNIEnv *env, jobject peer) {310__block AWTTrayIcon *trayIcon = nil;311312JNF_COCOA_ENTER(env);313314jobject thePeer = JNFNewGlobalRef(env, peer);315[ThreadUtilities performOnMainThreadWaiting:YES block:^(){316trayIcon = [[AWTTrayIcon alloc] initWithPeer:thePeer];317}];318319JNF_COCOA_EXIT(env);320321return ptr_to_jlong(trayIcon);322}323324325/*326* Class: java_awt_TrayIcon327* Method: initIDs328* Signature: ()V329*/330JNIEXPORT void JNICALL Java_java_awt_TrayIcon_initIDs331(JNIEnv *env, jclass cls) {332//Do nothing.333}334335/*336* Class: sun_lwawt_macosx_CTrayIcon337* Method: nativeSetToolTip338* Signature: (JLjava/lang/String;)V339*/340JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CTrayIcon_nativeSetToolTip341(JNIEnv *env, jobject self, jlong model, jstring jtooltip) {342JNF_COCOA_ENTER(env);343344AWTTrayIcon *icon = jlong_to_ptr(model);345NSString *tooltip = JNFJavaToNSString(env, jtooltip);346[ThreadUtilities performOnMainThreadWaiting:NO block:^(){347[icon setTooltip:tooltip];348}];349350JNF_COCOA_EXIT(env);351}352353/*354* Class: sun_lwawt_macosx_CTrayIcon355* Method: setNativeImage356* Signature: (JJZ)V357*/358JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CTrayIcon_setNativeImage359(JNIEnv *env, jobject self, jlong model, jlong imagePtr, jboolean autosize) {360JNF_COCOA_ENTER(env);361362AWTTrayIcon *icon = jlong_to_ptr(model);363[ThreadUtilities performOnMainThreadWaiting:YES block:^(){364[icon setImage:jlong_to_ptr(imagePtr) sizing:autosize];365}];366367JNF_COCOA_EXIT(env);368}369370JNIEXPORT jobject JNICALL371Java_sun_lwawt_macosx_CTrayIcon_nativeGetIconLocation372(JNIEnv *env, jobject self, jlong model) {373jobject jpt = NULL;374375JNF_COCOA_ENTER(env);376377__block NSPoint pt = NSZeroPoint;378AWTTrayIcon *icon = jlong_to_ptr(model);379[ThreadUtilities performOnMainThreadWaiting:YES block:^(){380NSPoint loc = [icon getLocationOnScreen];381pt = ConvertNSScreenPoint(env, loc);382}];383384jpt = NSToJavaPoint(env, pt);385386JNF_COCOA_EXIT(env);387388return jpt;389}390391392