1

In my "InitWithFrame" method of a view I'm setting a tracking area for which I want to capture mouse enter/exit events.
My problems are two fold:

  1. Without NSTrackingInVisibleRect the events won't be called at all.
  2. No matter what "rect" I put it, one that covers the entire view's frame or one that occupies just a small portion of it - the mouse enter/exited events are called for the entire view, regardless of where the mouse cursor is on the view.

this is how I initialize the tracking area:

trackingArea = [[NSTrackingArea alloc] initWithRect:rect
  options: (NSTrackingMouseEnteredAndExited | NSTrackingInVisibleRect | NSTrackingActiveAlways )
  owner:self userInfo:nil];
[self addTrackingArea:trackingArea];

Any clues why this happens? I want the mouse enter/exit events to be called only for a small portion (the bottom part) of my view.

Thomas Zoechling
  • 34,177
  • 3
  • 81
  • 112
JasonGenX
  • 4,952
  • 27
  • 106
  • 198

2 Answers2

5

Mike Abdullah's answer explains point 2.

Here is a guess about why you don't receive events at all when not using the NSTrackingInVisibleRect flag:
Probably the variable rect you provide is not within the view's coordinate system. You could use the following code as the designated initializer of your NSView subclass to receive mouseEntered: and mouseExited: events for the whole area of your view:

- (id)initWithFrame:(NSRect)frame 
{
    if ((self = [super initWithFrame:frame])) 
    {
        //by using [self bounds] we get our internal origin (0, 0)
        NSTrackingArea* trackingArea = [[NSTrackingArea alloc] initWithRect:[self bounds] options:(NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways) owner:self userInfo:nil];
        [self addTrackingArea:trackingArea];
        [trackingArea release];
    }
    return self;
}

Apple's documentation says:

When creating a tracking-area object, you specify a rectangle (in the view’s coordinate system), ...

Thomas Zoechling
  • 34,177
  • 3
  • 81
  • 112
  • 1
    Worth pointing out: `[self frame]` is in *the superview's* coordinate system, so passing `[self frame]` as the rectangle is very likely to be completely wrong: Most probably, the tracking rectangle will be as far up and right “in” your view as your view is up and right in its superview. The correct rectangle for the entire view, as shown in this answer, is `[self bounds]`. A view's bounds is within (and, indeed, the bounds of) its own coordinate system. – Peter Hosey Nov 09 '10 at 19:21
  • Good answer. Pretty sure you should `[trackingArea release]` after `[self addTrackingArea:trackingArea]`, it'll be owned by the view. – petert Jan 26 '11 at 12:21
4

Straight from the docs for NSTrackingInVisibleRect:

The NSTrackingArea object is automatically synchronized with changes in the view’s visible area (visibleRect) and the value returned from rect is ignored.

Mike Abdullah
  • 14,933
  • 2
  • 50
  • 75
  • thanks. that helped and i'm now getting the callbacks I need. – JasonGenX Nov 10 '10 at 16:40
  • It however seems to work weirdly when this option is given for NSTrackingArea objects in each row of a view based NSOutlineView when it is scrolled. I had to implement as given at http://stackoverflow.com/a/9107224/804616 for it to work which must not be required since the docs say "syncrhonized with changes in the view's visible area". – trss Jul 10 '12 at 16:49