From ead052b1989820d4f89e505429f8ff2aaeb08905 Mon Sep 17 00:00:00 2001 From: jules Date: Mon, 27 Oct 2008 20:31:22 +0000 Subject: [PATCH] --- .../juce_mac_CarbonViewWrapperComponent.h | 244 ++++++++++++++++++ 1 file changed, 244 insertions(+) create mode 100644 build/macosx/platform_specific_code/juce_mac_CarbonViewWrapperComponent.h diff --git a/build/macosx/platform_specific_code/juce_mac_CarbonViewWrapperComponent.h b/build/macosx/platform_specific_code/juce_mac_CarbonViewWrapperComponent.h new file mode 100644 index 0000000000..7b80418303 --- /dev/null +++ b/build/macosx/platform_specific_code/juce_mac_CarbonViewWrapperComponent.h @@ -0,0 +1,244 @@ +/* + ============================================================================== + + This file is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-7 by Raw Material Software ltd. + + ------------------------------------------------------------------------------ + + JUCE can be redistributed and/or modified under the terms of the + GNU General Public License, as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + JUCE is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JUCE; if not, visit www.gnu.org/licenses or write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + ------------------------------------------------------------------------------ + + If you'd like to release a closed-source product which uses JUCE, commercial + licenses are also available: visit www.rawmaterialsoftware.com/juce for + more information. + + ============================================================================== +*/ + +/** Creates a floating carbon window that can be used to hold a carbon UI. + + This is a handy class that's designed to be inlined where needed, e.g. + in the audio plugin hosting code. +*/ +class CarbonViewWrapperComponent : public Component, + public ComponentMovementWatcher, + public Timer +{ +public: + CarbonViewWrapperComponent() + : ComponentMovementWatcher (this), + wrapperWindow (0), + embeddedView (0), + recursiveResize (false) + { + } + + virtual ~CarbonViewWrapperComponent() + { + jassert (embeddedView == 0); // must call deleteWindow() in the subclass's destructor! + } + + virtual HIViewRef attachView (WindowRef windowRef, HIViewRef rootView) = 0; + virtual void removeView (HIViewRef embeddedView) = 0; + virtual void mouseDown (int x, int y) {} + virtual void paint() {} + + virtual bool getEmbeddedViewSize (int& w, int& h) + { + if (embeddedView == 0) + return false; + + HIRect bounds; + HIViewGetBounds (embeddedView, &bounds); + w = jmax (1, roundFloatToInt (bounds.size.width)); + h = jmax (1, roundFloatToInt (bounds.size.height)); + return true; + } + + void createWindow() + { + if (wrapperWindow == 0) + { + Rect r; + r.left = getScreenX(); + r.top = getScreenY(); + r.right = r.left + getWidth(); + r.bottom = r.top + getHeight(); + + CreateNewWindow (kDocumentWindowClass, + (WindowAttributes) (kWindowStandardHandlerAttribute | kWindowCompositingAttribute + | kWindowNoShadowAttribute | kWindowNoTitleBarAttribute), + &r, &wrapperWindow); + + jassert (wrapperWindow != 0); + if (wrapperWindow == 0) + return; + + NSWindow* carbonWindow = [[NSWindow alloc] initWithWindowRef: wrapperWindow]; + NSWindow* ownerWindow = [((NSView*) getWindowHandle()) window]; + + [ownerWindow addChildWindow: carbonWindow + ordered: NSWindowAbove]; + + embeddedView = attachView (wrapperWindow, HIViewGetRoot (wrapperWindow)); + + EventTypeSpec windowEventTypes[] = { { kEventClassWindow, kEventWindowGetClickActivation }, + { kEventClassWindow, kEventWindowHandleDeactivate } }; + + EventHandlerUPP upp = NewEventHandlerUPP (carbonEventCallback); + InstallWindowEventHandler (wrapperWindow, upp, + sizeof (windowEventTypes) / sizeof (EventTypeSpec), + windowEventTypes, this, &eventHandlerRef); + + setOurSizeToEmbeddedViewSize(); + setEmbeddedWindowToOurSize(); + } + } + + void deleteWindow() + { + removeView (embeddedView); + embeddedView = 0; + + if (wrapperWindow != 0) + { + RemoveEventHandler (eventHandlerRef); + DisposeWindow (wrapperWindow); + wrapperWindow = 0; + } + } + + //============================================================================== + void setOurSizeToEmbeddedViewSize() + { + int w, h; + if (getEmbeddedViewSize (w, h)) + { + if (w != getWidth() || h != getHeight()) + { + startTimer (50); + + setSize (w, h); + if (getParentComponent() != 0) + getParentComponent()->setSize (w, h); + } + else + { + startTimer (jlimit (50, 500, getTimerInterval() + 20)); + } + } + else + { + stopTimer(); + } + } + + void setEmbeddedWindowToOurSize() + { + if (! recursiveResize) + { + recursiveResize = true; + + if (embeddedView != 0) + { + HIRect r; + r.origin.x = 0; + r.origin.y = 0; + r.size.width = (float) getWidth(); + r.size.height = (float) getHeight(); + HIViewSetFrame (embeddedView, &r); + } + + if (wrapperWindow != 0) + { + Rect wr; + wr.left = getScreenX(); + wr.top = getScreenY(); + wr.right = wr.left + getWidth(); + wr.bottom = wr.top + getHeight(); + + SetWindowBounds (wrapperWindow, kWindowContentRgn, &wr); + ShowWindow (wrapperWindow); + } + + recursiveResize = false; + } + } + + void componentMovedOrResized (bool /*wasMoved*/, bool /*wasResized*/) + { + setEmbeddedWindowToOurSize(); + } + + void componentPeerChanged() + { + deleteWindow(); + createWindow(); + } + + void componentVisibilityChanged (Component&) + { + if (isShowing()) + createWindow(); + else + deleteWindow(); + + setEmbeddedWindowToOurSize(); + } + + void timerCallback() + { + setOurSizeToEmbeddedViewSize(); + } + + OSStatus carbonEventHandler (EventHandlerCallRef nextHandlerRef, + EventRef event) + { + switch (GetEventKind (event)) + { + case kEventWindowHandleDeactivate: + ActivateWindow (wrapperWindow, TRUE); + break; + + case kEventWindowGetClickActivation: + { + getTopLevelComponent()->toFront (false); + + ClickActivationResult howToHandleClick = kActivateAndHandleClick; + + SetEventParameter (event, kEventParamClickActivation, typeClickActivationResult, + sizeof (ClickActivationResult), &howToHandleClick); + } + break; + } + + return noErr; + } + + static pascal OSStatus carbonEventCallback (EventHandlerCallRef nextHandlerRef, + EventRef event, void* userData) + { + return ((CarbonViewWrapperComponent*) userData)->carbonEventHandler (nextHandlerRef, event); + } + +protected: + WindowRef wrapperWindow; + HIViewRef embeddedView; + bool recursiveResize; + + EventHandlerRef eventHandlerRef; +};