Question

Why can't I get the cursor to stay put for the duration of my mouse drag? As soon as I start dragging, it reverts to "Arrow" (even though I set it as open hand in the app delegate after launch).

- (void)mouseDown:(NSEvent *)event
{
   [[NSCursor closedHandCursor] push];
}

- (void)mouseUp:(NSEvent *)event
{
   [NSCursor pop];
}
Was it helpful?

Solution

Try using the addCursorRect:cursor: to set the cursor for you view.

Override the resetCursorRects for your view:

- (void)resetCursorRects
{
    [super resetCursorRects];
    if(drag) {
        [self addCursorRect:self.bounds cursor:[NSCursor closedHandCursor]];
    }
}

You need to call invalidateCursorRectsForView: to force update your cursor rects:

[self.window invalidateCursorRectsForView:self];

But if you want to have different cursor outside of you view you can call [[NSCursor closedHandCursor] set] in your mouseDragged: method.

OTHER TIPS

If you don't want other views to change your cursor while dragging you can do in -mouseDown:

[[self window] disableCursorRects];

and in -mouseUp:

[[self window] enableCursorRects];
[[self window] resetCursorRects];

I had the same problem which was caused by the fact that during the drag I was modifying a subview's frame, which seems to reset the cursor. When adding the tracking area with the .cursorUpdate option and resetting the cursor inside cursorUpdate(with:), it seems to work correctly.

class MyViewController: NSViewController {

    var cursor: NSCursor?

    override func viewDidLoad() {
        super.viewDidLoad()
        view.addTrackingArea(NSTrackingArea(rect: .zero, options: [.activeInKeyWindow, .inVisibleRect, .cursorUpdate], owner: self))
    }

    override func mouseDown(with event: NSEvent) {
        cursor = NSCursor.closedHand
    }

    override func cursorUpdate(with event: NSEvent) {
        cursor?.set()
    }
        
    override func mouseUp(with event: NSEvent) {
        cursor = nil
    }
    
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top