6

Okay, here is the problem:
I have a NSTextView and I add my custom NSButton using:

[_textView addSubview:button]; 

Then, inside my NSButton subclass, I have (along with the NSTrackingArea stuff):

- (void)mouseEntered:(NSEvent *)event{ [[NSCursor arrowCursor] set]; } - (void)mouseExited:(NSEvent *)theEvent{ [[NSCursor arrowCursor] set]; } - (void)mouseDown:(NSEvent *)theEvent{ [[NSCursor arrowCursor] set]; } - (void)mouseUp:(NSEvent *)theEvent{ [[NSCursor arrowCursor] set]; } 

But when I hover it, the cursor remains the same IBeamCursor (because it's a NSTextView). Only when I press the button, the cursor gets updated. And then, when I move the mouse, still inside the button, the cursor goes back to the IBeamCursor.

Any ideas on how to do this? Thank you!

2
  • Have you tried implementing cursorUpdate:, as specified in "Managing Cursor-Update Events"? Commented Apr 29, 2013 at 20:32
  • yes, but the outcome is the same Commented Apr 29, 2013 at 21:14

2 Answers 2

9

Adding a tracking area that only tracks enter/exit events seems to be not enough for NSTextView subviews. Somehow the textview always wins and sets it's IBeamCursor.

You can try to always enable tracking for mouse move events (NSTrackingMouseMoved) when adding the tracking area in your NSButton subclass:

#import "SSWHoverButton.h" @interface SSWHoverButton() { NSTrackingArea* trackingArea; } @end @implementation SSWHoverButton - (void)mouseMoved:(NSEvent*)theEvent { [[NSCursor arrowCursor] set]; } - (void)updateTrackingAreas { if(trackingArea != nil) { [self removeTrackingArea:trackingArea]; } NSTrackingAreaOptions opts = (NSTrackingMouseMoved|NSTrackingActiveAlways); trackingArea = [[NSTrackingArea alloc] initWithRect:[self bounds] options:opts owner:self userInfo:nil]; [self addTrackingArea:trackingArea]; } - (void)dealloc { [self removeTrackingArea:trackingArea]; } @end 
Sign up to request clarification or add additional context in comments.

4 Comments

thank you so much for your answer, but unfortunately it's not working :/
Hi Pedro, I just tried it in a sample Xcode project. Works like a charm here (10.8). Did you use exactly the subclass I posted above? If so, did you instantiate it instead of your own?
Ooops, pardon me! It's working now, and tbh, I haven't changed anything :P Thank you very much!
Thank you for the answer. Apparently solution mentioned here stackoverflow.com/questions/2925580/… does not work
5

Swift 5 variant:

import Cocoa class InsideTextButton: NSButton { var trackingArea: NSTrackingArea? override func mouseMoved(with event: NSEvent) { NSCursor.arrow.set() } override func updateTrackingAreas() { if let area = trackingArea { removeTrackingArea(area) } trackingArea = NSTrackingArea(rect: self.bounds, options: [.mouseMoved, .activeAlways], owner: self, userInfo: nil) if let area = trackingArea { addTrackingArea(area) } } deinit { if let area = trackingArea { removeTrackingArea(area) } } } 

1 Comment

Works perfectly.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.