Question

I am developing an application with a custom view where the user is able to move objects around the view. They can pick them up and put them in different places and I want to cursor to change depending on what objects they can pick-up and where they can put them.

I am using tracking areas, but in order to maintain the correct cursors I am using tracking area notifications and setting the cursor for any mouse movement.

This is working well and I have my solution, but I wanted to know if there was a performance penalty for calling [NSCursor set] so often or if AppKit is able to handle this without issue?

Update: As advised by Rob Keniger I have profiled the application and didn't see any real amount of time spent changing cursors. Just to be safe, I have implemented a simple macro that keeps the current cursor state and only sets it if necessary, as defined here:

// Values for _currentCursor
#define CURRENT_CURSOR_UNKNOWN      0
#define CURRENT_CURSOR_ARROW        1
#define CURRENT_CURSOR_POINTINGHAND 2
#define CURRENT_CURSOR_OPENHAND     3
#define CURRENT_CURSOR_CLOSEDHAND   4
#define CURRENT_CURSOR_NOENTRY      5

#define CURRENT_CURSOR_HIDDEN       0x80

#define SET_CURSOR(current, cursor) \
if ((_currentCursor & CURRENT_CURSOR_HIDDEN) == 0 && _currentCursor != current) \
{ \
   [cursor set]; \
    _currentCursor = current; \
}

You would invoke this in code thus:

SET_CURSOR(CURRENT_CURSOR_CLOSEDHAND, [NSCursor closedHandCursor]);
Was it helpful?

Solution

Firstly, with regards to performance, have you tested it? Apple provides excellent tools for profiling. With Instruments you'll very quickly find out how much of a performance hit the cursor changing calls are causing. Don't guess, profile.

Secondly, why are you not using the mouseEntered: and mouseExited: events to change the cursor, rather than the mouseMoved: event? Most of the time, the only time the cursor needs to change is when the mouse enters or exits a tracking area, right?

If you do need finer-grained control (for instance, I could see this might be the case if you're needing to select a non-rectangular object) and if the cursor change call turns out to be expensive (I very much doubt it), you should just store the current state of the cursor and in the mouseMoved: event, check to see if the cursor needs to change and then change it if so.

However, I suspect that what you're already doing will turn out to be just fine, as NSCursor probably does a similar check if you call [NSCursor set] with the same cursor as the current cursor.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top