7124321: [macosx] TrayIcon MouseListener is never triggered
Reviewed-by: anthony
This commit is contained in:
parent
63a30e3268
commit
743e5c0d91
@ -26,6 +26,7 @@
|
|||||||
package sun.lwawt.macosx;
|
package sun.lwawt.macosx;
|
||||||
|
|
||||||
import sun.awt.SunToolkit;
|
import sun.awt.SunToolkit;
|
||||||
|
import sun.lwawt.macosx.event.NSEvent;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
@ -42,6 +43,16 @@ public class CTrayIcon extends CFRetainedResource implements TrayIconPeer {
|
|||||||
private JDialog messageDialog;
|
private JDialog messageDialog;
|
||||||
private DialogEventHandler handler;
|
private DialogEventHandler handler;
|
||||||
|
|
||||||
|
// In order to construct MouseEvent object, we need to specify a
|
||||||
|
// Component target. Because TrayIcon isn't Component's subclass,
|
||||||
|
// we use this dummy frame instead
|
||||||
|
private final Frame dummyFrame;
|
||||||
|
|
||||||
|
// A bitmask that indicates what mouse buttons produce MOUSE_CLICKED events
|
||||||
|
// on MOUSE_RELEASE. Click events are only generated if there were no drag
|
||||||
|
// events between MOUSE_PRESSED and MOUSE_RELEASED for particular button
|
||||||
|
private static int mouseClickButtons = 0;
|
||||||
|
|
||||||
CTrayIcon(TrayIcon target) {
|
CTrayIcon(TrayIcon target) {
|
||||||
super(0, true);
|
super(0, true);
|
||||||
|
|
||||||
@ -49,6 +60,7 @@ public class CTrayIcon extends CFRetainedResource implements TrayIconPeer {
|
|||||||
this.handler = null;
|
this.handler = null;
|
||||||
this.target = target;
|
this.target = target;
|
||||||
this.popup = target.getPopupMenu();
|
this.popup = target.getPopupMenu();
|
||||||
|
this.dummyFrame = new Frame();
|
||||||
setPtr(createModel());
|
setPtr(createModel());
|
||||||
|
|
||||||
//if no one else is creating the peer.
|
//if no one else is creating the peer.
|
||||||
@ -119,6 +131,8 @@ public class CTrayIcon extends CFRetainedResource implements TrayIconPeer {
|
|||||||
disposeMessageDialog();
|
disposeMessageDialog();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dummyFrame.dispose();
|
||||||
|
|
||||||
LWCToolkit.targetDisposedPeer(target, this);
|
LWCToolkit.targetDisposedPeer(target, this);
|
||||||
target = null;
|
target = null;
|
||||||
|
|
||||||
@ -161,17 +175,78 @@ public class CTrayIcon extends CFRetainedResource implements TrayIconPeer {
|
|||||||
|
|
||||||
private native void setNativeImage(final long model, final long nsimage, final boolean autosize);
|
private native void setNativeImage(final long model, final long nsimage, final boolean autosize);
|
||||||
|
|
||||||
//invocation from the AWTTrayIcon.m
|
private void postEvent(final AWTEvent event) {
|
||||||
public void performAction() {
|
|
||||||
SunToolkit.executeOnEventHandlerThread(target, new Runnable() {
|
SunToolkit.executeOnEventHandlerThread(target, new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
final String cmd = target.getActionCommand();
|
|
||||||
final ActionEvent event = new ActionEvent(target, ActionEvent.ACTION_PERFORMED, cmd);
|
|
||||||
SunToolkit.postEvent(SunToolkit.targetToAppContext(target), event);
|
SunToolkit.postEvent(SunToolkit.targetToAppContext(target), event);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//invocation from the AWTTrayIcon.m
|
||||||
|
private void handleMouseEvent(NSEvent nsEvent) {
|
||||||
|
int buttonNumber = nsEvent.getButtonNumber();
|
||||||
|
final SunToolkit tk = (SunToolkit)Toolkit.getDefaultToolkit();
|
||||||
|
if ((buttonNumber > 2 && !tk.areExtraMouseButtonsEnabled())
|
||||||
|
|| buttonNumber > tk.getNumberOfButtons() - 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int jeventType = NSEvent.nsToJavaEventType(nsEvent.getType());
|
||||||
|
|
||||||
|
int jbuttonNumber = MouseEvent.NOBUTTON;
|
||||||
|
int jclickCount = 0;
|
||||||
|
if (jeventType != MouseEvent.MOUSE_MOVED) {
|
||||||
|
jbuttonNumber = NSEvent.nsToJavaButton(buttonNumber);
|
||||||
|
jclickCount = nsEvent.getClickCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
int jmodifiers = NSEvent.nsToJavaMouseModifiers(buttonNumber,
|
||||||
|
nsEvent.getModifierFlags());
|
||||||
|
boolean isPopupTrigger = NSEvent.isPopupTrigger(jmodifiers);
|
||||||
|
|
||||||
|
int eventButtonMask = (jbuttonNumber > 0)?
|
||||||
|
MouseEvent.getMaskForButton(jbuttonNumber) : 0;
|
||||||
|
long when = System.currentTimeMillis();
|
||||||
|
|
||||||
|
if (jeventType == MouseEvent.MOUSE_PRESSED) {
|
||||||
|
mouseClickButtons |= eventButtonMask;
|
||||||
|
} else if (jeventType == MouseEvent.MOUSE_DRAGGED) {
|
||||||
|
mouseClickButtons = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The MouseEvent's coordinates are relative to screen
|
||||||
|
int absX = nsEvent.getAbsX();
|
||||||
|
int absY = nsEvent.getAbsY();
|
||||||
|
|
||||||
|
MouseEvent mouseEvent = new MouseEvent(dummyFrame, jeventType, when,
|
||||||
|
jmodifiers, absX, absY, absX, absY, jclickCount, isPopupTrigger,
|
||||||
|
jbuttonNumber);
|
||||||
|
mouseEvent.setSource(target);
|
||||||
|
postEvent(mouseEvent);
|
||||||
|
|
||||||
|
// fire ACTION event
|
||||||
|
if (jeventType == MouseEvent.MOUSE_PRESSED && isPopupTrigger) {
|
||||||
|
final String cmd = target.getActionCommand();
|
||||||
|
final ActionEvent event = new ActionEvent(target,
|
||||||
|
ActionEvent.ACTION_PERFORMED, cmd);
|
||||||
|
postEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
// synthesize CLICKED event
|
||||||
|
if (jeventType == MouseEvent.MOUSE_RELEASED) {
|
||||||
|
if ((mouseClickButtons & eventButtonMask) != 0) {
|
||||||
|
MouseEvent clickEvent = new MouseEvent(dummyFrame,
|
||||||
|
MouseEvent.MOUSE_CLICKED, when, jmodifiers, absX, absY,
|
||||||
|
absX, absY, jclickCount, isPopupTrigger, jbuttonNumber);
|
||||||
|
clickEvent.setSource(target);
|
||||||
|
postEvent(clickEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
mouseClickButtons &= ~eventButtonMask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private native Point2D nativeGetIconLocation(long trayIconModel);
|
private native Point2D nativeGetIconLocation(long trayIconModel);
|
||||||
|
|
||||||
public void displayMessageOnEDT(String caption, String text,
|
public void displayMessageOnEDT(String caption, String text,
|
||||||
@ -256,6 +331,9 @@ public class CTrayIcon extends CFRetainedResource implements TrayIconPeer {
|
|||||||
|
|
||||||
dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
|
dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
|
||||||
dialog.setModal(false);
|
dialog.setModal(false);
|
||||||
|
dialog.setModalExclusionType(Dialog.ModalExclusionType.TOOLKIT_EXCLUDE);
|
||||||
|
dialog.setAlwaysOnTop(true);
|
||||||
|
dialog.setAutoRequestFocus(false);
|
||||||
dialog.setResizable(false);
|
dialog.setResizable(false);
|
||||||
dialog.setContentPane(op);
|
dialog.setContentPane(op);
|
||||||
|
|
||||||
|
@ -53,6 +53,7 @@ extern "C" {
|
|||||||
- (jobject) peer;
|
- (jobject) peer;
|
||||||
- (void) setImage:(NSImage *) imagePtr sizing:(BOOL)autosize;
|
- (void) setImage:(NSImage *) imagePtr sizing:(BOOL)autosize;
|
||||||
- (NSPoint) getLocationOnScreen;
|
- (NSPoint) getLocationOnScreen;
|
||||||
|
- (void) deliverJavaMouseEvent:(NSEvent*) event;
|
||||||
|
|
||||||
@end //AWTTrayIcon
|
@end //AWTTrayIcon
|
||||||
|
|
||||||
@ -68,6 +69,7 @@ extern "C" {
|
|||||||
-(id)initWithTrayIcon:(AWTTrayIcon *)theTrayIcon;
|
-(id)initWithTrayIcon:(AWTTrayIcon *)theTrayIcon;
|
||||||
-(void)setHighlighted:(BOOL)aFlag;
|
-(void)setHighlighted:(BOOL)aFlag;
|
||||||
-(void)setImage:(NSImage*)anImage;
|
-(void)setImage:(NSImage*)anImage;
|
||||||
|
-(void)setTrayIcon:(AWTTrayIcon*)theTrayIcon;
|
||||||
|
|
||||||
@end //AWTTrayIconView
|
@end //AWTTrayIconView
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
#import "CTrayIcon.h"
|
#import "CTrayIcon.h"
|
||||||
#import "ThreadUtilities.h"
|
#import "ThreadUtilities.h"
|
||||||
#include "GeomUtilities.h"
|
#include "GeomUtilities.h"
|
||||||
|
#import "LWCToolkit.h"
|
||||||
|
|
||||||
#define kImageInset 4.0
|
#define kImageInset 4.0
|
||||||
|
|
||||||
@ -76,8 +77,9 @@ static NSSize ScaledImageSizeForStatusBar(NSSize imageSize) {
|
|||||||
// Its a bad idea to force the item to release our view by setting
|
// Its a bad idea to force the item to release our view by setting
|
||||||
// the item's view to nil: it can lead to a crash in some scenarios.
|
// the item's view to nil: it can lead to a crash in some scenarios.
|
||||||
// The item will release the view later on, so just set the view's image
|
// The item will release the view later on, so just set the view's image
|
||||||
// to nil since we are done with it.
|
// and tray icon to nil since we are done with it.
|
||||||
[view setImage: nil];
|
[view setImage: nil];
|
||||||
|
[view setTrayIcon: nil];
|
||||||
[view release];
|
[view release];
|
||||||
|
|
||||||
[theItem release];
|
[theItem release];
|
||||||
@ -115,6 +117,45 @@ static NSSize ScaledImageSizeForStatusBar(NSSize imageSize) {
|
|||||||
return [[view window] convertBaseToScreen: NSZeroPoint];
|
return [[view window] convertBaseToScreen: NSZeroPoint];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-(void) deliverJavaMouseEvent: (NSEvent *) event {
|
||||||
|
[AWTToolkit eventCountPlusPlus];
|
||||||
|
|
||||||
|
JNIEnv *env = [ThreadUtilities getJNIEnv];
|
||||||
|
|
||||||
|
NSPoint eventLocation = [event locationInWindow];
|
||||||
|
NSPoint localPoint = [view convertPoint: eventLocation fromView: nil];
|
||||||
|
localPoint.y = [view bounds].size.height - localPoint.y;
|
||||||
|
|
||||||
|
NSPoint absP = [NSEvent mouseLocation];
|
||||||
|
NSEventType type = [event type];
|
||||||
|
|
||||||
|
NSRect screenRect = [[NSScreen mainScreen] frame];
|
||||||
|
absP.y = screenRect.size.height - absP.y;
|
||||||
|
jint clickCount;
|
||||||
|
|
||||||
|
clickCount = [event clickCount];
|
||||||
|
|
||||||
|
static JNF_CLASS_CACHE(jc_NSEvent, "sun/lwawt/macosx/event/NSEvent");
|
||||||
|
static JNF_CTOR_CACHE(jctor_NSEvent, jc_NSEvent, "(IIIIIIIIDD)V");
|
||||||
|
jobject jEvent = JNFNewObject(env, jctor_NSEvent,
|
||||||
|
[event type],
|
||||||
|
[event modifierFlags],
|
||||||
|
clickCount,
|
||||||
|
[event buttonNumber],
|
||||||
|
(jint)localPoint.x, (jint)localPoint.y,
|
||||||
|
(jint)absP.x, (jint)absP.y,
|
||||||
|
[event deltaY],
|
||||||
|
[event deltaX]);
|
||||||
|
if (jEvent == nil) {
|
||||||
|
// Unable to create event by some reason.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JNF_CLASS_CACHE(jc_TrayIcon, "sun/lwawt/macosx/CTrayIcon");
|
||||||
|
static JNF_MEMBER_CACHE(jm_handleMouseEvent, jc_TrayIcon, "handleMouseEvent", "(Lsun/lwawt/macosx/event/NSEvent;)V");
|
||||||
|
JNFCallVoidMethod(env, peer, jm_handleMouseEvent, jEvent);
|
||||||
|
}
|
||||||
|
|
||||||
@end //AWTTrayIcon
|
@end //AWTTrayIcon
|
||||||
//================================================
|
//================================================
|
||||||
|
|
||||||
@ -123,7 +164,7 @@ static NSSize ScaledImageSizeForStatusBar(NSSize imageSize) {
|
|||||||
-(id)initWithTrayIcon:(AWTTrayIcon *)theTrayIcon {
|
-(id)initWithTrayIcon:(AWTTrayIcon *)theTrayIcon {
|
||||||
self = [super initWithFrame:NSMakeRect(0, 0, 1, 1)];
|
self = [super initWithFrame:NSMakeRect(0, 0, 1, 1)];
|
||||||
|
|
||||||
trayIcon = theTrayIcon;
|
[self setTrayIcon: theTrayIcon];
|
||||||
isHighlighted = NO;
|
isHighlighted = NO;
|
||||||
image = nil;
|
image = nil;
|
||||||
|
|
||||||
@ -153,6 +194,10 @@ static NSSize ScaledImageSizeForStatusBar(NSSize imageSize) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-(void)setTrayIcon:(AWTTrayIcon*)theTrayIcon {
|
||||||
|
trayIcon = theTrayIcon;
|
||||||
|
}
|
||||||
|
|
||||||
- (void)menuWillOpen:(NSMenu *)menu
|
- (void)menuWillOpen:(NSMenu *)menu
|
||||||
{
|
{
|
||||||
[self setHighlighted:YES];
|
[self setHighlighted:YES];
|
||||||
@ -191,30 +236,57 @@ static NSSize ScaledImageSizeForStatusBar(NSSize imageSize) {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) mouseDown:(NSEvent *)e {
|
- (void)mouseDown:(NSEvent *)event {
|
||||||
//find CTrayIcon.getPopupMenuModel method and call it to get popup menu ptr.
|
[trayIcon deliverJavaMouseEvent: event];
|
||||||
JNIEnv *env = [ThreadUtilities getJNIEnv];
|
|
||||||
static JNF_CLASS_CACHE(jc_CTrayIcon, "sun/lwawt/macosx/CTrayIcon");
|
// don't show the menu on ctrl+click: it triggers ACTION event, like right click
|
||||||
static JNF_MEMBER_CACHE(jm_getPopupMenuModel, jc_CTrayIcon, "getPopupMenuModel", "()J");
|
if (([event modifierFlags] & NSControlKeyMask) == 0) {
|
||||||
static JNF_MEMBER_CACHE(jm_performAction, jc_CTrayIcon, "performAction", "()V");
|
//find CTrayIcon.getPopupMenuModel method and call it to get popup menu ptr.
|
||||||
jlong res = JNFCallLongMethod(env, trayIcon.peer, jm_getPopupMenuModel);
|
JNIEnv *env = [ThreadUtilities getJNIEnv];
|
||||||
if (res != 0) {
|
static JNF_CLASS_CACHE(jc_CTrayIcon, "sun/lwawt/macosx/CTrayIcon");
|
||||||
CPopupMenu *cmenu = jlong_to_ptr(res);
|
static JNF_MEMBER_CACHE(jm_getPopupMenuModel, jc_CTrayIcon, "getPopupMenuModel", "()J");
|
||||||
NSMenu* menu = [cmenu menu];
|
jlong res = JNFCallLongMethod(env, trayIcon.peer, jm_getPopupMenuModel);
|
||||||
[menu setDelegate:self];
|
|
||||||
[trayIcon.theItem popUpStatusItemMenu:menu];
|
if (res != 0) {
|
||||||
[self setNeedsDisplay:YES];
|
CPopupMenu *cmenu = jlong_to_ptr(res);
|
||||||
} else {
|
NSMenu* menu = [cmenu menu];
|
||||||
JNFCallVoidMethod(env, trayIcon.peer, jm_performAction);
|
[menu setDelegate:self];
|
||||||
|
[trayIcon.theItem popUpStatusItemMenu:menu];
|
||||||
|
[self setNeedsDisplay:YES];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) rightMouseDown:(NSEvent *)e {
|
- (void) mouseUp:(NSEvent *)event {
|
||||||
// Call CTrayIcon.performAction() method on right mouse press
|
[trayIcon deliverJavaMouseEvent: event];
|
||||||
JNIEnv *env = [ThreadUtilities getJNIEnv];
|
}
|
||||||
static JNF_CLASS_CACHE(jc_CTrayIcon, "sun/lwawt/macosx/CTrayIcon");
|
|
||||||
static JNF_MEMBER_CACHE(jm_performAction, jc_CTrayIcon, "performAction", "()V");
|
- (void) mouseDragged:(NSEvent *)event {
|
||||||
JNFCallVoidMethod(env, trayIcon.peer, jm_performAction);
|
[trayIcon deliverJavaMouseEvent: event];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) rightMouseDown:(NSEvent *)event {
|
||||||
|
[trayIcon deliverJavaMouseEvent: event];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) rightMouseUp:(NSEvent *)event {
|
||||||
|
[trayIcon deliverJavaMouseEvent: event];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) rightMouseDragged:(NSEvent *)event {
|
||||||
|
[trayIcon deliverJavaMouseEvent: event];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) otherMouseDown:(NSEvent *)event {
|
||||||
|
[trayIcon deliverJavaMouseEvent: event];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) otherMouseUp:(NSEvent *)event {
|
||||||
|
[trayIcon deliverJavaMouseEvent: event];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) otherMouseDragged:(NSEvent *)event {
|
||||||
|
[trayIcon deliverJavaMouseEvent: event];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user