aboutsummaryrefslogtreecommitdiffstats
path: root/src/newt/native/NewtMacWindow.m
diff options
context:
space:
mode:
Diffstat (limited to 'src/newt/native/NewtMacWindow.m')
-rw-r--r--src/newt/native/NewtMacWindow.m219
1 files changed, 182 insertions, 37 deletions
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;