提交 50732c42 编写于 作者: A alexsch

7171045: [macosx] There are no enter or exit events reported against 8b39 for...

7171045: [macosx] There are no enter or exit events reported against 8b39 for MouseEventsDuringDrag.
Reviewed-by: anthony, serb
上级 ebd5d929
......@@ -88,10 +88,16 @@ public class LWWindowPeer
private volatile int windowState = Frame.NORMAL;
// A peer where the last mouse event came to. Used to generate
// MOUSE_ENTERED/EXITED notifications and by cursor manager to
// check that the mouse is over the window
private volatile boolean isMouseOver = false;
// A peer where the last mouse event came to. Used by cursor manager to
// find the component under cursor
private static volatile LWComponentPeer lastMouseEventPeer = null;
private static volatile LWComponentPeer lastCommonMouseEventPeer = null;
// A peer where the last mouse event came to. Used to generate
// MOUSE_ENTERED/EXITED notifications
private volatile LWComponentPeer lastMouseEventPeer;
// Peers where all dragged/released events should come to,
// depending on what mouse button is being dragged according to Cocoa
......@@ -707,66 +713,65 @@ public class LWWindowPeer
Rectangle r = getBounds();
// findPeerAt() expects parent coordinates
LWComponentPeer targetPeer = findPeerAt(r.x + x, r.y + y);
LWWindowPeer lastWindowPeer =
(lastMouseEventPeer != null) ? lastMouseEventPeer.getWindowPeerOrSelf() : null;
LWWindowPeer curWindowPeer =
(targetPeer != null) ? targetPeer.getWindowPeerOrSelf() : null;
if (id == MouseEvent.MOUSE_EXITED) {
// Sometimes we may get MOUSE_EXITED after lastMouseEventPeer is switched
// to a peer from another window. So we must first check if this peer is
// the same as lastWindowPeer
if (lastWindowPeer == this) {
if (isEnabled()) {
isMouseOver = false;
if (lastMouseEventPeer != null) {
if (lastMouseEventPeer.isEnabled()) {
Point lp = lastMouseEventPeer.windowToLocal(x, y,
lastWindowPeer);
this);
postEvent(new MouseEvent(lastMouseEventPeer.getTarget(),
MouseEvent.MOUSE_EXITED, when,
modifiers, lp.x, lp.y, screenX,
screenY, clickCount, popupTrigger,
button));
MouseEvent.MOUSE_EXITED, when,
modifiers, lp.x, lp.y, screenX,
screenY, clickCount, popupTrigger,
button));
}
// Sometimes we may get MOUSE_EXITED after lastCommonMouseEventPeer is switched
// to a peer from another window. So we must first check if this peer is
// the same as lastWindowPeer
if (lastCommonMouseEventPeer != null && lastCommonMouseEventPeer.getWindowPeerOrSelf() == this) {
lastCommonMouseEventPeer = null;
}
lastMouseEventPeer = null;
}
} else {
if (targetPeer != lastMouseEventPeer) {
if (id != MouseEvent.MOUSE_DRAGGED || lastMouseEventPeer == null) {
// lastMouseEventPeer may be null if mouse was out of Java windows
if (lastMouseEventPeer != null && lastMouseEventPeer.isEnabled()) {
// Sometimes, MOUSE_EXITED is not sent by delegate (or is sent a bit
// later), in which case lastWindowPeer is another window
if (lastWindowPeer != this) {
Point oldp = lastMouseEventPeer.windowToLocal(x, y, lastWindowPeer);
// Additionally translate from this to lastWindowPeer coordinates
Rectangle lr = lastWindowPeer.getBounds();
oldp.x += r.x - lr.x;
oldp.y += r.y - lr.y;
postEvent(new MouseEvent(lastMouseEventPeer.getTarget(),
MouseEvent.MOUSE_EXITED,
when, modifiers,
oldp.x, oldp.y, screenX, screenY,
clickCount, popupTrigger, button));
} else {
Point oldp = lastMouseEventPeer.windowToLocal(x, y, this);
postEvent(new MouseEvent(lastMouseEventPeer.getTarget(),
MouseEvent.MOUSE_EXITED,
when, modifiers,
oldp.x, oldp.y, screenX, screenY,
clickCount, popupTrigger, button));
}
}
if (targetPeer != null && targetPeer.isEnabled() && id != MouseEvent.MOUSE_ENTERED) {
Point newp = targetPeer.windowToLocal(x, y, curWindowPeer);
} else if(id == MouseEvent.MOUSE_ENTERED) {
isMouseOver = true;
if (targetPeer != null) {
if (targetPeer.isEnabled()) {
Point lp = targetPeer.windowToLocal(x, y, this);
postEvent(new MouseEvent(targetPeer.getTarget(),
MouseEvent.MOUSE_ENTERED,
when, modifiers,
newp.x, newp.y, screenX, screenY,
clickCount, popupTrigger, button));
}
MouseEvent.MOUSE_ENTERED, when,
modifiers, lp.x, lp.y, screenX,
screenY, clickCount, popupTrigger,
button));
}
lastCommonMouseEventPeer = targetPeer;
lastMouseEventPeer = targetPeer;
}
} else {
PlatformWindow topmostPlatforWindow =
platformWindow.getTopmostPlatformWindowUnderMouse();
LWWindowPeer topmostWindowPeer =
topmostPlatforWindow != null ? topmostPlatforWindow.getPeer() : null;
// topmostWindowPeer == null condition is added for the backward
// compatibility with applets. It can be removed when the
// getTopmostPlatformWindowUnderMouse() method will be properly
// implemented in CPlatformEmbeddedFrame class
if (topmostWindowPeer == this || topmostWindowPeer == null) {
generateMouseEnterExitEventsForComponents(when, button, x, y,
screenX, screenY, modifiers, clickCount, popupTrigger,
targetPeer);
} else {
LWComponentPeer topmostTargetPeer =
topmostWindowPeer != null ? topmostWindowPeer.findPeerAt(r.x + x, r.y + y) : null;
topmostWindowPeer.generateMouseEnterExitEventsForComponents(when, button, x, y,
screenX, screenY, modifiers, clickCount, popupTrigger,
topmostTargetPeer);
}
// TODO: fill "bdata" member of AWTEvent
int eventButtonMask = (button > 0)? MouseEvent.getMaskForButton(button) : 0;
......@@ -816,19 +821,13 @@ public class LWWindowPeer
// mouseClickButtons is updated below, after MOUSE_CLICK is sent
}
// check if we receive mouseEvent from outside the window's bounds
// it can be either mouseDragged or mouseReleased
if (curWindowPeer == null) {
//TODO This can happen if this window is invisible. this is correct behavior in this case?
curWindowPeer = this;
}
if (targetPeer == null) {
//TODO This can happen if this window is invisible. this is correct behavior in this case?
targetPeer = this;
}
Point lp = targetPeer.windowToLocal(x, y, curWindowPeer);
Point lp = targetPeer.windowToLocal(x, y, this);
if (targetPeer.isEnabled()) {
MouseEvent event = new MouseEvent(targetPeer.getTarget(), id,
when, modifiers, lp.x, lp.y,
......@@ -852,6 +851,38 @@ public class LWWindowPeer
notifyUpdateCursor();
}
private void generateMouseEnterExitEventsForComponents(long when,
int button, int x, int y, int screenX, int screenY,
int modifiers, int clickCount, boolean popupTrigger,
LWComponentPeer targetPeer) {
if (!isMouseOver || targetPeer == lastMouseEventPeer) {
return;
}
// Generate Mouse Exit for components
if (lastMouseEventPeer != null && lastMouseEventPeer.isEnabled()) {
Point oldp = lastMouseEventPeer.windowToLocal(x, y, this);
postEvent(new MouseEvent(lastMouseEventPeer.getTarget(),
MouseEvent.MOUSE_EXITED,
when, modifiers,
oldp.x, oldp.y, screenX, screenY,
clickCount, popupTrigger, button));
}
lastCommonMouseEventPeer = targetPeer;
lastMouseEventPeer = targetPeer;
// Generate Mouse Enter for components
if (targetPeer != null && targetPeer.isEnabled()) {
Point newp = targetPeer.windowToLocal(x, y, this);
postEvent(new MouseEvent(targetPeer.getTarget(),
MouseEvent.MOUSE_ENTERED,
when, modifiers,
newp.x, newp.y, screenX, screenY,
clickCount, popupTrigger, button));
}
}
public void dispatchMouseWheelEvent(long when, int x, int y, int modifiers,
int scrollType, int scrollAmount,
int wheelRotation, double preciseWheelRotation,
......@@ -1096,11 +1127,11 @@ public class LWWindowPeer
}
public static LWWindowPeer getWindowUnderCursor() {
return lastMouseEventPeer != null ? lastMouseEventPeer.getWindowPeerOrSelf() : null;
return lastCommonMouseEventPeer != null ? lastCommonMouseEventPeer.getWindowPeerOrSelf() : null;
}
public static LWComponentPeer<?, ?> getPeerUnderCursor() {
return lastMouseEventPeer;
return lastCommonMouseEventPeer;
}
/*
......
......@@ -118,6 +118,8 @@ public interface PlatformWindow {
public void setAlwaysOnTop(boolean value);
public PlatformWindow getTopmostPlatformWindowUnderMouse();
public void updateFocusableWindowState();
public boolean rejectFocusRequest(CausedFocusEvent.Cause cause);
......
......@@ -151,6 +151,10 @@ public class CPlatformEmbeddedFrame implements PlatformWindow {
@Override
public void setAlwaysOnTop(boolean value) {}
// This method should be properly implemented for applets.
// It returns null just as a stub.
public PlatformWindow getTopmostPlatformWindowUnderMouse() { return null; }
@Override
public void updateFocusableWindowState() {}
......
......@@ -61,8 +61,9 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
private static native void nativeSetNSWindowRepresentedFilename(long nsWindowPtr, String representedFilename);
private static native void nativeSetNSWindowSecurityWarningPositioning(long nsWindowPtr, double x, double y, float biasX, float biasY);
private static native void nativeSetEnabled(long nsWindowPtr, boolean isEnabled);
private static native void nativeSynthesizeMouseEnteredExitedEvents(long nsWindowPtr);
private static native void nativeSynthesizeMouseEnteredExitedEvents();
private static native void nativeDispose(long nsWindowPtr);
private static native CPlatformWindow nativeGetTopmostPlatformWindowUnderMouse();
private static native int nativeGetNSWindowDisplayID_AppKitThread(long nsWindowPtr);
......@@ -588,7 +589,7 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
}
}
nativeSynthesizeMouseEnteredExitedEvents(nsWindowPtr);
nativeSynthesizeMouseEnteredExitedEvents();
// Configure stuff #2
updateFocusabilityForAutoRequestFocus(true);
......@@ -729,6 +730,10 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
setStyleBits(ALWAYS_ON_TOP, isAlwaysOnTop);
}
public PlatformWindow getTopmostPlatformWindowUnderMouse(){
return CPlatformWindow.nativeGetTopmostPlatformWindowUnderMouse();
}
@Override
public void setOpacity(float opacity) {
CWrapper.NSWindow.setAlphaValue(getNSWindowPtr(), opacity);
......@@ -803,7 +808,7 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
throw new RuntimeException("Unknown window state: " + windowState);
}
nativeSynthesizeMouseEnteredExitedEvents(nsWindowPtr);
nativeSynthesizeMouseEnteredExitedEvents();
// NOTE: the SWP.windowState field gets updated to the newWindowState
// value when the native notification comes to us
......
......@@ -33,8 +33,8 @@
@private
jobject m_cPlatformView;
// Handler for the tracking rect needed for Enter/Exit events management.
NSTrackingRectTag rolloverTrackingRectTag;
// Handler for the tracking area needed for Enter/Exit events management.
NSTrackingArea* rolloverTrackingArea;
// TODO: NSMenu *contextualMenu;
......@@ -61,7 +61,7 @@
- (id) initWithRect:(NSRect) rect platformView:(jobject)cPlatformView windowLayer:(CALayer*)windowLayer;
- (void) deliverJavaMouseEvent: (NSEvent *) event;
- (void) resetTrackingRect;
- (void) resetTrackingArea;
- (void) deliverJavaKeyEventHelper: (NSEvent *) event;
- (jobject) awtComponent:(JNIEnv *)env;
......
......@@ -82,6 +82,7 @@ AWT_ASSERT_APPKIT_THREAD;
fPAHNeedsToSelect = NO;
mouseIsOver = NO;
[self resetTrackingArea];
if (windowLayer != nil) {
self.cglLayer = windowLayer;
......@@ -146,7 +147,7 @@ AWT_ASSERT_APPKIT_THREAD;
[[self window] makeFirstResponder: self];
}];
if ([self window] != NULL) {
[self resetTrackingRect];
[self resetTrackingArea];
}
}
......@@ -368,30 +369,31 @@ AWT_ASSERT_APPKIT_THREAD;
JNFCallVoidMethod(env, m_cPlatformView, jm_deliverMouseEvent, jEvent);
}
- (void) clearTrackingRect {
if (rolloverTrackingRectTag > 0) {
[self removeTrackingRect:rolloverTrackingRectTag];
rolloverTrackingRectTag = 0;
- (void) resetTrackingArea {
if (rolloverTrackingArea != nil) {
[self removeTrackingArea:rolloverTrackingArea];
[rolloverTrackingArea release];
}
}
- (void) resetTrackingRect {
[self clearTrackingRect];
rolloverTrackingRectTag = [self addTrackingRect:[self visibleRect]
owner:self
userData:NULL
assumeInside:NO];
int options = (NSTrackingActiveInActiveApp | NSTrackingMouseEnteredAndExited |
NSTrackingMouseMoved | NSTrackingEnabledDuringMouseDrag);
rolloverTrackingArea = [[NSTrackingArea alloc] initWithRect:[self visibleRect]
options: options
owner:self
userInfo:nil
];
[self addTrackingArea:rolloverTrackingArea];
}
- (void)updateTrackingAreas {
[super updateTrackingAreas];
[self resetTrackingRect];
[self resetTrackingArea];
}
- (void) resetCursorRects {
[super resetCursorRects];
[self resetTrackingRect];
[self resetTrackingArea];
}
-(void) deliverJavaKeyEventHelper: (NSEvent *) event {
......@@ -402,7 +404,7 @@ AWT_ASSERT_APPKIT_THREAD;
}
[sLastKeyEvent release];
sLastKeyEvent = [event retain];
[AWTToolkit eventCountPlusPlus];
JNIEnv *env = [ThreadUtilities getJNIEnv];
......
......@@ -238,10 +238,12 @@ AWT_ASSERT_APPKIT_THREAD;
return self;
}
// checks that this window is under the mouse cursor and this point is not overlapped by others windows
- (BOOL) isTopmostWindowUnderMouse {
+ (BOOL) isAWTWindow:(NSWindow *)window {
return [window isKindOfClass: [AWTWindow_Panel class]] || [window isKindOfClass: [AWTWindow_Normal class]];
}
int currentWinID = [self.nsWindow windowNumber];
// returns id for the topmost window under mouse
+ (NSInteger) getTopmostWindowUnderMouseID {
NSRect screenRect = [[NSScreen mainScreen] frame];
NSPoint nsMouseLocation = [NSEvent mouseLocation];
......@@ -249,53 +251,77 @@ AWT_ASSERT_APPKIT_THREAD;
NSMutableArray *windows = (NSMutableArray *)CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements, kCGNullWindowID);
for (NSDictionary *window in windows) {
int layer = [[window objectForKey:(id)kCGWindowLayer] intValue];
NSInteger layer = [[window objectForKey:(id)kCGWindowLayer] integerValue];
if (layer == 0) {
int winID = [[window objectForKey:(id)kCGWindowNumber] intValue];
CGRect rect;
CGRectMakeWithDictionaryRepresentation((CFDictionaryRef)[window objectForKey:(id)kCGWindowBounds], &rect);
if (CGRectContainsPoint(rect, cgMouseLocation)) {
return currentWinID == winID;
} else if (currentWinID == winID) {
return NO;
return [[window objectForKey:(id)kCGWindowNumber] integerValue];
}
}
}
return NO;
return -1;
}
- (void) synthesizeMouseEnteredExitedEvents {
// checks that this window is under the mouse cursor and this point is not overlapped by others windows
- (BOOL) isTopmostWindowUnderMouse {
return [self.nsWindow windowNumber] == [AWTWindow getTopmostWindowUnderMouseID];
}
int eventType = 0;
BOOL isUnderMouse = [self isTopmostWindowUnderMouse];
BOOL mouseIsOver = [[self.nsWindow contentView] mouseIsOver];
+ (AWTWindow *) getTopmostWindowUnderMouse {
NSEnumerator *windowEnumerator = [[NSApp windows] objectEnumerator];
NSWindow *window;
if (isUnderMouse && !mouseIsOver) {
eventType = NSMouseEntered;
} else if (!isUnderMouse && mouseIsOver) {
eventType = NSMouseExited;
} else {
return;
NSInteger topmostWindowUnderMouseID = [AWTWindow getTopmostWindowUnderMouseID];
while ((window = [windowEnumerator nextObject]) != nil) {
if ([window windowNumber] == topmostWindowUnderMouseID) {
BOOL isAWTWindow = [AWTWindow isAWTWindow: window];
return isAWTWindow ? (AWTWindow *) [window delegate] : nil;
}
}
return nil;
}
+ (void) synthesizeMouseEnteredExitedEvents:(NSWindow*)window withType:(NSEventType)eventType {
NSPoint screenLocation = [NSEvent mouseLocation];
NSPoint windowLocation = [self.nsWindow convertScreenToBase: screenLocation];
NSPoint windowLocation = [window convertScreenToBase: screenLocation];
int modifierFlags = (eventType == NSMouseEntered) ? NSMouseEnteredMask : NSMouseExitedMask;
NSEvent *mouseEvent = [NSEvent enterExitEventWithType: eventType
location: windowLocation
modifierFlags: modifierFlags
timestamp: 0
windowNumber: [self.nsWindow windowNumber]
context: nil
eventNumber: 0
trackingNumber: 0
userData: nil
];
[[self.nsWindow contentView] deliverJavaMouseEvent: mouseEvent];
location: windowLocation
modifierFlags: modifierFlags
timestamp: 0
windowNumber: [window windowNumber]
context: nil
eventNumber: 0
trackingNumber: 0
userData: nil
];
[[window contentView] deliverJavaMouseEvent: mouseEvent];
}
+ (void) synthesizeMouseEnteredExitedEventsForAllWindows {
NSInteger topmostWindowUnderMouseID = [AWTWindow getTopmostWindowUnderMouseID];
NSArray *windows = [NSApp windows];
NSWindow *window;
NSEnumerator *windowEnumerator = [windows objectEnumerator];
while ((window = [windowEnumerator nextObject]) != nil) {
if ([AWTWindow isAWTWindow: window]) {
BOOL isUnderMouse = ([window windowNumber] == topmostWindowUnderMouseID);
BOOL mouseIsOver = [[window contentView] mouseIsOver];
if (isUnderMouse && !mouseIsOver) {
[AWTWindow synthesizeMouseEnteredExitedEvents:window withType:NSMouseEntered];
} else if (!isUnderMouse && mouseIsOver) {
[AWTWindow synthesizeMouseEnteredExitedEvents:window withType:NSMouseExited];
}
}
}
}
- (void) dealloc {
......@@ -825,7 +851,7 @@ AWT_ASSERT_NOT_APPKIT_THREAD;
// (this will also re-enable screen updates, which were disabled above)
// TODO: send PaintEvent
[window synthesizeMouseEnteredExitedEvents];
[AWTWindow synthesizeMouseEnteredExitedEventsForAllWindows];
}];
JNF_COCOA_EXIT(env);
......@@ -1038,24 +1064,44 @@ AWT_ASSERT_NOT_APPKIT_THREAD;
JNF_COCOA_EXIT(env);
}
/*
* Class: sun_lwawt_macosx_CPlatformWindow
* Method: nativeGetTopmostPlatformWindowUnderMouse
* Signature: (J)V
*/
JNIEXPORT jobject
JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeGetTopmostPlatformWindowUnderMouse
(JNIEnv *env, jclass clazz)
{
jobject topmostWindowUnderMouse = nil;
JNF_COCOA_ENTER(env);
AWT_ASSERT_APPKIT_THREAD;
AWTWindow *awtWindow = [AWTWindow getTopmostWindowUnderMouse];
if (awtWindow != nil) {
topmostWindowUnderMouse = [awtWindow.javaPlatformWindow jObject];
}
JNF_COCOA_EXIT(env);
return topmostWindowUnderMouse;
}
/*
* Class: sun_lwawt_macosx_CPlatformWindow
* Method: nativeSynthesizeMouseEnteredExitedEvents
* Signature: (J)V
*/
JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSynthesizeMouseEnteredExitedEvents
(JNIEnv *env, jclass clazz, jlong windowPtr)
(JNIEnv *env, jclass clazz)
{
JNF_COCOA_ENTER(env);
AWT_ASSERT_NOT_APPKIT_THREAD;
NSWindow *nsWindow = OBJC(windowPtr);
[JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
AWT_ASSERT_APPKIT_THREAD;
AWTWindow *window = (AWTWindow*)[nsWindow delegate];
[window synthesizeMouseEnteredExitedEvents];
[AWTWindow synthesizeMouseEnteredExitedEventsForAllWindows];
}];
JNF_COCOA_EXIT(env);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册