diff options
author | Sven Gothel <[email protected]> | 2014-05-26 19:04:41 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2014-05-26 19:04:41 +0200 |
commit | 759d90674d977bae24ba58684fad3830f7f0d40f (patch) | |
tree | 16c402b0cc667e7d4d7899f9be92756465a372db | |
parent | 56d60b36798fa8dae48bf2aa5e2de6f3178ab0d1 (diff) |
Bug 1012: Fix erroneous handling of multiple monitor coordinates on OSX with NEWT
To properly convert Top-Left (TL) from/to Bottom-Left (BL) coordinates
we need to utilize the given CGDisplay viewport (TL)
and NSScreen (BL) to perform the y-flip.
This is especially true for the case of having multiple monitors
covering different viewports (mixed resolution).
5 files changed, 91 insertions, 59 deletions
diff --git a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java index 1546bd909..5ef32a5aa 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java +++ b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java @@ -686,6 +686,10 @@ public abstract class NativeWindowFactory { return new WrappedWindow(config, surfaceHandle, hook, true, windowHandle); } + /** + * @param nw + * @return top-left client-area position in window units + */ public static PointImmutable getLocationOnScreen(NativeWindow nw) { final String nwt = NativeWindowFactory.getNativeWindowType(true); if( NativeWindowFactory.TYPE_X11 == nwt ) { @@ -693,7 +697,7 @@ public abstract class NativeWindowFactory { } else if( NativeWindowFactory.TYPE_WINDOWS == nwt ) { return GDIUtil.GetRelativeLocation(nw.getWindowHandle(), 0, 0, 0); } else if( NativeWindowFactory.TYPE_MACOSX == nwt ) { - return OSXUtil.GetLocationOnScreen(nw.getWindowHandle(), null == nw.getParent(), 0, 0); + return OSXUtil.GetLocationOnScreen(nw.getWindowHandle(), 0, 0); /** * FIXME: Needs service provider interface (SPI) for TK dependent implementation } else if( NativeWindowFactory.TYPE_BCM_VC_IV == nwt ) { diff --git a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java index 31b06d360..12e574ced 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java +++ b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java @@ -91,31 +91,13 @@ public class OSXUtil implements ToolkitProperties { } /** - * In case the <code>windowOrView</code> is top-level, - * you shall set <code>topLevel</code> to true where - * insets gets into account to compute the client position as follows: - * <pre> - if(topLevel) { - // top-level position -> client window position - final Insets insets = GetInsets(windowOrView); - los.setX(los.getX() + insets.getLeftWidth()); - los.setY(los.getY() + insets.getTopHeight()); - } - * </pre> * @param windowOrView - * @param topLevel * @param src_x * @param src_y - * @return the client position + * @return top-left client-area position in window units */ - public static Point GetLocationOnScreen(long windowOrView, boolean topLevel, int src_x, int src_y) { - final Point los = (Point) GetLocationOnScreen0(windowOrView, src_x, src_y); - if(topLevel) { - // top-level position -> client window position - final Insets insets = GetInsets(windowOrView); - los.set(los.getX() + insets.getLeftWidth(), los.getY() + insets.getTopHeight()); - } - return los; + public static Point GetLocationOnScreen(long windowOrView, int src_x, int src_y) { + return (Point) GetLocationOnScreen0(windowOrView, src_x, src_y); } public static Insets GetInsets(long windowOrView) { diff --git a/src/nativewindow/native/macosx/OSXmisc.m b/src/nativewindow/native/macosx/OSXmisc.m index 2f5a44584..62d3d67bb 100644 --- a/src/nativewindow/native/macosx/OSXmisc.m +++ b/src/nativewindow/native/macosx/OSXmisc.m @@ -137,6 +137,14 @@ Java_jogamp_nativewindow_macosx_OSXUtil_isNSWindow0(JNIEnv *env, jclass _unused, return u; } +static CGDirectDisplayID OSXUtil_getCGDirectDisplayIDByNSScreen(NSScreen *screen) { + // Mind: typedef uint32_t CGDirectDisplayID; - however, we assume it's 64bit on 64bit ?! + NSDictionary * dict = [screen deviceDescription]; + NSNumber * val = (NSNumber *) [dict objectForKey: @"NSScreenNumber"]; + // [NSNumber integerValue] returns NSInteger which is 32 or 64 bit native size + return (CGDirectDisplayID) [val integerValue]; +} + /* * Class: Java_jogamp_nativewindow_macosx_OSXUtil * Method: getLocationOnScreen0 @@ -151,10 +159,6 @@ JNIEXPORT jobject JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetLocationOnS * return location in 0/0 top-left space, * OSX is 0/0 bottom-left space naturally */ - NSRect r; - int dest_x=-1; - int dest_y=-1; - NSObject *nsObj = (NSObject*) (intptr_t) winOrView; NSWindow* win = NULL; NSView* view = NULL; @@ -166,27 +170,36 @@ JNIEXPORT jobject JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetLocationOnS view = (NSView*) nsObj; win = [view window]; } else { - NativewindowCommon_throwNewRuntimeException(env, "neither win not view %p\n", nsObj); + NativewindowCommon_throwNewRuntimeException(env, "neither win nor view %p\n", nsObj); } - NSScreen* screen = [win screen]; - NSRect screenRect = [screen frame]; - NSRect winFrame = [win frame]; + NSRect viewFrame = [view frame]; + NSRect r; r.origin.x = src_x; - r.origin.y = winFrame.size.height - src_y; // y-flip for 0/0 top-left + r.origin.y = viewFrame.size.height - src_y; // y-flip for 0/0 top-left r.size.width = 0; r.size.height = 0; // NSRect rS = [win convertRectToScreen: r]; // 10.7 - NSPoint oS = [win convertBaseToScreen: r.origin]; - /** - NSLog(@"LOS.1: (bottom-left) %d/%d, screen-y[0: %d, h: %d], (top-left) %d/%d\n", - (int)oS.x, (int)oS.y, (int)screenRect.origin.y, (int) screenRect.size.height, - (int)oS.x, (int)(screenRect.origin.y + screenRect.size.height - oS.y)); */ + NSPoint oS = [win convertBaseToScreen: r.origin]; // BL-screen - dest_x = (int) oS.x; - dest_y = (int) screenRect.origin.y + screenRect.size.height - oS.y; + NSScreen* screen = [win screen]; + CGDirectDisplayID display = OSXUtil_getCGDirectDisplayIDByNSScreen(screen); + CGRect frameTL = CGDisplayBounds (display); // origin top-left + NSRect frameBL = [screen frame]; // origin bottom-left + oS.y = frameTL.origin.y + frameTL.size.height - ( oS.y - frameBL.origin.y ); // y-flip from BL-screen -> TL-screen + +#ifdef VERBOSE + NSRect winFrame = [win frame]; + DBG_PRINT( "GetLocationOnScreen0(window: %p):: point-in[%d/%d], winFrame[%d/%d %dx%d], viewFrame[%d/%d %dx%d], screen tl[%d/%d %dx%d] bl[%d/%d %dx%d] -> %d/%d\n", + win, (int)src_x, (int)src_y, + (int)winFrame.origin.x, (int)winFrame.origin.y, (int)winFrame.size.width, (int)winFrame.size.height, + (int)viewFrame.origin.x, (int)viewFrame.origin.y, (int)viewFrame.size.width, (int)viewFrame.size.height, + (int)frameTL.origin.x, (int)frameTL.origin.y, (int)frameTL.size.width, (int)frameTL.size.height, + (int)frameBL.origin.x, (int)frameBL.origin.y, (int)frameBL.size.width, (int)frameBL.size.height, + (int)oS.x, (int)oS.y); +#endif - jobject res = (*env)->NewObject(env, pointClz, pointCstr, (jint)dest_x, (jint)dest_y); + jobject res = (*env)->NewObject(env, pointClz, pointCstr, (jint)oS.x, (jint)oS.y); [pool release]; diff --git a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java index 540186f2e..4653faf01 100644 --- a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java @@ -430,7 +430,7 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl private Point getLocationOnScreenImpl(final int x, final int y, final NativeWindow parent, final boolean useParent) { if( !useParent && !isOffscreenInstance && 0 != surfaceHandle) { - return OSXUtil.GetLocationOnScreen(surfaceHandle, true, x, y); + return OSXUtil.GetLocationOnScreen(surfaceHandle, x, y); } final Point p = new Point(x, y); diff --git a/src/newt/native/NewtMacWindow.m b/src/newt/native/NewtMacWindow.m index 1a70de445..c4800bd26 100644 --- a/src/newt/native/NewtMacWindow.m +++ b/src/newt/native/NewtMacWindow.m @@ -477,14 +477,26 @@ static jmethodID windowRepaintID = NULL; } } +/** + * p abs screen position w/ bottom-left origin + */ - (void) setMousePosition:(NSPoint)p { NSWindow* nsWin = [self window]; if( NULL != nsWin ) { NSScreen* screen = [nsWin screen]; - NSRect screenRect = [screen frame]; - CGPoint pt = { p.x, screenRect.size.height - p.y }; // y-flip (CG is top-left origin) + CGDirectDisplayID display = NewtScreen_getCGDirectDisplayIDByNSScreen(screen); + CGRect frameTL = CGDisplayBounds (display); // origin top-left + NSRect frameBL = [screen frame]; // origin bottom-left + CGPoint pt = { p.x, frameTL.origin.y + frameTL.size.height - ( p.y - frameBL.origin.y ) }; // y-flip from BL-screen -> TL-screen + + DBG_PRINT( "setMousePosition: point-in[%d/%d], screen tl[%d/%d %dx%d] bl[%d/%d %dx%d] -> %d/%d\n", + (int)p.x, (int)p.y, + (int)frameTL.origin.x, (int)frameTL.origin.y, (int)frameTL.size.width, (int)frameTL.size.height, + (int)frameBL.origin.x, (int)frameBL.origin.y, (int)frameBL.size.width, (int)frameBL.size.height, + (int)pt.x, (int)pt.y); + CGEventRef ev = CGEventCreateMouseEvent (NULL, kCGEventMouseMoved, pt, kCGMouseButtonLeft); CGEventPost (kCGHIDEventTap, ev); } @@ -956,19 +968,20 @@ static jmethodID windowRepaintID = NULL; { int totalHeight = nsz.height + cachedInsets[3]; // height + insets.bottom - DBG_PRINT( "newtAbsClientTLWinPos2AbsBLScreenPos: given %d/%d %dx%d, insets bottom %d -> totalHeight %d\n", + DBG_PRINT( "newtAbsClientTLWinPos2AbsBLScreenPos: point-in[%d/%d], size-in[%dx%d], insets bottom %d -> totalHeight %d\n", (int)p.x, (int)p.y, (int)nsz.width, (int)nsz.height, cachedInsets[3], totalHeight); NSScreen* screen = [self screen]; - NSRect screenFrame = [screen frame]; - DBG_PRINT( "newtAbsClientTLWinPos2AbsBLScreenPos: screen %d/%d %dx%d\n", - (int)screenFrame.origin.x, (int)screenFrame.origin.y, (int)screenFrame.size.width, (int)screenFrame.size.height); + CGDirectDisplayID display = NewtScreen_getCGDirectDisplayIDByNSScreen(screen); + CGRect frameTL = CGDisplayBounds (display); // origin top-left + NSRect frameBL = [screen frame]; // origin bottom-left + NSPoint r = NSMakePoint(p.x, frameBL.origin.y + frameBL.size.height - ( p.y - frameTL.origin.y ) - totalHeight); // y-flip from TL-screen -> BL-screen - NSPoint r = NSMakePoint(screenFrame.origin.x + p.x, - screenFrame.origin.y + screenFrame.size.height - p.y - totalHeight); - - DBG_PRINT( "newtAbsClientTLWinPos2AbsBLScreenPos: result %d/%d\n", (int)r.x, (int)r.y); + DBG_PRINT( "newtAbsClientTLWinPos2AbsBLScreenPos: screen tl[%d/%d %dx%d] bl[%d/%d %dx%d -> %d/%d\n", + (int)frameTL.origin.x, (int)frameTL.origin.y, (int)frameTL.size.width, (int)frameTL.size.height, + (int)frameBL.origin.x, (int)frameBL.origin.y, (int)frameBL.size.width, (int)frameBL.size.height, + (int)r.x, (int)r.y); return r; } @@ -983,9 +996,16 @@ static jmethodID windowRepaintID = NULL; NSView* mView = [self contentView]; NSRect mViewFrame = [mView frame]; + NSPoint r = NSMakePoint(winFrame.origin.x + p.x, + winFrame.origin.y + ( mViewFrame.size.height - p.y ) ); // y-flip in view + + DBG_PRINT( "newtRelClientTLWinPos2AbsBLScreenPos: point-in[%d/%d], winFrame[%d/%d %dx%d], viewFrame[%d/%d %dx%d] -> %d/%d\n", + (int)p.x, (int)p.y, + (int)winFrame.origin.x, (int)winFrame.origin.y, (int)winFrame.size.width, (int)winFrame.size.height, + (int)mViewFrame.origin.x, (int)mViewFrame.origin.y, (int)mViewFrame.size.width, (int)mViewFrame.size.height, + (int)r.x, (int)r.y); - return NSMakePoint(winFrame.origin.x + p.x, - winFrame.origin.y + ( mViewFrame.size.height - p.y ) ); // y-flip in view + return r; } - (NSSize) newtClientSize2TLSize: (NSSize) nsz @@ -1001,20 +1021,33 @@ static jmethodID windowRepaintID = NULL; */ - (NSPoint) getLocationOnScreen: (NSPoint) p { - NSScreen* screen = [self screen]; - NSRect screenRect = [screen frame]; - NSView* view = [self contentView]; NSRect viewFrame = [view frame]; - NSRect r; r.origin.x = p.x; r.origin.y = viewFrame.size.height - p.y; // y-flip r.size.width = 0; r.size.height = 0; - // NSRect rS = [win convertRectToScreen: r]; // 10.7 - NSPoint oS = [self convertBaseToScreen: r.origin]; - oS.y = screenRect.origin.y + screenRect.size.height - oS.y; + // NSRect rS = [self convertRectToScreen: r]; // 10.7 + NSPoint oS = [self convertBaseToScreen: r.origin]; // BL-screen + + NSScreen* screen = [self screen]; + CGDirectDisplayID display = NewtScreen_getCGDirectDisplayIDByNSScreen(screen); + CGRect frameTL = CGDisplayBounds (display); // origin top-left + NSRect frameBL = [screen frame]; // origin bottom-left + oS.y = frameTL.origin.y + frameTL.size.height - ( oS.y - frameBL.origin.y ); // y-flip from BL-screen -> TL-screen + +#ifdef VERBOSE_ON + NSRect winFrame = [self frame]; + DBG_PRINT( "getLocationOnScreen: point-in[%d/%d], winFrame[%d/%d %dx%d], viewFrame[%d/%d %dx%d], screen tl[%d/%d %dx%d] bl[%d/%d %dx%d] -> %d/%d\n", + (int)p.x, (int)p.y, + (int)winFrame.origin.x, (int)winFrame.origin.y, (int)winFrame.size.width, (int)winFrame.size.height, + (int)viewFrame.origin.x, (int)viewFrame.origin.y, (int)viewFrame.size.width, (int)viewFrame.size.height, + (int)frameTL.origin.x, (int)frameTL.origin.y, (int)frameTL.size.width, (int)frameTL.size.height, + (int)frameBL.origin.x, (int)frameBL.origin.y, (int)frameBL.size.width, (int)frameBL.size.height, + (int)oS.x, (int)oS.y); +#endif + return oS; } |