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