Re: mouseDragged: with NSTableView
Re: mouseDragged: with NSTableView
- Subject: Re: mouseDragged: with NSTableView
- From: Ben Lachman <email@hidden>
- Date: Tue, 21 Apr 2009 02:19:49 -0400
Ok. Found a work around--it's a big pain in the butt though.
What you have to do is override the tableview's mouseDown, install an
event tap on drag events for the current process as a listener, then
process drag events in the tap's callback and send them off to the
correct view as needed. NSTableView's mouse tracking still gets the
events and functions normally. Disabling the event tap after you're
done is important, otherwise it doesn't seems to go away and things
get real slow. This code isn't the best for background apps because
of the way the cocoa run loop doesn't always drain it's autorelease
pool when in the background, but otherwise should work. Last caveat
is that autoscroll is only called once, I haven't yet implemented
repeated calling of autoscroll to make continuous scrolling happen.
Anyway, here's the code:
CGEventRef DragEventTapCallback(CGEventTapProxy proxy, CGEventType
type, CGEventRef event, void *userData) {
NSEvent *dragEvent = [NSEvent eventWithCGEvent:event];
NSView *groceryView = (NSView *)userData;
NSScrollView *scrollView = [groceryView enclosingScrollView]; // this
is the scrollview we're passing drag events to via the autoscroll:
mechanism
NSPoint viewLocation = [scrollView convertPointFromBase:[dragEvent
locationInWindow]];
if( ! NSMouseInRect(viewLocation, [scrollView visibleRect],
[scrollView isFlipped]) )
[groceryView autoscroll:dragEvent];
return nil; // since we're just a listener we can return nil
}
- (void)mouseDown:(NSEvent *)theEvent {
// create and install a temporary event tap
CFRunLoopRef cfRunLoop = CFRunLoopGetCurrent();
if( cfRunLoop == nil )
return;
ProcessSerialNumber psn;
GetCurrentProcess(&psn);
CFMachPortRef eventTapPort = CGEventTapCreateForPSN(&psn,
kCGTailAppendEventTap, kCGEventTapOptionListenOnly,
CGEventMaskBit(kCGEventLeftMouseDragged), DragEventTapCallback,
groceryListView); // pass in the view we'll be autoscrolling
if( eventTapPort == nil )
return;
CFRunLoopSourceRef eventTapSource =
CFMachPortCreateRunLoopSource(NULL, eventTapPort, 0);
if( eventTapSource == nil )
return;
CFRunLoopAddSource(cfRunLoop, eventTapSource, kCFRunLoopCommonModes);
// run the super mouse tracking code
[super mouseDown:theEvent];
// uninstall the event tap
CGEventTapEnable(eventTapPort, NO);
CFRunLoopRemoveSource(cfRunLoop, eventTapSource,
kCFRunLoopCommonModes);
CFRelease(eventTapSource);
CFRelease(eventTapPort);
}
--
Ben Lachman
Acacia Tree Software
http://acaciatreesoftware.com
email: email@hidden
twitter: @benlachman
mobile: 740.590.0009
On Apr 17, 2009, at 5:07 PM, Corbin Dunn wrote:
On Apr 17, 2009, at 1:56 PM, Ben Lachman wrote:
Does anyone know of a way to get a mouseDragged event for a
tableview? I've sub-classed NSTableView and it's enclosing
scrollview to no effect (doesn't even hit -mouseDragged:). My
guess is that it is being eaten by the clip view, but there isn't
an easy way to sub-class that from what I can tell. Anyone have
any thoughts?
Nope...you can't. NSTableView uses the "mouse tracking" approach
instead of the "three method approach" (which you would want in
order to subclass).
See:
http://developer.apple.com/documentation/Cocoa/Conceptual/EventOverview/HandlingMouseEvents/HandlingMouseEvents.html
In short; what are you trying to do?
You'll probably have to override mouseDown:, determine if you should
call super or not, and if not, write your own mouse-tracking loop as
seen above.
corbin
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden