From f3cca83dc8babb0134276a3f225340bd24a2d454 Mon Sep 17 00:00:00 2001 From: jules Date: Thu, 13 Feb 2014 21:53:11 +0000 Subject: [PATCH] Refactored some NSView wrapper classes. Should fix some plugin host window resizing issues. --- .../format_types/juce_VST3PluginFormat.cpp | 9 +- .../format_types/juce_VSTPluginFormat.cpp | 11 +- .../juce_audio_processors.cpp | 33 +++++ .../native/juce_mac_NSViewComponent.mm | 116 ++++++++++++------ 4 files changed, 116 insertions(+), 53 deletions(-) diff --git a/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp b/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp index 7c0012fb8f..9aa67edeba 100644 --- a/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp +++ b/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp @@ -1220,7 +1220,6 @@ public: #if JUCE_MAC dummyComponent.setView (nullptr); - [pluginHandle release]; #endif view = nullptr; @@ -1337,14 +1336,14 @@ private: ScopedPointer peer; typedef HWND HandleFormat; #elif JUCE_MAC - NSViewComponent dummyComponent; + AutoResizingNSViewComponentWithParent dummyComponent; typedef NSView* HandleFormat; #else Component dummyComponent; typedef void* HandleFormat; #endif - HandleFormat pluginHandle; // Don't delete this + HandleFormat pluginHandle; bool recursiveResize; //============================================================================== @@ -1370,8 +1369,8 @@ private: #elif JUCE_MAC dummyComponent.setBounds (getBounds().withZeroOrigin()); addAndMakeVisible (dummyComponent); - pluginHandle = [[NSView alloc] init]; - dummyComponent.setView (pluginHandle); + pluginHandle = (NSView*) dummyComponent.getView(); + jassert (pluginHandle != nil); #endif if (pluginHandle != nullptr) diff --git a/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp b/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp index fdfbf6b65b..3d29db0487 100644 --- a/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp +++ b/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp @@ -1927,17 +1927,10 @@ public: #elif JUCE_MAC #if JUCE_SUPPORT_CARBON if (! plug.usesCocoaNSView) - { addAndMakeVisible (carbonWrapper = new CarbonWrapperComponent (*this)); - } else #endif - { - addAndMakeVisible (cocoaWrapper = new AutoResizingNSViewComponent()); - NSView* innerView = [[NSView alloc] init]; - cocoaWrapper->setView (innerView); - [innerView release]; - } + addAndMakeVisible (cocoaWrapper = new AutoResizingNSViewComponentWithParent()); #endif activeVSTWindows.add (this); @@ -2600,7 +2593,7 @@ private: ScopedPointer carbonWrapper; #endif - ScopedPointer cocoaWrapper; + ScopedPointer cocoaWrapper; void resized() override { diff --git a/modules/juce_audio_processors/juce_audio_processors.cpp b/modules/juce_audio_processors/juce_audio_processors.cpp index e1a281b417..474198a892 100644 --- a/modules/juce_audio_processors/juce_audio_processors.cpp +++ b/modules/juce_audio_processors/juce_audio_processors.cpp @@ -77,6 +77,7 @@ static inline bool arrayContainsPlugin (const OwnedArray& lis } #if JUCE_MAC +//============================================================================== struct AutoResizingNSViewComponent : public NSViewComponent, private AsyncUpdater { @@ -100,6 +101,38 @@ struct AutoResizingNSViewComponent : public NSViewComponent, bool recursive; }; + +//============================================================================== +struct AutoResizingNSViewComponentWithParent : public AutoResizingNSViewComponent, + private Timer +{ + AutoResizingNSViewComponentWithParent() + { + NSView* v = [[NSView alloc] init]; + setView (v); + [v release]; + + startTimer (100); + } + + void timerCallback() override + { + if (NSView* parent = (NSView*) getView()) + { + if (NSView* child = [[parent subviews] firstObject]) + { + NSRect f = [parent frame]; + NSSize newSize = [child frame].size; + + if (f.size.width != newSize.width || f.size.height != newSize.height) + { + f.size = newSize; + [parent setFrame: f]; + } + } + } + } +}; #endif #if JUCE_CLANG diff --git a/modules/juce_gui_extra/native/juce_mac_NSViewComponent.mm b/modules/juce_gui_extra/native/juce_mac_NSViewComponent.mm index ff9cdca8d9..b31eb86168 100644 --- a/modules/juce_gui_extra/native/juce_mac_NSViewComponent.mm +++ b/modules/juce_gui_extra/native/juce_mac_NSViewComponent.mm @@ -22,14 +22,82 @@ ============================================================================== */ + +struct NSViewResizeWatcher +{ + NSViewResizeWatcher() : callback (nil) {} + + virtual ~NSViewResizeWatcher() + { + // must call detachViewWatcher() first + jassert (callback == nil); + } + + void attachViewWatcher (NSView* view) + { + static ViewFrameChangeCallbackClass cls; + callback = [cls.createInstance() init]; + ViewFrameChangeCallbackClass::setTarget (callback, this); + + [[NSNotificationCenter defaultCenter] addObserver: callback + selector: @selector (frameChanged:) + name: NSViewFrameDidChangeNotification + object: view]; + } + + void detachViewWatcher() + { + if (callback != nil) + { + [[NSNotificationCenter defaultCenter] removeObserver: callback]; + [callback release]; + callback = nil; + } + } + + virtual void viewResized() = 0; + +private: + id callback; + + //============================================================================== + struct ViewFrameChangeCallbackClass : public ObjCClass + { + ViewFrameChangeCallbackClass() : ObjCClass ("JUCE_NSViewCallback_") + { + addIvar ("target"); + addMethod (@selector (frameChanged:), frameChanged, "v@:@"); + registerClass(); + } + + static void setTarget (id self, NSViewResizeWatcher* c) + { + object_setInstanceVariable (self, "target", c); + } + + private: + static void frameChanged (id self, SEL, NSNotification*) + { + if (NSViewResizeWatcher* const target = getIvar (self, "target")) + target->viewResized(); + } + + JUCE_DECLARE_NON_COPYABLE (ViewFrameChangeCallbackClass); + }; + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (NSViewResizeWatcher) +}; + +//============================================================================== class NSViewAttachment : public ReferenceCountedObject, - public ComponentMovementWatcher + public ComponentMovementWatcher, + private NSViewResizeWatcher { public: NSViewAttachment (NSView* const v, Component& comp) : ComponentMovementWatcher (&comp), view (v), owner (comp), - currentPeer (nullptr), frameChangeCallback (nullptr) + currentPeer (nullptr) { [view retain]; [view setPostsFrameChangedNotifications: YES]; @@ -37,21 +105,12 @@ public: if (owner.isShowing()) componentPeerChanged(); - static ViewFrameChangeCallbackClass cls; - frameChangeCallback = [cls.createInstance() init]; - ViewFrameChangeCallbackClass::setTarget (frameChangeCallback, &owner); - - [[NSNotificationCenter defaultCenter] addObserver: frameChangeCallback - selector: @selector (frameChanged:) - name: NSViewFrameDidChangeNotification - object: view]; + attachViewWatcher (view); } ~NSViewAttachment() { - [[NSNotificationCenter defaultCenter] removeObserver: frameChangeCallback]; - [frameChangeCallback release]; - + detachViewWatcher(); removeFromParent(); [view release]; } @@ -103,12 +162,16 @@ public: componentPeerChanged(); } + void viewResized() override + { + owner.childBoundsChanged (nullptr); + } + NSView* const view; private: Component& owner; ComponentPeer* currentPeer; - id frameChangeCallback; void removeFromParent() { @@ -117,31 +180,6 @@ private: // override the call and use it as a sign that they're being deleted, which breaks everything.. } - //============================================================================== - struct ViewFrameChangeCallbackClass : public ObjCClass - { - ViewFrameChangeCallbackClass() : ObjCClass ("JUCE_NSViewCallback_") - { - addIvar ("target"); - addMethod (@selector (frameChanged:), frameChanged, "v@:@"); - registerClass(); - } - - static void setTarget (id self, Component* c) - { - object_setInstanceVariable (self, "target", c); - } - - private: - static void frameChanged (id self, SEL, NSNotification*) - { - if (Component* const target = getIvar (self, "target")) - target->childBoundsChanged (nullptr); - } - - JUCE_DECLARE_NON_COPYABLE (ViewFrameChangeCallbackClass); - }; - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (NSViewAttachment) };