diff options
author | Sven Gothel <[email protected]> | 2011-10-16 03:47:31 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2011-10-16 03:47:31 +0200 |
commit | aeffc47f9fea7ae94c7531e6ee4cb53bc88e64f1 (patch) | |
tree | 4f31c2924b4ee7f375b7b15e181d849fcc26b0bf /src/newt/native | |
parent | ec2fc482bf97459c57417a8f856345a5836680f3 (diff) |
NEWT/OSX: Add mouse enter/exit and pointer features (visible, confined, warp) - cleanup pos/coord translations
Diffstat (limited to 'src/newt/native')
-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 |
3 files changed, 249 insertions, 70 deletions
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; |