3
votes

I'm currently porting an application (or to be more exact, a VST Plugin) from windows to OSX. I'm kinda new to OSX programming, but I'm using a Cocoa NSView added to a Carbon window (that I get from the host) using HICocoaCreateView.

Anywhoo... Inside this view I want to get mouseMoved & mouseDragged events, but when dragging I also want to get these events even when the mouse leaves my NSView (and also the parent window), but I just can't seem to make this happen.

On windows I would do a SetCapture on mouseDown to get all mouse events for a while. The closest thing I've found in Cocoa is "addGlobalMonitorForEventsMatchingMask", but this is 10.6+ only and I have a hard time believing this is something that wasn't possible to do before that. (After all, this is something that is commonly used for draggable components like scroll bars etc.)

This is driving me insane!

UPDATE:

There's something called CGEventTapCreate as well which, as far as I can tell from scarce docs, is similar to addGlobalMonitor... but in Carbon. I haven't gotten a hang of exactly how Carbon and Cocoa relate to eachother and what's working where. Is it usuable even though my main stuff is Cocoa? (The window I get from the host can be both Cocoa and Carbon. It's really all a mess.)

2

2 Answers

3
votes

The CGEventTap stuff isn't really Carbon. It's in Quartz, which can be treated as a sub-framework of Cocoa (which is really just a conglomeration of other frameworks anyways). Carbon is a legacy (and deprecated) framework that was created to ease the transition between Mac OS 9, where applications programming was mostly done in C, and Mac OS X, where Objective-C is used. Not every C function that Apple provides is Carbon; Quartz and Grand Central Dispatch spring to mind immediately as modern frameworks that use C (I believe for the slight speed advantage).

Having gotten the background out of the way, those functions work just fine with Cocoa code. So far as I can figure out, addGlobalEventMonitor... and addLocalEventMonitor... are just Obj-C wrappers around CGEventTaps.

I think a CGEventTap is the way to go. The docs for them are sparse, yes, but they're straightforward. Dave DeLong's answer to this SO question may put you on the right path.

2
votes

I guess you need to do something like this...

EventHandlerRef     m_ApplicationMouseDragEventHandlerRef;          
EventHandlerRef     m_MonitorMouseDragEventHandlerRef;

{
    OSStatus ErrStatus;

    static const EventTypeSpec kMouseDragEvents[] =
      {
        { kEventClassMouse, kEventMouseDragged }
      };

    ErrStatus = InstallEventHandler(GetEventMonitorTarget(), NewEventHandlerUPP(MouseHasDragged), GetEventTypeCount(kMouseDragEvents), kMouseDragEvents, this, &m_MonitorMouseDragEventHandlerRef);

    ErrStatus = InstallApplicationEventHandler(NewEventHandlerUPP(MouseHasDragged), GetEventTypeCount(kMouseDragEvents), kMouseDragEvents, this, &m_ApplicationMouseDragEventHandlerRef);

    return true;
}

//implement these functions
OSStatus MouseHasDragged(EventHandlerCallRef inCaller, EventRef inEvent, void *pUserData){}

EventTypeSpec needs to be updated/changed for moving and rest should be same. This is a carbon code. But you may also look at quartz desktop services.

Cheers!