Get Current Keyboard Cursor Location - objective-c

Is there anyway to get coordinates for the current position of the keyboard cursor (caret) globally like you can for the mouse cursor position with mouseLocation?

No, there is no way to do it globally.
If you want to do it in your own app, like in an NSTextView, you'd do it like this:
NSRange range = [textView selectedRange];
NSRange newRange = [[textView layoutManager] glyphRangeForCharacterRange:range actualCharacterRange:NULL];
NSRect rect = [[textView layoutManager] boundingRectForGlyphRange:newRange inTextContainer:[textView textContainer]];
rect would be the rect of the selected text, or in the case where there is just an insertion point but no selection, rect.origin is the view-relative location of the insertion point.

The closest you can get would be to use OS X's Accessibility Protocol. This is intended to help disabled users operate the computer, but many applications don't support it, or do not support it very well.
The procedure would be something like:
appRef = AXUIElementCreateApplication(appPID);
focusElemRef = AXUIElementCopyAttributeValue(appRef,kAXFocusedUIElementAttribute, &theValue)
AXUIElementCopyAttributeValue(focusElemRef, kAXSelectedTextRangeAttribute, &selRangeValue);
AXUIElementCopyParameterizedAttributeValue(focusElemRef, kAXBoundsForRangeParameterizedAttribute, adjSelRangeValue, &boundsValue);
Due to the spotty support for the protocol, with many applications you won't get beyond the FocusedUIElementAttribute step, but this does work with some applications.

You can do this easily in macOS 10.0 and up.
For an NSTextView, override the drawInsertionPointInRect:color:turnedOn: method. To translate the caret position relative to the window, use the convertPoint:toView: method. Finally, you can store the translated position in an instance variable.
#interface MyTextView : NSTextView
#end
#implementation MyTextView
{
NSPoint _caretPositionInWindow;
}
- (void)drawInsertionPointInRect:(CGRect)rect color:(NSColor *)color turnedOn:(BOOL)flag
{
[super drawInsertionPointInRect:rect color:color turnedOn:flag];
_caretPositionInWindow = [self convertPoint:rect.origin toView:nil];
}
#end

Related

How to make a smooth, rounded, volume-like OS X window with NSVisualEffectView?

I'm currently trying to make a window that looks like the Volume OS X window:
To make this, I have my own NSWindow (using a custom subclass), which is transparent/titlebar-less/shadow-less, that has a NSVisualEffectView inside its contentView. Here's the code of my subclass to make the content view round:
- (void)setContentView:(NSView *)aView {
aView.wantsLayer = YES;
aView.layer.frame = aView.frame;
aView.layer.cornerRadius = 14.0;
aView.layer.masksToBounds = YES;
[super setContentView:aView];
}
And here's the outcome (as you can see, the corners are grainy, OS X's are way smoother):
Any ideas on how to make the corners smoother? Thanks
Update for OS X El Capitan
The hack I described in my original answer below is not needed on OS X El Capitan anymore. The NSVisualEffectView’s maskImage should work correctly there, if the NSWindow’s contentView is set to be the NSVisualEffectView (it’s not enough if it is a subview of the contentView).
Here’s a sample project: https://github.com/marcomasser/OverlayTest
Original Answer – Only Relevant for OS X Yosemite
I found a way to do this by overriding a private NSWindow method: - (NSImage *)_cornerMask. Simply return an image created by drawing an NSBezierPath with a rounded rect in it to get a look similar to OS X’s volume window.
In my testing I found that you need to use a mask image for the NSVisualEffectView and the NSWindow. In your code, you’re using the view’s layer’s cornerRadius property to get the rounded corners, but you can achieve the same by using a mask image. In my code, I generate an NSImage that is used by both the NSVisualEffectView and the NSWindow:
func maskImage(#cornerRadius: CGFloat) -> NSImage {
let edgeLength = 2.0 * cornerRadius + 1.0
let maskImage = NSImage(size: NSSize(width: edgeLength, height: edgeLength), flipped: false) { rect in
let bezierPath = NSBezierPath(roundedRect: rect, xRadius: cornerRadius, yRadius: cornerRadius)
NSColor.blackColor().set()
bezierPath.fill()
return true
}
maskImage.capInsets = NSEdgeInsets(top: cornerRadius, left: cornerRadius, bottom: cornerRadius, right: cornerRadius)
maskImage.resizingMode = .Stretch
return maskImage
}
I then created an NSWindow subclass that has a setter for the mask image:
class MaskedWindow : NSWindow {
/// Just in case Apple decides to make `_cornerMask` public and remove the underscore prefix,
/// we name the property `cornerMask`.
#objc dynamic var cornerMask: NSImage?
/// This private method is called by AppKit and should return a mask image that is used to
/// specify which parts of the window are transparent. This works much better than letting
/// the window figure it out by itself using the content view's shape because the latter
/// method makes rounded corners appear jagged while using `_cornerMask` respects any
/// anti-aliasing in the mask image.
#objc dynamic func _cornerMask() -> NSImage? {
return cornerMask
}
}
Then, in my NSWindowController subclass I set up the mask image for the view and the window:
class OverlayWindowController : NSWindowController {
#IBOutlet weak var visualEffectView: NSVisualEffectView!
override func windowDidLoad() {
super.windowDidLoad()
let maskImage = maskImage(cornerRadius: 18.0)
visualEffectView.maskImage = maskImage
if let window = window as? MaskedWindow {
window.cornerMask = maskImage
}
}
}
I don’t know what Apple will do if you submit an app with that code to the App Store. You’re not actually calling any private API, you’re just overriding a method that happens to have the same name as a private method in AppKit. How should you know that there’s a naming conflict? 😉
Besides, this fails gracefully without you having to do anything. If Apple changes the way this works internally and the method just won’t get called, your window does not get the nice rounded corners, but everything still works and looks almost the same.
If you’re curious about how I found out about this method:
I knew that the OS X volume indication did what I want to do and I hoped that changing the volume like a madman resulted in noticeable CPU usage by the process that puts that volume indication on screen. I therefore opened Activity Monitor, sorted by CPU usage, activated the filter to only show “My Processes” and hammered my volume up/down keys.
It became clear that coreaudiod and something called BezelUIServer in /System/Library/LoginPlugins/BezelServices.loginPlugin/Contents/Resources/BezelUI/BezelUIServer did something. From looking at the bundle resources for the latter, it was evident that it is responsible for drawing the volume indication. (Note: that process only runs for a short time after it displays something.)
I then used Xcode to attach to that process as soon as it launched (Debug > Attach to Process > By Process Identifier (PID) or Name…, then enter “BezelUIServer”) and changed the volume again. After the debugger was attached, the view debugger let me take a look at the view hierarchy and see that the window was an instance of a NSWindow subclass called BSUIRoundWindow.
Using class-dump on the binary showed that this class is a direct descendant of NSWindow and only implements three methods, whereas one is - (id)_cornerMask, which sounded promising.
Back in Xcode, I used the Object Inspector (right hand side, third tab) to get the address for the window object. Using that pointer I checked what this _cornerMask actually returns by printing its description in lldb:
(lldb) po [0x108500110 _cornerMask]
<NSImage 0x608000070300 Size={37, 37} Reps=(
"NSCustomImageRep 0x608000082d50 Size={37, 37} ColorSpace=NSCalibratedRGBColorSpace BPS=0 Pixels=0x0 Alpha=NO"
)>
This shows that the return value actually is an NSImage, which is the information I needed to implement _cornerMask.
If you want to take a look at that image, you can write it to a file:
(lldb) e (BOOL)[[[0x108500110 _cornerMask] TIFFRepresentation] writeToFile:(id)[#"~/Desktop/maskImage.tiff" stringByExpandingTildeInPath] atomically:YES]
To dig a bit deeper, you can use Hopper Disassembler to disassemble BezelUIServer and AppKit and generate pseudo code to see how the _cornerMask is implemented and used to get a clearer picture of how the internals work. Unfortunately, everything in regard to this mechanism is private API.
I remember doing this sort of thing long before CALayer was around. You use NSBezierPath to make the path.
I don't believe you actually need to subclass NSWindow. The important bit about the window is to initialize the window with NSBorderlessWindowMask and apply the following settings:
[window setAlphaValue:0.5]; // whatever your desired opacity is
[window setOpaque:NO];
[window setHasShadow:NO];
Then you set the contentView of your window to a custom NSView subclass with the drawRect: method overridden similar to this:
// "erase" the window background
[[NSColor clearColor] set];
NSRectFill(self.frame);
// make a rounded rect and fill it with whatever color you like
NSBezierPath* clipPath = [NSBezierPath bezierPathWithRoundedRect:self.frame xRadius:14.0 yRadius:14.0];
[[NSColor blackColor] set]; // your bg color
[clipPath fill];
result (ignore the slider):
Edit: If this method is for whatever reason undesirable, can you not simply assign a CAShapeLayer as your contentView's layer then either convert the above NSBezierPath to CGPath or just construct as a CGPath and assign the path to the layers path?
The "smooth effect" you are referring to is called "Antialiasing". I did a bit of googling and I think you might be the first person who has tried to round the corners of an NSVisualEffectView. You told the CALayer to have a border radius, which will round the corners, but you didn't set any other options. I would try this:
layer.shouldRasterize = YES;
layer.edgeAntialiasingMask = kCALayerLeftEdge | kCALayerRightEdge | kCALayerBottomEdge | kCALayerTopEdge;
Anti-alias diagonal edges of CALayer
https://developer.apple.com/library/mac/documentation/GraphicsImaging/Reference/CALayer_class/index.html#//apple_ref/occ/instp/CALayer/edgeAntialiasingMask
Despite the limitations of NSVisualEffectView not antialiasing edges, here's a kludgey workaround for now that should work for this application of a floating title-less unresizeable window with no shadow - have a child window underneath that draws out just the edges.
I was able to get mine to look like this:
by doing the following:
In a controller holding everything:
- (void) create {
NSRect windowRect = NSMakeRect(100.0, 100.0, 200.0, 200.0);
NSRect behindWindowRect = NSMakeRect(99.0, 99.0, 202.0, 202.0);
NSRect behindViewRect = NSMakeRect(0.0, 0.0, 202.0, 202.0);
NSRect viewRect = NSMakeRect(0.0, 0.0, 200.0, 200.0);
window = [FloatingWindow createWindow:windowRect];
behindAntialiasWindow = [FloatingWindow createWindow:behindWindowRect];
roundedHollowView = [[RoundedHollowView alloc] initWithFrame:behindViewRect];
[behindAntialiasWindow setContentView:roundedHollowView];
[window addChildWindow:behindAntialiasWindow ordered:NSWindowBelow];
backingView = [[NSView alloc] initWithFrame:viewRect];
contentView = [[NSVisualEffectView alloc] initWithFrame:viewRect];
[contentView setWantsLayer:NO];
[contentView setState:NSVisualEffectStateActive];
[contentView setAppearance:
[NSAppearance appearanceNamed:NSAppearanceNameVibrantLight]];
[contentView setMaskImage:[AppDelegate maskImageWithBounds:contentView.bounds]];
[backingView addSubview:contentView];
[window setContentView:backingView];
[window setLevel:NSFloatingWindowLevel];
[window orderFront:self];
}
+ (NSImage *) maskImageWithBounds: (NSRect) bounds
{
return [NSImage imageWithSize:bounds.size flipped:YES drawingHandler:^BOOL(NSRect dstRect) {
NSBezierPath *path = [NSBezierPath bezierPathWithRoundedRect:bounds xRadius:20.0 yRadius:20.0];
[path setLineJoinStyle:NSRoundLineJoinStyle];
[path fill];
return YES;
}];
}
RoundedHollowView's drawrect looks like this:
- (void)drawRect:(NSRect)dirtyRect {
[super drawRect:dirtyRect];
// "erase" the window background
[[NSColor clearColor] set];
NSRectFill(self.frame);
[[NSColor colorWithDeviceWhite:1.0 alpha:0.7] set];
NSBezierPath *path = [NSBezierPath bezierPathWithRoundedRect:self.bounds xRadius:20.0 yRadius:20.0];
path.lineWidth = 2.0;
[path stroke];
}
Again, this is a hack and you may need to play with the lineWidth / alpha values depending on the base color you use - in my example if you look really closely or under lighter backgrounds you'll make out the border a bit, but for my own use it feels less jarring than not having any antialiasing.
Keep in mind that the blending mode won't be the same as the native osx yosemite pop-ups like the volume control - those appear to use a different undocumented behindwindow appearance that shows more of a color burn effect.
All kudos to Marco Masser for the most neat solution, there're two useful points:
For smooth rounded corners to work, the NSVisualEffectView must be the root view within view controller.
When using the dark material there are still funny light cropped edges that get very apparent on the dark background. Make your window background transparent to avoid this, window.backgroundColor = NSColor.clearColor().
None of these solutions worked for me on Mojave. However after an hour of research, I found this amazing repo which showcases different window designs. One of the solution looks like the OP's desired look. I tried it and it worked with nicely anti-aliased rounded corners and no titlebar artifact remaining. Here is the working code:
let visualEffect = NSVisualEffectView()
visualEffect.translatesAutoresizingMaskIntoConstraints = false
visualEffect.material = .dark
visualEffect.state = .active
visualEffect.wantsLayer = true
visualEffect.layer?.cornerRadius = 16.0
window?.titleVisibility = .hidden
window?.styleMask.remove(.titled)
window?.backgroundColor = .clear
window?.isMovableByWindowBackground = true
window?.contentView?.addSubview(visualEffect)
Note at the end the contentView.addSubview(visualEffect) instead of contentView = visualEffect. This is one of the key to make it work.

How to differentiate the mouseDown event from mouseDragged in a Transparent NSWindow

I have a Transparent NSWindow with an simple icon in it that can be dragged around the screen.
My code is:
.h:
#interface CustomView : NSWindow{
}
#property (assign) NSPoint initialLocation;
.m
#synthesize initialLocation;
- (id) initWithContentRect: (NSRect) contentRect
styleMask: (NSUInteger) aStyle
backing: (NSBackingStoreType) bufferingType
defer: (BOOL) flag{
if (![super initWithContentRect: contentRect
styleMask: NSBorderlessWindowMask
backing: bufferingType
defer: flag]) return nil;
[self setBackgroundColor: [NSColor clearColor]];
[self setOpaque:NO];
[NSApp activateIgnoringOtherApps:YES];
return self;
}
- (void)mouseDragged:(NSEvent *)theEvent {
NSRect screenVisibleFrame = [[NSScreen mainScreen] visibleFrame];
NSRect windowFrame = [self frame];
NSPoint newOrigin = windowFrame.origin;
// Get the mouse location in window coordinates.
NSPoint currentLocation = [theEvent locationInWindow];
// Update the origin with the difference between the new mouse location and the old mouse location.
newOrigin.x += (currentLocation.x - initialLocation.x);
newOrigin.y += (currentLocation.y - initialLocation.y);
// Don't let window get dragged up under the menu bar
if ((newOrigin.y + windowFrame.size.height) > (screenVisibleFrame.origin.y + screenVisibleFrame.size.height)) {
newOrigin.y = screenVisibleFrame.origin.y + (screenVisibleFrame.size.height - windowFrame.size.height);
}
// Move the window to the new location
[self setFrameOrigin:newOrigin];
}
- (void)mouseDown:(NSEvent *)theEvent {
// Get the mouse location in window coordinates.
self.initialLocation = [theEvent locationInWindow];
}
I want to display a NSPopover when the users clicks the image of the transparent window. But, as you can see in the code, the mouseDown event is used to get the mouse location (the code above was taken from an example).
What can i do to know when the user clicks the icon just to drag it around or simply clicked it to display the NSPopover?
Thank you
This is the classic situation of receiving the defining event after you need it in order to begin the action. Specifically, you can't know if the mouseDown is the beginning of a drag until after the drag starts. However, you want to act upon that mouseDown if a drag doesn't start.
In iOS (I realize that's not directly relevant to the code here, but it is instructional), there's an entire API built around letting iOS attempt to make these kinds of decisions for you. The entire Gesture system is based on the idea that the user starts to do something that might be one of many different actions, and thus needs to be resolved over time, possibly resulting in cancelled actions during the tracking period.
On OS X, we don't have many systems to help out with this, so if you have something that needs to handle a click and a drag differentially, you will need to defer your next action until a guard time has passed, and if that passes, you can perform the original action. In this case, you will likely want to do the following:
In the mouseDown, begin an NSTimer set for an appropriate guard time (not so long that people will accidentally move the pointer, and not so short that you'll trigger before the user drags) in order to call you back later to trigger the popover.
In the mouseDragged, use a guard area to make sure that if the user just twitches a little, it doesn't count as a drag. This can be irritating, as it sometimes results in needing to drag something farther than it seems necessary in order to begin a drag, so you'll want to either find a magic constant somewhere, or do some experimentation. When the guard area is exceeded, then begin your legitimate drag operation by canceling the NSTimer with [timer invalidate] and do your drag.
In the callback for the timer, display your popover. If the user dragged, the NSTimer will have been invalidated, causing it not to fire, and so the popover won't be displayed.

Dragging the view

I have an NSView which I am adding as a sub-view of another NSView. I want to be able to drag the first NSView around the parent view. I have some code that is partially working but there's an issue with the NSView moving in the opposite direction on the Y axis from my mouse drag. (i.e. I drag down, it goes up and the inverse of that).
Here's my code:
// -------------------- MOUSE EVENTS ------------------- \\
- (BOOL) acceptsFirstMouse:(NSEvent *)e {
return YES;
}
- (void)mouseDown:(NSEvent *) e {
//get the mouse point
lastDragLocation = [e locationInWindow];
}
- (void)mouseDragged:(NSEvent *)theEvent {
NSPoint newDragLocation = [theEvent locationInWindow];
NSPoint thisOrigin = [self frame].origin;
thisOrigin.x += (-lastDragLocation.x + newDragLocation.x);
thisOrigin.y += (-lastDragLocation.y + newDragLocation.y);
[self setFrameOrigin:thisOrigin];
lastDragLocation = newDragLocation;
}
The view is flipped, though I changed that back to the default and it didn't seem to make a difference. What am I doing wrong?
The best way to approach this problem is by starting with a solid understanding of coordinate spaces.
First, it is critical to understand that when we talk about the "frame" of a window, it is in the coordinate space of the superview. This means that adjusting the flippedness of the view itself won't actually make a difference, because we haven't been changing anything inside the view itself.
But your intuition that the flippedness is important here is correct.
By default your code, as typed, seems like it would work; perhaps your superview has been flipped (or not flipped), and it is in a different coordinate space than you expect.
Rather than just flipping and unflipping views at random, it is best to convert the points you're dealing with into a known coordinate space.
I've edited your above code to always convert into the superview's coordinate space, because we're working with the frame origin. This will work if your draggable view is placed in a flipped, or non-flipped superview.
// -------------------- MOUSE EVENTS ------------------- \\
- (BOOL) acceptsFirstMouse:(NSEvent *)e {
return YES;
}
- (void)mouseDown:(NSEvent *) e {
// Convert to superview's coordinate space
self.lastDragLocation = [[self superview] convertPoint:[e locationInWindow] fromView:nil];
}
- (void)mouseDragged:(NSEvent *)theEvent {
// We're working only in the superview's coordinate space, so we always convert.
NSPoint newDragLocation = [[self superview] convertPoint:[theEvent locationInWindow] fromView:nil];
NSPoint thisOrigin = [self frame].origin;
thisOrigin.x += (-self.lastDragLocation.x + newDragLocation.x);
thisOrigin.y += (-self.lastDragLocation.y + newDragLocation.y);
[self setFrameOrigin:thisOrigin];
self.lastDragLocation = newDragLocation;
}
Additionally, I'd recommend refactoring your code to simply deal with the original mouse-down location, and the current location of the pointer, rather than deal with the deltas between mouseDragged events. This could lead to unexpected results down the line.
Instead simply store the offset between the origin of dragged view and the mouse pointer (where the mouse pointer is within the view), and set the frame origin to the location of the mouse pointer, minus the offset.
Here is some additional reading:
Cocoa Drawing Guide
Cocoa Event Handling Guide
I think you should calculate according to the position of mouse, cause according to my test,it gets more smooth.Because The way like below only provide the position inside the application's window coordinate system:
[[self superview] convertPoint:[theEvent locationInWindow] fromView:nil];
What I am suggesting is something like this:
lastDrag = [NSEvent mouseLocation];
other codes are just the same.

How to use a custom view correctly?

I have been trying to make a simple drawing program. Recently, I have figured out to draw shapes in a custom view for this purpose. My problem is that I have to draw everything at a single point in time. I don't know if that actually makes sense, but it seems to me that it calls the drawRect method only once, at that "once" is on startup.
Here is my code so far:
Header file.
NSBezierPath *thePath;
NSColor *theColor;
NSTimer *updateTimer;
NSPoint *mousePoint;
int x = 0;
int y = 0;
#interface test : NSView {
IBOutlet NSView *myView;
}
#property (readwrite) NSPoint mousePoint;
#end
Then, implementation in the .m file.
#implementation test
#synthesize mousePoint;
- (void) mouseDown:(NSEvent*)someEvent {
CGEventRef ourEvent = CGEventCreate(NULL);
mousePoint = CGEventGetLocation(ourEvent);
NSLog(#"Location: x= %f, y = %f", (float)mousePoint.x, (float)mousePoint.y);
thePath = [NSBezierPath bezierPathWithRect:NSMakeRect(mousePoint.x, mousePoint.y, 10, 10)];
theColor = [NSColor blackColor];
}
- (void) mouseDragged:(NSEvent *)someEvent {
mousePoint = [someEvent locationInWindow];
NSLog(#"Location: x= %f, y = %f", (float)mousePoint.x, (float)mousePoint.y);
x = mousePoint.x;
y = mousePoint.y;
[myView setNeedsDisplay:YES];
}
- (void) drawRect:(NSRect)rect; {
NSLog(#"oisudfghio");
thePath = [NSBezierPath bezierPathWithRect:NSMakeRect(x, y, 10, 10)];
theColor = [NSColor blackColor];
[theColor set];
[thePath fill];
}
#end
On startup, it draws a rectangle in the bottom left corner, like it should. The problem is, the drawRect method is only called on startup. It just won't fire no matter what I do.
EDIT: I have just updated the code. I hope it helps.
SECOND EDIT: I have really simplified the code. I hope this helps a bit more.
Short Answer:
When your view's state is changed such that it would draw differently, you need to invoke -[NSView setNeedsDisplay:]. That will cause your view's drawRect: method to be called in the near future. You should never call drawRect: yourself. That's a callback that's invoked on your behalf.
When events occur in your application that cause you to want to change your drawing, capture state about what happened into instance variables, invoke setNeedsDisplay: and then later when drawRect: is called do the new drawing.
Long Answer:
In Cocoa, window drawing is done with an pull/invalidation model. That means the window has an idea of whether or not it needs to draw, and when it thinks it needs to draw it draws once per event loop.
If you're not familiar with event loops you can read about them on Wikipedia
At the top level of the application you can imagine that Cocoa is doing this:
while (1) {
NSArray *events = [self waitForEvents];
[self doEvents:events];
}
Where events are things like the mouse moving, the keyboard being pressed, and timers going off.
NSView has a method -[NSView setNeedsDisplay:]. It takes a boolean parameter. When that method is invoked the window invalidates the drawing region for that view, and schedules an event for the future to do redrawing - but only if there isn't a preexisting redrawing event scheduled.
When the runloop spins next time, the views that were marked with setNeedsDisplay: are re-drawn. This means you can call setNeedsDisplay: several times in a row and drawing will be batched to one call of drawRect: in the future. This is important for performance reasons and means you can do things like change the frame of a view several times in one method but it will only be drawn once at the final location.
The code in your example has a couple of problems. The first is that all drawing code must be in the drawRect: method or a method called from drawRect:, so the drawing code you've placed in your other methods will have no effect at runtime. The second problem is that your code should never directly call drawRect:; instead, the framework will call it automatically (if necessary) once per event cycle.
Instead of hardcoding all the values, consider using instance variables for things you want to be able to change at runtime, for example, the drawing color and rectangle. Then in your mouseDragged: method, send the view (myView in your example) a setNeedsDisplay: message. If you pass YES as the argument, the drawRect: method will be called for you by the framework.

How to find the location of the mouse in objective-c

I am making an image editor (just a simple editor for a program I am making), and I need to find the position of the mouse. Is it possible to do this in Objective-C? If so, how?
EDIT: I just thought I should mention that I have done some research on this and I haven't found anything that works. The code I have in my header file is as follows:
#import <Cocoa/Cocoa.h>
#interface test : NSWindow <NSWindowDelegate> {
}
#end
I can handle any outlets and actions that are needed; I just need to know how to find the position of the mouse.
If you are catching it through an event, such as mouseDown, it will look like this:
- (void)mouseDown:(NSEvent *)theEvent {
NSPoint mouseDownPos = [theEvent locationInWindow];
}
Otherwise, use:
[NSEvent mouseLocation];
EDIT: (Sorry, I wrote NSPoint *, which is wrong, since it's a struct)
Inside a mouse event handler (mouseDown:, mouseUp:, mouseMoved:, etc.), you can ask the event for its locationInWindow. If you need the mouse location at some arbitrary time (generally you won't want to do that, since it's rare for a program to have a one-off need to discover the mouse location), you can do [NSEvent mouseLocation] and it will return the mouse's location at the time in screen coordinates.
If you want the coordinates from the origin of the view itself, use:
NSPoint locationInView = [self convertPoint:[theEvent locationInWindow] fromView:nil];
You can use this NSPoint directly to draw in the NSView coordinates; otherwise with
[theEvent locationInWindow]
you will have the coordinates of the mouse in the window, which is probably not what you want.