Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flipped NSView mouse coordinates

Tags:

macos

cocoa

I have a subclass of NSView that re-implements a number of the mouse event functions. For instance in mouseDown to get the point from the NSEvent I use:

NSEvent *theEvent; // <- argument to function

NSPoint p = [theEvent locationInWindow];
p = [self convertPoint:p fromView:nil];

However the coordinates seem to be flipped, (0, 0) is in the bottom left of the window?

EDIT: I have already overridden the isFlipped method to return TRUE, but it has only affected drawing. Sorry, can't believe I forgot to put that straight away.

like image 606
cdyer Avatar asked Sep 29 '11 14:09

cdyer


2 Answers

What do you mean by flipped? Mac uses a LLO (lower-left-origin) coordinate system for everything.

EDIT I can't reproduce this with a simple project. I created a single NSView implemented like this:

@implementation FlipView
- (BOOL)isFlipped {
  return YES;
}

- (void)mouseDown:(NSEvent *)theEvent {
  NSPoint p = [theEvent locationInWindow];
  p = [self convertPoint:p fromView:nil];
  NSLog(@"%@", NSStringFromPoint(p));
}
@end

I received the coordinates I would expect. Removing the isFlipped switched the orientation as expected. Do you have a simple project that demonstrates your problmem?

like image 53
Rob Napier Avatar answered Sep 28 '22 19:09

Rob Napier


I found this so obnoxious - until one day I just sat down and refused to get up until I had something that worked perfectly . Here it is.. called via...

-(void) mouseDown:(NSEvent *)click{
  NSPoint mD = [NSScreen wtfIsTheMouse:click
                        relativeToView:self];
}

invokes a Category on NSScreen....

@implementation NSScreen (FlippingOut)
+ (NSPoint)wtfIsTheMouse:(NSEvent*)anyEevent 
          relativeToView:(NSView *)view {
   NSScreen *now = [NSScreen currentScreenForMouseLocation];
    return [now flipPoint:[now convertToScreenFromLocalPoint:event.locationInWindow relativeToView:view]];
}
- (NSPoint)flipPoint:(NSPoint)aPoint {
         return (NSPoint) { aPoint.x, 
   self.frame.size.height - aPoint.y  };
}
- (NSPoint)convertToScreenFromLocalPoint:(NSPoint)point 
      relativeToView:(NSView *)view {
    NSPoint winP, scrnP, flipScrnP; 
    if(self) {
       winP = [view convertPoint:point toView:nil];
       scrnP = [[view window] convertBaseToScreen:winP];
       flipScrnP = [self flipPoint:scrnP];
       flipScrnP.y += [self frame].origin.y;
       return flipScrnP;
       }    return NSZeroPoint;
}
@end

Hope this can prevent just one minor freakout.. somewhere, someday. For the children, damnit. I beg of you.. for the children.

like image 24
Alex Gray Avatar answered Sep 28 '22 17:09

Alex Gray