diff --git a/src/effects/VST/VSTEffect.cpp b/src/effects/VST/VSTEffect.cpp index ae56fc85b..5a217d9e6 100644 --- a/src/effects/VST/VSTEffect.cpp +++ b/src/effects/VST/VSTEffect.cpp @@ -826,6 +826,36 @@ DEFINE_LOCAL_EVENT_TYPE(EVT_UPDATEDISPLAY); extern void DebugPrintControlHierarchy(WindowRef inWindow); extern void DebugPrintWindowList(void); +// Event handler to track when the mouse enters/exits the various view +static const EventTypeSpec trackingEventList[] = +{ + {kEventClassControl, kEventControlTrackingAreaEntered}, + {kEventClassControl, kEventControlTrackingAreaExited}, +}; + +pascal OSStatus VSTEffect::TrackingEventHandler(EventHandlerCallRef handler, EventRef event, void *data) +{ + return ((VSTEffect *)data)->OnTrackingEvent(event); +} + +OSStatus VSTEffect::OnTrackingEvent(EventRef event) +{ + OSStatus result = eventNotHandledErr; + + if (GetEventKind(event) == kEventControlTrackingAreaEntered) + { + // Should we save the existing cursor??? + SetThemeCursor(kThemeArrowCursor); + } + + if (GetEventKind(event) == kEventControlTrackingAreaExited) + { + // Possibly restore a saved cursor + } + + return result; +} + // ---------------------------------------------------------------------------- // Most of the following is used to deal with VST effects that create an overlay // window on top of ours. This is usually done because Cocoa is being used @@ -1136,6 +1166,24 @@ OSStatus VSTEffect::OnWindowEvent(EventHandlerCallRef handler, EventRef event) this, &mOverlayEventHandlerRef); + ControlRef root = HIViewGetRoot(mOverlayRef); + HIViewRef view; + HIViewFindByID(root, kHIViewWindowContentID, &view); + InstallControlEventHandler(root, + mTrackingHandlerUPP, + GetEventTypeCount(trackingEventList), + trackingEventList, + this, + &mOverlayRootTrackingHandlerRef); + InstallControlEventHandler(view, + mTrackingHandlerUPP, + GetEventTypeCount(trackingEventList), + trackingEventList, + this, + &mOverlayViewTrackingHandlerRef); + HIViewNewTrackingArea(root, NULL, 0, NULL); + HIViewNewTrackingArea(view, NULL, 0, NULL); + //#if !defined(EXPERIMENTAL_REALTIME_EFFECTS) // Since we set the activation scope to independent, // we need to make sure the overlay gets activated. @@ -1436,6 +1484,13 @@ VSTEffect::VSTEffect(const wxString & path, VSTEffect *master) mWindowRef = 0; mWindowEventHandlerUPP = 0; mWindowEventHandlerRef = 0; + + mRootTrackingHandlerRef = 0; + mViewTrackingHandlerRef = 0; + mSubviewTrackingHandlerRef = 0; + mOverlayRootTrackingHandlerRef = 0; + mOverlayViewTrackingHandlerRef = 0; + #elif defined(__WXMSW__) mHwnd = 0; #else @@ -3102,6 +3157,18 @@ void VSTEffect::RemoveHandler() mWindowRef = 0; } + if (mOverlayViewTrackingHandlerRef) + { + ::RemoveEventHandler(mOverlayViewTrackingHandlerRef); + mOverlayViewTrackingHandlerRef = 0; + } + + if (mOverlayRootTrackingHandlerRef) + { + ::RemoveEventHandler(mOverlayRootTrackingHandlerRef); + mOverlayRootTrackingHandlerRef = 0; + } + if (mOverlayEventHandlerRef) { ::RemoveEventHandler(mOverlayEventHandlerRef); @@ -3114,6 +3181,30 @@ void VSTEffect::RemoveHandler() mOverlayEventHandlerUPP = 0; } + if (mSubviewTrackingHandlerRef) + { + ::RemoveEventHandler(mSubviewTrackingHandlerRef); + mSubviewTrackingHandlerRef = 0; + } + + if (mViewTrackingHandlerRef) + { + ::RemoveEventHandler(mViewTrackingHandlerRef); + mViewTrackingHandlerRef = 0; + } + + if (mRootTrackingHandlerRef) + { + ::RemoveEventHandler(mRootTrackingHandlerRef); + mRootTrackingHandlerRef = 0; + } + + if (mTrackingHandlerUPP) + { + DisposeEventHandlerUPP(mTrackingHandlerUPP); + mTrackingHandlerUPP = 0; + } + if (mWindowEventHandlerRef) { ::RemoveEventHandler(mWindowEventHandlerRef); @@ -3172,8 +3263,9 @@ void VSTEffect::BuildFancy() &mWindowEventHandlerRef); // Find the content view within our window + ControlRef root = HIViewGetRoot(mWindowRef); HIViewRef view; - HIViewFindByID(HIViewGetRoot(mWindowRef), kHIViewWindowContentID, &view); + HIViewFindByID(root, kHIViewWindowContentID, &view); // And ask the effect to add it's GUI callDispatcher(effEditOpen, 0, 0, mWindowRef, 0.0); @@ -3193,6 +3285,30 @@ void VSTEffect::BuildFancy() return; } + // Install the tracking event handler on our views + mTrackingHandlerUPP = NewEventHandlerUPP(VSTEffect::TrackingEventHandler); + InstallControlEventHandler(root, + mTrackingHandlerUPP, + GetEventTypeCount(trackingEventList), + trackingEventList, + this, + &mRootTrackingHandlerRef); + InstallControlEventHandler(view, + mTrackingHandlerUPP, + GetEventTypeCount(trackingEventList), + trackingEventList, + this, + &mViewTrackingHandlerRef); + InstallControlEventHandler(subview, + mTrackingHandlerUPP, + GetEventTypeCount(trackingEventList), + trackingEventList, + this, + &mSubviewTrackingHandlerRef); + HIViewNewTrackingArea(root, NULL, 0, NULL); + HIViewNewTrackingArea(view, NULL, 0, NULL); + HIViewNewTrackingArea(subview, NULL, 0, NULL); + #elif defined(__WXMSW__) // Use a panel to host the plugins GUI diff --git a/src/effects/VST/VSTEffect.h b/src/effects/VST/VSTEffect.h index de733cf6a..54fcfea9f 100644 --- a/src/effects/VST/VSTEffect.h +++ b/src/effects/VST/VSTEffect.h @@ -325,6 +325,8 @@ private: OSStatus OnOverlayEvent(EventHandlerCallRef handler, EventRef event); static pascal OSStatus WindowEventHandler(EventHandlerCallRef handler, EventRef event, void *data); OSStatus OnWindowEvent(EventHandlerCallRef handler, EventRef event); + static pascal OSStatus TrackingEventHandler(EventHandlerCallRef handler, EventRef event, void *data); + OSStatus OnTrackingEvent(EventRef event); WindowRef mOverlayRef; EventHandlerUPP mOverlayEventHandlerUPP; @@ -335,6 +337,13 @@ private: EventHandlerUPP mWindowEventHandlerUPP; EventHandlerRef mWindowEventHandlerRef; + EventHandlerUPP mTrackingHandlerUPP; + EventHandlerRef mRootTrackingHandlerRef; + EventHandlerRef mViewTrackingHandlerRef; + EventHandlerRef mSubviewTrackingHandlerRef; + EventHandlerRef mOverlayRootTrackingHandlerRef; + EventHandlerRef mOverlayViewTrackingHandlerRef; + #elif defined(__WXMSW__) HANDLE mHwnd; diff --git a/src/effects/audiounits/AudioUnitEffect.cpp b/src/effects/audiounits/AudioUnitEffect.cpp index eb809611f..47fa63e52 100644 --- a/src/effects/audiounits/AudioUnitEffect.cpp +++ b/src/effects/audiounits/AudioUnitEffect.cpp @@ -822,6 +822,38 @@ printf("CONTROL class %d kind %d\n", GetEventClass(event), GetEventKind(event)); } */ +// Event handler to track when the mouse enters/exits the various view +static const EventTypeSpec trackingEventList[] = +{ + {kEventClassControl, kEventControlTrackingAreaEntered}, + {kEventClassControl, kEventControlTrackingAreaExited}, +}; + +pascal OSStatus +AudioUnitEffect::TrackingEventHandler(EventHandlerCallRef handler, EventRef event, void *data) +{ + return ((AudioUnitEffect *)data)->OnTrackingEvent(event); +} + +OSStatus AudioUnitEffect::OnTrackingEvent(EventRef event) +{ + OSStatus result = eventNotHandledErr; + + if (GetEventKind(event) == kEventControlTrackingAreaEntered) + { + // Should we save the existing cursor??? + SetThemeCursor(kThemeArrowCursor); + } + + if (GetEventKind(event) == kEventControlTrackingAreaExited) + { + // Possibly restore a saved cursor + } + + return result; +} + + // Event handler to capture the window close event static const EventTypeSpec windowEventList[] = { @@ -908,6 +940,11 @@ AudioUnitEffect::AudioUnitEffect(const wxString & path, mHandlerRef = NULL; mHandlerUPP = NULL; + mRootTrackingHandlerRef = NULL; + mContentTrackingHandlerRef = NULL; + mAUTrackingHandlerRef = NULL; + mTrackingHandlerUPP = NULL; + mEventHelper = NULL; mEventListenerRef = NULL; } @@ -1769,6 +1806,16 @@ bool AudioUnitEffect::SetAutomationParameters(EffectAutomationParameters & parms void AudioUnitEffect::SetUIHost(EffectUIHostInterface *host) { mUIHost = host; + + mHandlerRef = 0; + mHandlerUPP = 0; + mControlHandlerRef = 0; + mControlHandlerUPP = 0; + + mTrackingHandlerUPP = 0; + mRootTrackingHandlerRef = 0; + mContentTrackingHandlerRef = 0; + mAUTrackingHandlerRef = 0; } bool AudioUnitEffect::PopulateUI(wxWindow *parent) @@ -1784,7 +1831,7 @@ bool AudioUnitEffect::PopulateUI(wxWindow *parent) // Find the content view within our window HIViewRef contentView; - HIViewFindByID(HIViewGetRoot(windowRef), kHIViewWindowContentID, &contentView); + HIViewFindByID(rootControl, kHIViewWindowContentID, &contentView); mIsCocoa = false; mIsCarbon = false; @@ -1898,6 +1945,28 @@ bool AudioUnitEffect::PopulateUI(wxWindow *parent) this, &mControlHandlerRef); */ + mTrackingHandlerUPP = NewEventHandlerUPP(AudioUnitEffect::TrackingEventHandler); + InstallControlEventHandler(rootControl, + mTrackingHandlerUPP, + GetEventTypeCount(trackingEventList), + trackingEventList, + this, + &mRootTrackingHandlerRef); + InstallControlEventHandler(contentView, + mTrackingHandlerUPP, + GetEventTypeCount(trackingEventList), + trackingEventList, + this, + &mContentTrackingHandlerRef); + InstallControlEventHandler(auView, + mTrackingHandlerUPP, + GetEventTypeCount(trackingEventList), + trackingEventList, + this, + &mAUTrackingHandlerRef); + HIViewNewTrackingArea(rootControl, NULL, 0, NULL); + HIViewNewTrackingArea(contentView, NULL, 0, NULL); + HIViewNewTrackingArea(auView, NULL, 0, NULL); return true; } @@ -1931,6 +2000,8 @@ bool AudioUnitEffect::HideUI() bool AudioUnitEffect::CloseUI() { + RemoveHandler(); + if (mEventHelper) { mParent->RemoveEventHandler(mEventHelper); @@ -2075,6 +2146,57 @@ void AudioUnitEffect::ShowOptions() // AudioUnitEffect Implementation // ============================================================================ +void AudioUnitEffect::RemoveHandler() +{ + if (mAUTrackingHandlerRef) + { + ::RemoveEventHandler(mAUTrackingHandlerRef); + mAUTrackingHandlerRef = 0; + } + + if (mContentTrackingHandlerRef) + { + ::RemoveEventHandler(mContentTrackingHandlerRef); + mContentTrackingHandlerRef = 0; + } + + if (mRootTrackingHandlerRef) + { + ::RemoveEventHandler(mRootTrackingHandlerRef); + mRootTrackingHandlerRef = 0; + } + + if (mTrackingHandlerUPP) + { + DisposeEventHandlerUPP(mTrackingHandlerUPP); + mTrackingHandlerUPP = 0; + } + + if (mControlHandlerRef) + { + ::RemoveEventHandler(mControlHandlerRef); + mControlHandlerRef = 0; + } + + if (mControlHandlerUPP) + { + DisposeEventHandlerUPP(mControlHandlerUPP); + mControlHandlerUPP = 0; + } + + if (mHandlerRef) + { + ::RemoveEventHandler(mHandlerRef); + mHandlerRef = 0; + } + + if (mHandlerUPP) + { + DisposeEventHandlerUPP(mHandlerUPP); + mHandlerUPP = 0; + } +} + void AudioUnitEffect::LoadParameters(const wxString & group) { OSStatus result; diff --git a/src/effects/audiounits/AudioUnitEffect.h b/src/effects/audiounits/AudioUnitEffect.h index 4bd619dc5..dfdff5c5b 100644 --- a/src/effects/audiounits/AudioUnitEffect.h +++ b/src/effects/audiounits/AudioUnitEffect.h @@ -165,6 +165,13 @@ private: void *data); OSStatus ControlEventHandler(EventRef event); + static pascal OSStatus TrackingEventHandler(EventHandlerCallRef handler, + EventRef event, + void *data); + OSStatus OnTrackingEvent(EventRef event); + + void RemoveHandler(); + void GetChannelCounts(); void LoadParameters(const wxString & group); @@ -224,6 +231,11 @@ private: EventHandlerRef mControlHandlerRef; EventHandlerUPP mControlHandlerUPP; + EventHandlerUPP mTrackingHandlerUPP; + EventHandlerRef mRootTrackingHandlerRef; + EventHandlerRef mContentTrackingHandlerRef; + EventHandlerRef mAUTrackingHandlerRef; + AudioUnitEffectEventHelper *mEventHelper; friend class AudioUnitEffectEventHelper;