| @@ -951,15 +951,13 @@ private: | |||
| }; | |||
| //============================================================================== | |||
| class EditorCompHolder : public Component, | |||
| public ComponentListener | |||
| class EditorCompHolder : public Component | |||
| { | |||
| public: | |||
| EditorCompHolder (AudioProcessorEditor* const editor) | |||
| { | |||
| setSize (editor->getWidth(), editor->getHeight()); | |||
| addAndMakeVisible (editor); | |||
| editor->addComponentListener (this); | |||
| #if ! JucePlugin_EditorRequiresKeyboardFocus | |||
| setWantsKeyboardFocus (false); | |||
| @@ -974,11 +972,11 @@ public: | |||
| // have been transferred to another parent which takes over ownership. | |||
| } | |||
| void componentMovedOrResized (Component& component, bool wasMoved, bool wasResized) | |||
| void childBoundsChanged (Component*) | |||
| { | |||
| Component* editor = getChildComponent(0); | |||
| if (editor != 0 && wasResized) | |||
| if (editor != 0) | |||
| { | |||
| const int w = jmax (32, editor->getWidth()); | |||
| const int h = jmax (32, editor->getHeight()); | |||
| @@ -988,13 +986,16 @@ public: | |||
| NSView* view = (NSView*) getWindowHandle(); | |||
| NSRect r = [[view superview] frame]; | |||
| r.size.width = component.getWidth(); | |||
| r.size.height = component.getHeight(); | |||
| r.size.width = editor->getWidth(); | |||
| r.size.height = editor->getHeight(); | |||
| [[view superview] setFrame: r]; | |||
| [view setFrame: NSMakeRect (0, 0, editor->getWidth(), editor->getHeight())]; | |||
| [view setNeedsDisplay: YES]; | |||
| } | |||
| } | |||
| private: | |||
| JUCE_DECLARE_NON_COPYABLE (EditorCompHolder); | |||
| }; | |||
| //============================================================================== | |||
| @@ -1044,6 +1045,7 @@ public: | |||
| // is trying to delete our plugin.. | |||
| jassert (Component::getCurrentlyModalComponent() == 0); | |||
| [[NSNotificationCenter defaultCenter] removeObserver: self]; | |||
| [self deleteEditor]; | |||
| jassert (activeUIs.contains (self)); | |||
| @@ -1204,6 +1206,8 @@ public: | |||
| void* getEventListenerUserData() const { return mEventListenerUserData; } | |||
| private: | |||
| FakeMouseMoveGenerator fakeMouseGenerator; | |||
| void deleteUI() | |||
| { | |||
| if (windowComp != 0) | |||
| @@ -1223,26 +1227,25 @@ private: | |||
| //============================================================================== | |||
| // Uses a child NSWindow to sit in front of a HIView and display our component | |||
| class ComponentInHIView : public Component, | |||
| public ComponentListener | |||
| class ComponentInHIView : public Component | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| ComponentInHIView (Component* const editor_, HIViewRef parentHIView) | |||
| ComponentInHIView (AudioProcessorEditor* const editor_, HIViewRef parentHIView) | |||
| : parentView (parentHIView), | |||
| editor (editor_), | |||
| recursive (false) | |||
| { | |||
| JUCE_AUTORELEASEPOOL | |||
| jassert (editor != 0); | |||
| addAndMakeVisible (editor); | |||
| jassert (editor_ != 0); | |||
| addAndMakeVisible (&editor); | |||
| setOpaque (true); | |||
| setVisible (true); | |||
| setBroughtToFrontOnMouseClick (true); | |||
| setSize (editor->getWidth(), editor->getHeight()); | |||
| SizeControl (parentHIView, editor->getWidth(), editor->getHeight()); | |||
| setSize (editor.getWidth(), editor.getHeight()); | |||
| SizeControl (parentHIView, editor.getWidth(), editor.getHeight()); | |||
| WindowRef windowRef = HIViewGetWindow (parentHIView); | |||
| hostWindow = [[NSWindow alloc] initWithWindowRef: windowRef]; | |||
| @@ -1280,16 +1283,10 @@ private: | |||
| NewEventHandlerUPP (windowVisibilityBodge), | |||
| GetEventTypeCount (eventsToCatch), eventsToCatch, | |||
| (void*) hostWindow, 0); | |||
| editor->addComponentListener (this); | |||
| } | |||
| ~ComponentInHIView() | |||
| { | |||
| jassert (isParentOf (editor)); // you mustn't remove your editor from its parent! | |||
| editor->removeComponentListener (this); | |||
| JUCE_AUTORELEASEPOOL | |||
| NSWindow* pluginWindow = [((NSView*) getWindowHandle()) window]; | |||
| @@ -1298,8 +1295,6 @@ private: | |||
| [hostWindow release]; | |||
| hostWindow = 0; | |||
| editor = 0; | |||
| } | |||
| void updateWindowPos() | |||
| @@ -1330,27 +1325,24 @@ private: | |||
| void paint (Graphics& g) {} | |||
| void componentMovedOrResized (Component& component, bool wasMoved, bool wasResized) | |||
| void childBoundsChanged (Component*) | |||
| { | |||
| if (! recursive) | |||
| { | |||
| recursive = true; | |||
| if (editor != 0 && wasResized) | |||
| { | |||
| const int w = jmax (32, editor->getWidth()); | |||
| const int h = jmax (32, editor->getHeight()); | |||
| const int w = jmax (32, editor.getWidth()); | |||
| const int h = jmax (32, editor.getHeight()); | |||
| SizeControl (parentView, w, h); | |||
| SizeControl (parentView, w, h); | |||
| if (getWidth() != w || getHeight() != h) | |||
| setSize (w, h); | |||
| if (getWidth() != w || getHeight() != h) | |||
| setSize (w, h); | |||
| editor->repaint(); | |||
| editor.repaint(); | |||
| updateWindowPos(); | |||
| addSubWindow(); // (need this for AULab) | |||
| } | |||
| updateWindowPos(); | |||
| addSubWindow(); // (need this for AULab) | |||
| recursive = false; | |||
| } | |||
| @@ -1378,7 +1370,7 @@ private: | |||
| private: | |||
| HIViewRef parentView; | |||
| NSWindow* hostWindow; | |||
| ScopedPointer<Component> editor; | |||
| EditorCompHolder editor; | |||
| bool recursive; | |||
| /* When you wrap a WindowRef as an NSWindow, it seems to bugger up the HideWindow | |||
| @@ -185,15 +185,10 @@ namespace | |||
| GetClassName (parent, windowType, 31); | |||
| if (String (windowType).equalsIgnoreCase ("MDIClient")) | |||
| { | |||
| w = parent; | |||
| break; | |||
| } | |||
| return parent; | |||
| RECT windowPos; | |||
| RECT windowPos, parentPos; | |||
| GetWindowRect (w, &windowPos); | |||
| RECT parentPos; | |||
| GetWindowRect (parent, &parentPos); | |||
| const int dw = (parentPos.right - parentPos.left) - (windowPos.right - windowPos.left); | |||
| @@ -210,6 +205,42 @@ namespace | |||
| return w; | |||
| } | |||
| //============================================================================== | |||
| static HHOOK mouseWheelHook = 0; | |||
| static int mouseHookUsers = 0; | |||
| LRESULT CALLBACK mouseWheelHookCallback (int nCode, WPARAM wParam, LPARAM lParam) | |||
| { | |||
| if (nCode >= 0 && wParam == WM_MOUSEWHEEL) | |||
| { | |||
| const MSLLHOOKSTRUCT& hs = *(MSLLHOOKSTRUCT*) lParam; | |||
| Component* const comp = Desktop::getInstance().findComponentAt (Point<int> (hs.pt.x, | |||
| hs.pt.y)); | |||
| if (comp != 0 && comp->getWindowHandle() != 0) | |||
| return PostMessage ((HWND) comp->getWindowHandle(), WM_MOUSEWHEEL, | |||
| hs.mouseData & 0xffff0000, (hs.pt.x & 0xffff) | (hs.pt.y << 16)); | |||
| } | |||
| return CallNextHookEx (mouseWheelHook, nCode, wParam, lParam); | |||
| } | |||
| void registerMouseWheelHook() | |||
| { | |||
| if (mouseHookUsers++ == 0) | |||
| mouseWheelHook = SetWindowsHookEx (WH_MOUSE_LL, mouseWheelHookCallback, | |||
| (HINSTANCE) PlatformUtilities::getCurrentModuleInstanceHandle(), 0); | |||
| } | |||
| void unregisterMouseWheelHook() | |||
| { | |||
| if (--mouseHookUsers == 0 && mouseWheelHook != 0) | |||
| { | |||
| UnhookWindowsHookEx (mouseWheelHook); | |||
| mouseWheelHook = 0; | |||
| } | |||
| } | |||
| } | |||
| //============================================================================== | |||
| @@ -1288,14 +1319,20 @@ public: | |||
| editor->setTopLeftPosition (0, 0); | |||
| addAndMakeVisible (editor); | |||
| #if JUCE_WIN | |||
| #if JUCE_WINDOWS | |||
| if (! getHostType().isReceptor()) | |||
| addMouseListener (this, true); | |||
| registerMouseWheelHook(); | |||
| #endif | |||
| } | |||
| ~EditorCompWrapper() | |||
| { | |||
| #if JUCE_WINDOWS | |||
| unregisterMouseWheelHook(); | |||
| #endif | |||
| deleteAllChildren(); // note that we can't use a ScopedPointer because the editor may | |||
| // have been transferred to another parent which takes over ownership. | |||
| } | |||
| @@ -1379,6 +1416,7 @@ public: | |||
| private: | |||
| //============================================================================== | |||
| JuceVSTWrapper& wrapper; | |||
| FakeMouseMoveGenerator fakeMouseGenerator; | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (EditorCompWrapper); | |||
| }; | |||
| @@ -25,3 +25,48 @@ | |||
| #include "juce_IncludeCharacteristics.h" | |||
| #include "../../../juce_amalgamated.h" | |||
| #if JUCE_MAC && JUCE_SUPPORT_CARBON | |||
| // Helper class to workaround carbon windows not getting mouse-moves.. | |||
| class FakeMouseMoveGenerator : public Timer | |||
| { | |||
| public: | |||
| FakeMouseMoveGenerator() | |||
| { | |||
| startTimer (1000 / 30); | |||
| } | |||
| void timerCallback() | |||
| { | |||
| // workaround for carbon windows not getting mouse-moves.. | |||
| const Point<int> screenPos (Desktop::getInstance().getMainMouseSource().getScreenPosition()); | |||
| if (screenPos != lastScreenPos) | |||
| { | |||
| lastScreenPos = screenPos; | |||
| const ModifierKeys mods (ModifierKeys::getCurrentModifiers()); | |||
| if (! mods.isAnyMouseButtonDown()) | |||
| { | |||
| Component* comp = Desktop::getInstance().findComponentAt (screenPos); | |||
| if (comp != 0) | |||
| { | |||
| ComponentPeer* const peer = comp->getPeer(); | |||
| if (peer != 0 && ! peer->isFocused()) | |||
| peer->handleMouseEvent (0, screenPos - peer->getScreenPosition(), mods, Time::currentTimeMillis()); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| private: | |||
| Point<int> lastScreenPos; | |||
| }; | |||
| #else | |||
| struct FakeMouseMoveGenerator {}; | |||
| #endif | |||
| @@ -35673,7 +35673,6 @@ BEGIN_JUCE_NAMESPACE | |||
| AudioProcessor::AudioProcessor() | |||
| : playHead (0), | |||
| activeEditor (0), | |||
| sampleRate (0), | |||
| blockSize (0), | |||
| numInputChannels (0), | |||
| @@ -35855,8 +35854,6 @@ void AudioProcessor::editorBeingDeleted (AudioProcessorEditor* const editor) thr | |||
| { | |||
| const ScopedLock sl (callbackLock); | |||
| jassert (activeEditor == editor); | |||
| if (activeEditor == editor) | |||
| activeEditor = 0; | |||
| } | |||
| @@ -41698,7 +41698,7 @@ protected: | |||
| private: | |||
| Array <AudioProcessorListener*> listeners; | |||
| AudioProcessorEditor* activeEditor; | |||
| Component::SafePointer<AudioProcessorEditor> activeEditor; | |||
| double sampleRate; | |||
| int blockSize, numInputChannels, numOutputChannels, latencySamples; | |||
| bool suspended, nonRealtime; | |||
| @@ -35,7 +35,6 @@ BEGIN_JUCE_NAMESPACE | |||
| //============================================================================== | |||
| AudioProcessor::AudioProcessor() | |||
| : playHead (0), | |||
| activeEditor (0), | |||
| sampleRate (0), | |||
| blockSize (0), | |||
| numInputChannels (0), | |||
| @@ -218,8 +217,6 @@ void AudioProcessor::editorBeingDeleted (AudioProcessorEditor* const editor) thr | |||
| { | |||
| const ScopedLock sl (callbackLock); | |||
| jassert (activeEditor == editor); | |||
| if (activeEditor == editor) | |||
| activeEditor = 0; | |||
| } | |||
| @@ -580,7 +580,7 @@ protected: | |||
| private: | |||
| Array <AudioProcessorListener*> listeners; | |||
| AudioProcessorEditor* activeEditor; | |||
| Component::SafePointer<AudioProcessorEditor> activeEditor; | |||
| double sampleRate; | |||
| int blockSize, numInputChannels, numOutputChannels, latencySamples; | |||
| bool suspended, nonRealtime; | |||