diff options
Diffstat (limited to 'src/newt')
-rw-r--r-- | src/newt/classes/jogamp/newt/WindowImpl.java | 4 | ||||
-rw-r--r-- | src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java | 74 | ||||
-rw-r--r-- | src/newt/native/MacWindow.m | 76 | ||||
-rw-r--r-- | src/newt/native/NewtMacWindow.h | 24 | ||||
-rw-r--r-- | src/newt/native/NewtMacWindow.m | 219 |
5 files changed, 299 insertions, 98 deletions
diff --git a/src/newt/classes/jogamp/newt/WindowImpl.java b/src/newt/classes/jogamp/newt/WindowImpl.java index b8f0929a8..7df326e8e 100644 --- a/src/newt/classes/jogamp/newt/WindowImpl.java +++ b/src/newt/classes/jogamp/newt/WindowImpl.java @@ -119,8 +119,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer private int mouseButtonPressed = 0; // current pressed mouse button number private long lastMousePressed = 0; // last time when a mouse button was pressed private int lastMouseClickCount = 0; // last mouse button click count - private boolean mouseInWindow = false;// mouse entered window - is inside the window (may be synthetic) - private Point lastMousePosition = new Point(); + protected boolean mouseInWindow = false;// mouse entered window - is inside the window (may be synthetic) + protected Point lastMousePosition = new Point(); private ArrayList<KeyListener> keyListeners = new ArrayList<KeyListener>(); diff --git a/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java b/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java index d18d6b901..0bb0b6b13 100644 --- a/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java +++ b/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java @@ -243,6 +243,48 @@ public class MacWindow extends WindowImpl { // nop - using event driven insetsChange(..) } + @Override + protected void sizeChanged(boolean defer, int newWidth, int newHeight, boolean force) { + if(width != newWidth || height != newHeight) { + final Point p0S = position2TopLevel(new Point(x, y)); + setFrameTopLeftPoint0(getParentWindowHandle(), getWindowHandle(), p0S.getX(), p0S.getY()); + } + super.sizeChanged(defer, newWidth, newHeight, force); + } + + @Override + protected void positionChanged(boolean defer, int newX, int newY) { + positionChanged(defer, new Point(newX, newY)); + } + + @Override + protected boolean setPointerVisibleImpl(final boolean pointerVisible) { + return setPointerVisible0(getWindowHandle(), pointerVisible); + } + + @Override + protected boolean confinePointerImpl(final boolean confine) { + return confinePointer0(getWindowHandle(), confine); + } + + @Override + protected void warpPointerImpl(final int x, final int y) { + warpPointer0(getWindowHandle(), x, y); + } + + @Override + public void enqueueKeyEvent(boolean wait, int eventType, int modifiers, int keyCode, char keyChar) { + int key = convertKeyChar(keyChar); + if(DEBUG_IMPLEMENTATION) System.err.println("MacWindow.enqueueKeyEvent "+Thread.currentThread().getName()); + // Note that we send the key char for the key code on this + // platform -- we do not get any useful key codes out of the system + super.enqueueKeyEvent(wait, eventType, modifiers, key, keyChar); + } + + //---------------------------------------------------------------------- + // Internals only + // + private char convertKeyChar(char keyChar) { if (keyChar == '\r') { // Turn these into \n @@ -326,15 +368,6 @@ public class MacWindow extends WindowImpl { return keyChar; } - @Override - public void enqueueKeyEvent(boolean wait, int eventType, int modifiers, int keyCode, char keyChar) { - int key = convertKeyChar(keyChar); - if(DEBUG_IMPLEMENTATION) System.err.println("MacWindow.enqueueKeyEvent "+Thread.currentThread().getName()); - // Note that we send the key char for the key code on this - // platform -- we do not get any useful key codes out of the system - super.enqueueKeyEvent(wait, eventType, modifiers, key, keyChar); - } - private void createWindow(final boolean recreate, PointImmutable pS, int width, int height, final boolean fullscreen) { @@ -377,26 +410,12 @@ public class MacWindow extends WindowImpl { } } - @Override - protected void sizeChanged(boolean defer, int newWidth, int newHeight, boolean force) { - if(width != newWidth || height != newHeight) { - final Point p0S = position2TopLevel(new Point(x, y)); - setFrameTopLeftPoint0(getParentWindowHandle(), getWindowHandle(), p0S.getX(), p0S.getY()); - } - super.sizeChanged(defer, newWidth, newHeight, force); - } - - @Override - protected void positionChanged(boolean defer, int newX, int newY) { - positionChanged(defer, new Point(newX, newY)); - } - - protected void positionChanged(boolean defer, Point absPos) { + private void positionChanged(boolean defer, Point absPos) { position2ClientSpace(absPos); super.positionChanged(defer, absPos.getX(), absPos.getY()); } - protected Point position2ClientSpace(Point absPos) { + private Point position2ClientSpace(Point absPos) { final NativeWindow parent = getParent(); if(null != parent) { return absPos.translate( parent.getLocationOnScreen(null).scale(-1, -1) ); @@ -404,7 +423,7 @@ public class MacWindow extends WindowImpl { return absPos; } - protected Point position2TopLevel(Point clientPos) { + private Point position2TopLevel(Point clientPos) { if(0<=clientPos.getX() && 0<=clientPos.getY()) { final InsetsImmutable _insets = getInsets(); // zero if undecorated // client position -> top-level window position @@ -440,4 +459,7 @@ public class MacWindow extends WindowImpl { private native void setFrameTopLeftPoint0(long parentWindowHandle, long window, int x, int y); private native void setAlwaysOnTop0(long window, boolean atop); private static native Object getLocationOnScreen0(long windowHandle, int src_x, int src_y); + private static native boolean setPointerVisible0(long windowHandle, boolean visible); + private static native boolean confinePointer0(long windowHandle, boolean confine); + private static native void warpPointer0(long windowHandle, int x, int y); } diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m index 670deaf1d..1ddf3363f 100644 --- a/src/newt/native/MacWindow.m +++ b/src/newt/native/MacWindow.m @@ -58,39 +58,11 @@ static NSString* jstringToNSString(JNIEnv* env, jstring jstr) } static void setFrameTopLeftPoint(NSWindow* pWin, NewtMacWindow* mWin, jint x, jint y) { - - NSScreen* screen = [mWin screen]; - NSRect screenTotal = [screen frame]; + NSPoint pS = [mWin newtScreenWinPos2OSXScreenPos: NSMakePoint(x, y)]; + [mWin setFrameOrigin: pS]; NSView* mView = [mWin contentView]; - NSRect mViewFrame = [mView frame]; - int totalHeight = mViewFrame.size.height + mWin->cachedInsets[2] + mWin->cachedInsets[3]; // height + insets[top+bottom] - - NSPoint pS = NSMakePoint(screenTotal.origin.x + x, screenTotal.origin.y + screenTotal.size.height - y - totalHeight); - -#ifdef VERBOSE_ON - NSMenu * menu = [NSApp mainMenu]; - int menuHeight = [NSMenu menuBarVisible] ? (int) [menu menuBarHeight] : 0; - - DBG_PRINT( "setFrameTopLeftPoint screen %lf/%lf %lfx%lf, menuHeight %d, win top-left %d/%d totalHeight %d -> scrn bottom-left %lf/%lf\n", - screenTotal.origin.x, screenTotal.origin.y, screenTotal.size.width, screenTotal.size.height, menuHeight, - (int)x, (int)y, (int)totalHeight, pS.x, pS.y); - - if(NULL != pWin) { - NSView* pView = [pWin contentView]; - NSRect pViewFrame = [pView frame]; - DBG_PRINT( "setFrameTopLeftPoint pViewFrame %lf/%lf %lfx%lf\n", - pViewFrame.origin.x, pViewFrame.origin.y, pViewFrame.size.width, pViewFrame.size.height); - - NSPoint pS0; - pS0.x = 0; pS0.y = 0; - // pS = [win convertRectToScreen: r]; // 10.7 - pS0 = [pWin convertBaseToScreen: pS0]; - DBG_PRINT( "setFrameTopLeftPoint (parent) base 0/0 -> screen: %lf/%lf\n", pS0.x, pS0.y); - } -#endif - - [mWin setFrameOrigin: pS]; + [mWin invalidateCursorRectsForView: mView]; } static NewtView * changeContentView(JNIEnv *env, jobject javaWindowObject, NSWindow *pwin, NSView *pview, NSWindow *win, NewtView *newView) { @@ -364,6 +336,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_MacWindow_createWindow0 // Immediately re-position the window based on an upper-left coordinate system setFrameTopLeftPoint(parentWindow, myWindow, x, y); + [myWindow makeKeyAndOrderFront: myWindow]; NS_DURING // Available >= 10.5 - Makes the menubar disapear @@ -664,8 +637,45 @@ JNIEXPORT jobject JNICALL Java_jogamp_newt_driver_macosx_MacWindow_getLocationOn NewtCommon_throwNewRuntimeException(env, "not NewtMacWindow %p\n", nsObj); } - NSPoint p0 = { src_x, src_y }; - p0 = [mWin getLocationOnScreen: p0]; + NSPoint p0 = [mWin getLocationOnScreen: NSMakePoint(src_x, src_y)]; return (*env)->NewObject(env, pointClz, pointCstr, (jint)p0.x, (jint)p0.y); } +/* + * Class: Java_jogamp_newt_driver_macosx_MacWindow + * Method: setPointerVisible0 + * Signature: (JZ)Z + */ +JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_MacWindow_setPointerVisible0 + (JNIEnv *env, jclass clazz, jlong window, jboolean mouseVisible) +{ + NewtMacWindow *mWin = (NewtMacWindow*) ((intptr_t) window); + [mWin setMouseVisible: ( JNI_TRUE == mouseVisible ) ? YES : NO]; + return JNI_TRUE; +} + +/* + * Class: Java_jogamp_newt_driver_macosx_MacWindow + * Method: confinePointer0 + * Signature: (JZ)Z + */ +JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_MacWindow_confinePointer0 + (JNIEnv *env, jclass clazz, jlong window, jboolean confine) +{ + NewtMacWindow *mWin = (NewtMacWindow*) ((intptr_t) window); + [mWin setMouseConfined: ( JNI_TRUE == confine ) ? YES : NO]; + return JNI_TRUE; +} + +/* + * Class: Java_jogamp_newt_driver_macosx_MacWindow + * Method: warpPointer0 + * Signature: (JJII)V + */ +JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_warpPointer0 + (JNIEnv *env, jclass clazz, jlong window, jint x, jint y) +{ + NewtMacWindow *mWin = (NewtMacWindow*) ((intptr_t) window); + [mWin setMousePosition: [mWin newtClientWinPos2OSXScreenPos: NSMakePoint(x, y)]]; +} + diff --git a/src/newt/native/NewtMacWindow.h b/src/newt/native/NewtMacWindow.h index 911abb8aa..532eba6b4 100644 --- a/src/newt/native/NewtMacWindow.h +++ b/src/newt/native/NewtMacWindow.h @@ -53,8 +53,16 @@ int jvmVersion; BOOL destroyNotifySent; + + NSTrackingRectTag ptrTrackingTag; + NSRect ptrRect; + NSCursor * myCursor; } +- (id)initWithFrame:(NSRect)frameRect; + +- (NSCursor *) cursor; + /* Set during event dispatching cycle */ - (void) setJVMHandle: (JavaVM*) vm; - (JavaVM*) getJVMHandle; @@ -70,6 +78,7 @@ - (BOOL) getDestroyNotifySent; - (void) rightMouseDown: (NSEvent*) theEvent; +- (void) resetCursorRects; @end @@ -79,14 +88,29 @@ @interface NewtMacWindow : NSWindow #endif { + BOOL mouseConfined; + BOOL mouseVisible; + BOOL mouseInside; + BOOL cursorIsHidden; + NSPoint lastInsideMousePosition; @public int cachedInsets[4]; // l, r, t, b } + (BOOL) initNatives: (JNIEnv*) env forClass: (jobject) clazz; +- (NSPoint) newtScreenWinPos2OSXScreenPos: (NSPoint) p; + +- (NSPoint) newtClientWinPos2OSXScreenPos: (NSPoint) p; - (NSPoint) getLocationOnScreen: (NSPoint) p; +- (NSPoint) screenPos2NewtClientWinPos: (NSPoint) p; + +- (void) cursorHide:(BOOL)v; +- (void) setMouseVisible:(BOOL)v; +- (void) setMouseConfined:(BOOL)v; +- (void) setMousePosition:(NSPoint)p; + - (void) updateInsets: (JNIEnv*) env; - (id) initWithContentRect: (NSRect) contentRect diff --git a/src/newt/native/NewtMacWindow.m b/src/newt/native/NewtMacWindow.m index a44914c97..d4e2c2b6d 100644 --- a/src/newt/native/NewtMacWindow.m +++ b/src/newt/native/NewtMacWindow.m @@ -85,6 +85,27 @@ static jmethodID windowDestroyNotifyID = NULL; @implementation NewtView +- (id)initWithFrame:(NSRect)frameRect +{ + javaWindowObject = NULL; + + jvmHandle = NULL; + jvmVersion = 0; + destroyNotifySent = NO; + + ptrTrackingTag = 0; + + /** + NSCursor crs = [NSCursor arrowCursor]; + NSImage crsImg = [crs image]; + NSPoint crsHot = [crs hotSpot]; + myCursor = [[NSCursor alloc] initWithImage: crsImg hotSpot:crsHot]; + */ + myCursor = NULL; + + return [super initWithFrame:frameRect]; +} + - (void) setJVMHandle: (JavaVM*) vm { jvmHandle = vm; @@ -132,6 +153,24 @@ static jmethodID windowDestroyNotifyID = NULL; } } +- (void) resetCursorRects +{ + [super resetCursorRects]; + + if(0 != ptrTrackingTag) { + // [self removeCursorRect: ptrRect cursor: myCursor]; + [self removeTrackingRect: ptrTrackingTag]; + } + ptrRect = [self bounds]; + // [self addCursorRect: ptrRect cursor: myCursor]; + ptrTrackingTag = [self addTrackingRect: ptrRect owner: self userData: nil assumeInside: NO]; +} + +- (NSCursor *) cursor +{ + return myCursor; +} + - (void)viewWillDraw { DBG_PRINT("*************** viewWillDraw: 0x%p\n", javaWindowObject); @@ -197,29 +236,6 @@ static jmethodID windowDestroyNotifyID = NULL; return NO; } -- (NSPoint) getLocationOnScreen: (NSPoint) p -{ - /** - * return location in 0/0 top-left space, - * OSX is 0/0 bottom-left space naturally - */ - 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 for 0/0 top-left - 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; - return oS; -} - - (void) updateInsets: (JNIEnv*) env { NSView* nsview = [self contentView]; @@ -266,9 +282,86 @@ static jmethodID windowDestroyNotifyID = NULL; cachedInsets[1] = 0; // r cachedInsets[2] = 0; // t cachedInsets[3] = 0; // b + mouseConfined = NO; + mouseVisible = YES; + mouseInside = NO; + cursorIsHidden = NO; return res; } +/** + * p abs screen position w/ top-left origin + * returns: abs screen position w/ bottom-left origin + */ +- (NSPoint) newtScreenWinPos2OSXScreenPos: (NSPoint) p +{ + NSView* mView = [self contentView]; + NSRect mViewFrame = [mView frame]; + int totalHeight = mViewFrame.size.height + cachedInsets[2] + cachedInsets[3]; // height + insets[top+bottom] + + NSScreen* screen = [self screen]; + NSRect screenFrame = [screen frame]; + + return NSMakePoint(screenFrame.origin.x + p.x + cachedInsets[0], + screenFrame.origin.y + screenFrame.size.height - p.y - totalHeight); +} + +/** + * p rel client window position w/ top-left origin + * returns: abs screen position w/ bottom-left origin + */ +- (NSPoint) newtClientWinPos2OSXScreenPos: (NSPoint) p +{ + NSRect winFrame = [self frame]; + + NSView* mView = [self contentView]; + NSRect mViewFrame = [mView frame]; + + return NSMakePoint(winFrame.origin.x + p.x, + winFrame.origin.y + ( mViewFrame.size.height - p.y ) ); // y-flip in view +} + +/** + * y-flips input / output + * p rel client window position w/ top-left origin + * returns: location in 0/0 top-left space. + */ +- (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; + return oS; +} + +- (NSPoint) screenPos2NewtClientWinPos: (NSPoint) p +{ + NSView* view = [self contentView]; + NSRect viewFrame = [view frame]; + + NSRect r; + r.origin.x = p.x; + r.origin.y = p.y; + r.size.width = 0; + r.size.height = 0; + // NSRect rS = [win convertRectFromScreen: r]; // 10.7 + NSPoint oS = [self convertScreenToBase: r.origin]; + oS.y = viewFrame.size.height - oS.y; // y-flip + + return oS; +} + - (BOOL) canBecomeKeyWindow { // Even if the window is borderless, we still want it to be able @@ -363,17 +456,7 @@ static jint mods2JavaMods(NSUInteger mods) NSLog(@"sendMouseEvent: null JNIEnv"); return; } - jint javaMods = mods2JavaMods([event modifierFlags]); - NSRect frameRect = [self frame]; - NSRect contentRect = [self contentRectForFrameRect: frameRect]; - // NSPoint location = [event locationInWindow]; - // The following computation improves the behavior of mouse drag - // events when they also affect the location of the window, but it - // still isn't perfect - NSPoint curLocation = [NSEvent mouseLocation]; - NSPoint location = NSMakePoint(curLocation.x - frameRect.origin.x, - curLocation.y - frameRect.origin.y); // convert to 1-based button number (or use zero if no button is involved) // TODO: detect mouse button when mouse wheel scrolled @@ -411,10 +494,12 @@ static jint mods2JavaMods(NSUInteger mods) if (evType == EVENT_MOUSE_PRESSED) { (*env)->CallVoidMethod(env, javaWindowObject, enqueueRequestFocusID, JNI_FALSE); } + + NSPoint location = [self screenPos2NewtClientWinPos: [NSEvent mouseLocation]]; + (*env)->CallVoidMethod(env, javaWindowObject, enqueueMouseEventID, JNI_FALSE, evType, javaMods, - (jint) location.x, - (jint) (contentRect.size.height - location.y), + (jint) location.x, (jint) location.y, javaButtonNum, scrollDeltaY); if (shallBeDetached) { @@ -422,18 +507,73 @@ static jint mods2JavaMods(NSUInteger mods) } } +- (void) setMouseVisible:(BOOL)v +{ + mouseVisible = v; + DBG_PRINT( "setMouseVisible: confined %d, visible %d\n", mouseConfined, mouseVisible); + if(YES == mouseInside) { + [self cursorHide: !mouseVisible]; + } +} + +- (void) cursorHide:(BOOL)v +{ + if(v) { + if(!cursorIsHidden) { + [NSCursor hide]; + cursorIsHidden = YES; + } + } else { + if(cursorIsHidden) { + [NSCursor unhide]; + cursorIsHidden = NO; + } + } +} + +- (void) setMouseConfined:(BOOL)v +{ + mouseConfined = v; + DBG_PRINT( "setMouseConfined: confined %d, visible %d\n", mouseConfined, mouseVisible); +} + +- (void) setMousePosition:(NSPoint)p +{ + NSScreen* screen = [self screen]; + NSRect screenRect = [screen frame]; + + CGPoint pt = { p.x, screenRect.size.height - p.y }; // y-flip (CG is top-left origin) + CGEventRef ev = CGEventCreateMouseEvent (NULL, kCGEventMouseMoved, pt, kCGMouseButtonLeft); + CGEventPost (kCGHIDEventTap, ev); + NSPoint l0 = [NSEvent mouseLocation]; + [self screenPos2NewtClientWinPos: l0]; +} + - (void) mouseEntered: (NSEvent*) theEvent { - [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_ENTERED]; + DBG_PRINT( "mouseEntered: confined %d, visible %d\n", mouseConfined, mouseVisible); + mouseInside = YES; + [self setMouseVisible: mouseVisible]; + if(NO == mouseConfined) { + [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_ENTERED]; + } } - (void) mouseExited: (NSEvent*) theEvent { - [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_EXITED]; + DBG_PRINT( "mouseExited: confined %d, visible %d\n", mouseConfined, mouseVisible); + if(NO == mouseConfined) { + mouseInside = NO; + [self cursorHide: NO]; + [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_EXITED]; + } else { + [self setMousePosition: lastInsideMousePosition]; + } } - (void) mouseMoved: (NSEvent*) theEvent { + lastInsideMousePosition = [NSEvent mouseLocation]; [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_MOVED]; } @@ -449,6 +589,7 @@ static jint mods2JavaMods(NSUInteger mods) - (void) mouseDragged: (NSEvent*) theEvent { + lastInsideMousePosition = [NSEvent mouseLocation]; // Note use of MOUSE_MOVED event type because mouse dragged events are synthesized by Java [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_MOVED]; } @@ -465,6 +606,7 @@ static jint mods2JavaMods(NSUInteger mods) - (void) rightMouseDragged: (NSEvent*) theEvent { + lastInsideMousePosition = [NSEvent mouseLocation]; // Note use of MOUSE_MOVED event type because mouse dragged events are synthesized by Java [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_MOVED]; } @@ -481,6 +623,7 @@ static jint mods2JavaMods(NSUInteger mods) - (void) otherMouseDragged: (NSEvent*) theEvent { + lastInsideMousePosition = [NSEvent mouseLocation]; // Note use of MOUSE_MOVED event type because mouse dragged events are synthesized by Java [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_MOVED]; } @@ -558,6 +701,8 @@ static jint mods2JavaMods(NSUInteger mods) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + [self cursorHide: NO]; + NSView* nsview = [self contentView]; if( ! [nsview isMemberOfClass:[NewtView class]] ) { return; |