views:

181

answers:

4

I'm doing usability testing and would like to log all user input events: mouse movements, clicks, drags, and keyboard input. I'm not having much luck figuring out how, or finding any code to do so. Any hints? I took a look at the CoreGraphics EventTap mechanisms, but I'm worried that it will be too low-level; I'd like to actually know what particular UI elements the user clicks on.

Edit to clarify:

I'm doing usability testing, so I want to keep track of what parts of the interface the user uses and doesn't use. So, I want to keep track of "Button 'foo' was clicked 7 times at these particular timestamps, the user scrolled through this list and selected such-and-such item" and so forth.

+3  A: 

If you're just looking to track them for your application, you could override -[NSApplication sendEvent:]. It's responsible for dispatching all the events your application receives to the appropriate responders.

Chuck
Hm, it would appear that my comment disappeared. To reprise: unless I'm missing something, what I get from sendEvent doesn't contain any details about what UI element was clicked on. I seem to just get an NSEvent that informs me that "location (x,y) was clicked on in the window" without knowing what button, view, etc was clicked.
Dan
A: 

This is completely different than what you're thinking about right now, but consider something like Silverback if you haven't yet.

Marc Charbonneau
Thanks for the tip; I'm using ScreenFlow to do screen recording.
Dan
+1  A: 

I think you'll need to do a lot of swizzling.

Try swizzling tryToPerform:with: first; if that doesn't work, you'll need to swizzle such methods as mouseDown:, mouseUp:, the drag event methods, keyDown:, keyUp:, and the undocumented gesture methods.

One complication in the latter solution is that you'll need to swizzle those methods on not just NSResponder, but on several of its subclasses, because many view classes provide their own implementations, which may or may not call up to their ancestors' implementations.

Peter Hosey
Yep, no good with tryToPerform:with:. I get nothing whatsoever. My original solution in fact involved trying to swizzle mouseDown: etc, but, as you say, many of the downstream responders don't call back to the parent method. I guess this means, ideally, figuring out all of the UI classes in use and automatically swizzling them all. That's probably a separate question, though.
Dan
+1  A: 

Instruments has a way to record user interface events. It seems like you might be able to use the dtrace calls that underlie this to accomplish what you're going for.

JimDusseau