The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

297 lines
11KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2013 - Raw Material Software Ltd.
  5. Permission is granted to use this software under the terms of either:
  6. a) the GPL v2 (or any later version)
  7. b) the Affero GPL v3
  8. Details of these licenses can be found at: www.gnu.org/licenses
  9. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  10. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  11. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  12. ------------------------------------------------------------------------------
  13. To release a closed-source product which uses JUCE, commercial licenses are
  14. available: visit www.juce.com for more information.
  15. ==============================================================================
  16. */
  17. // Your project must contain an AppConfig.h file with your project-specific settings in it,
  18. // and your header search path must make it accessible to the module's files.
  19. #include "AppConfig.h"
  20. #include "../utility/juce_CheckSettingMacros.h"
  21. #if JucePlugin_Build_VST || JucePlugin_Build_VST3
  22. #define JUCE_MAC_WINDOW_VISIBITY_BODGE 1
  23. #include "../utility/juce_IncludeSystemHeaders.h"
  24. #include "../utility/juce_IncludeModuleHeaders.h"
  25. #include "../utility/juce_FakeMouseMoveGenerator.h"
  26. #include "../utility/juce_CarbonVisibility.h"
  27. //==============================================================================
  28. namespace juce
  29. {
  30. #if ! JUCE_64BIT
  31. void updateEditorCompBounds (Component*);
  32. void updateEditorCompBounds (Component* comp)
  33. {
  34. HIViewRef dummyView = (HIViewRef) (void*) (pointer_sized_int)
  35. comp->getProperties() ["dummyViewRef"].toString().getHexValue64();
  36. HIRect r;
  37. HIViewGetFrame (dummyView, &r);
  38. HIViewRef root;
  39. HIViewFindByID (HIViewGetRoot (HIViewGetWindow (dummyView)), kHIViewWindowContentID, &root);
  40. HIViewConvertRect (&r, HIViewGetSuperview (dummyView), root);
  41. Rect windowPos;
  42. GetWindowBounds (HIViewGetWindow (dummyView), kWindowContentRgn, &windowPos);
  43. comp->setTopLeftPosition ((int) (windowPos.left + r.origin.x),
  44. (int) (windowPos.top + r.origin.y));
  45. }
  46. static pascal OSStatus viewBoundsChangedEvent (EventHandlerCallRef, EventRef, void* user)
  47. {
  48. updateEditorCompBounds ((Component*) user);
  49. return noErr;
  50. }
  51. #endif
  52. //==============================================================================
  53. void initialiseMac();
  54. void initialiseMac()
  55. {
  56. #if ! JUCE_64BIT
  57. NSApplicationLoad();
  58. #endif
  59. }
  60. void* attachComponentToWindowRef (Component* comp, void* parentWindowOrView, bool isNSView);
  61. void* attachComponentToWindowRef (Component* comp, void* parentWindowOrView, bool isNSView)
  62. {
  63. JUCE_AUTORELEASEPOOL
  64. {
  65. #if ! JUCE_64BIT
  66. if (! isNSView)
  67. {
  68. NSWindow* hostWindow = [[NSWindow alloc] initWithWindowRef: parentWindowOrView];
  69. [hostWindow retain];
  70. [hostWindow setCanHide: YES];
  71. [hostWindow setReleasedWhenClosed: YES];
  72. HIViewRef parentView = 0;
  73. WindowAttributes attributes;
  74. GetWindowAttributes ((WindowRef) parentWindowOrView, &attributes);
  75. if ((attributes & kWindowCompositingAttribute) != 0)
  76. {
  77. HIViewRef root = HIViewGetRoot ((WindowRef) parentWindowOrView);
  78. HIViewFindByID (root, kHIViewWindowContentID, &parentView);
  79. if (parentView == 0)
  80. parentView = root;
  81. }
  82. else
  83. {
  84. GetRootControl ((WindowRef) parentWindowOrView, (ControlRef*) &parentView);
  85. if (parentView == 0)
  86. CreateRootControl ((WindowRef) parentWindowOrView, (ControlRef*) &parentView);
  87. }
  88. // It seems that the only way to successfully position our overlaid window is by putting a dummy
  89. // HIView into the host's carbon window, and then catching events to see when it gets repositioned
  90. HIViewRef dummyView = 0;
  91. HIImageViewCreate (0, &dummyView);
  92. HIRect r = { {0, 0}, { (float) comp->getWidth(), (float) comp->getHeight()} };
  93. HIViewSetFrame (dummyView, &r);
  94. HIViewAddSubview (parentView, dummyView);
  95. comp->getProperties().set ("dummyViewRef", String::toHexString ((pointer_sized_int) (void*) dummyView));
  96. EventHandlerRef ref;
  97. const EventTypeSpec kControlBoundsChangedEvent = { kEventClassControl, kEventControlBoundsChanged };
  98. InstallEventHandler (GetControlEventTarget (dummyView), NewEventHandlerUPP (viewBoundsChangedEvent), 1, &kControlBoundsChangedEvent, (void*) comp, &ref);
  99. comp->getProperties().set ("boundsEventRef", String::toHexString ((pointer_sized_int) (void*) ref));
  100. updateEditorCompBounds (comp);
  101. #if ! JucePlugin_EditorRequiresKeyboardFocus
  102. comp->addToDesktop (ComponentPeer::windowIsTemporary | ComponentPeer::windowIgnoresKeyPresses);
  103. #else
  104. comp->addToDesktop (ComponentPeer::windowIsTemporary);
  105. #endif
  106. comp->setVisible (true);
  107. comp->toFront (false);
  108. NSView* pluginView = (NSView*) comp->getWindowHandle();
  109. NSWindow* pluginWindow = [pluginView window];
  110. [pluginWindow setExcludedFromWindowsMenu: YES];
  111. [pluginWindow setCanHide: YES];
  112. [hostWindow addChildWindow: pluginWindow
  113. ordered: NSWindowAbove];
  114. [hostWindow orderFront: nil];
  115. [pluginWindow orderFront: nil];
  116. attachWindowHidingHooks (comp, (WindowRef) parentWindowOrView, hostWindow);
  117. return hostWindow;
  118. }
  119. #endif
  120. (void) isNSView;
  121. NSView* parentView = [(NSView*) parentWindowOrView retain];
  122. #if JucePlugin_EditorRequiresKeyboardFocus
  123. comp->addToDesktop (0, parentView);
  124. #else
  125. comp->addToDesktop (ComponentPeer::windowIgnoresKeyPresses, parentView);
  126. #endif
  127. // (this workaround is because Wavelab provides a zero-size parent view..)
  128. if ([parentView frame].size.height == 0)
  129. [((NSView*) comp->getWindowHandle()) setFrameOrigin: NSZeroPoint];
  130. comp->setVisible (true);
  131. comp->toFront (false);
  132. [[parentView window] setAcceptsMouseMovedEvents: YES];
  133. return parentView;
  134. }
  135. }
  136. void detachComponentFromWindowRef (Component* comp, void* window, bool isNSView);
  137. void detachComponentFromWindowRef (Component* comp, void* window, bool isNSView)
  138. {
  139. JUCE_AUTORELEASEPOOL
  140. {
  141. #if ! JUCE_64BIT
  142. if (! isNSView)
  143. {
  144. EventHandlerRef ref = (EventHandlerRef) (void*) (pointer_sized_int)
  145. comp->getProperties() ["boundsEventRef"].toString().getHexValue64();
  146. RemoveEventHandler (ref);
  147. removeWindowHidingHooks (comp);
  148. HIViewRef dummyView = (HIViewRef) (void*) (pointer_sized_int)
  149. comp->getProperties() ["dummyViewRef"].toString().getHexValue64();
  150. if (HIViewIsValid (dummyView))
  151. CFRelease (dummyView);
  152. NSWindow* hostWindow = (NSWindow*) window;
  153. NSView* pluginView = (NSView*) comp->getWindowHandle();
  154. NSWindow* pluginWindow = [pluginView window];
  155. [pluginView retain];
  156. [hostWindow removeChildWindow: pluginWindow];
  157. [pluginWindow close];
  158. comp->removeFromDesktop();
  159. [pluginView release];
  160. [hostWindow release];
  161. static bool needToRunMessageLoop = ! getHostType().isReaper();
  162. // The event loop needs to be run between closing the window and deleting the plugin,
  163. // presumably to let the cocoa objects get tidied up. Leaving out this line causes crashes
  164. // in Live when you delete the plugin with its window open.
  165. // (Doing it this way rather than using a single longer timout means that we can guarantee
  166. // how many messages will be dispatched, which seems to be vital in Reaper)
  167. if (needToRunMessageLoop)
  168. for (int i = 20; --i >= 0;)
  169. MessageManager::getInstance()->runDispatchLoopUntil (1);
  170. return;
  171. }
  172. #endif
  173. (void) isNSView;
  174. comp->removeFromDesktop();
  175. [(id) window release];
  176. }
  177. }
  178. void setNativeHostWindowSize (void* window, Component* component, int newWidth, int newHeight, bool isNSView);
  179. void setNativeHostWindowSize (void* window, Component* component, int newWidth, int newHeight, bool isNSView)
  180. {
  181. JUCE_AUTORELEASEPOOL
  182. {
  183. #if ! JUCE_64BIT
  184. if (! isNSView)
  185. {
  186. if (HIViewRef dummyView = (HIViewRef) (void*) (pointer_sized_int)
  187. component->getProperties() ["dummyViewRef"].toString().getHexValue64())
  188. {
  189. HIRect frameRect;
  190. HIViewGetFrame (dummyView, &frameRect);
  191. frameRect.size.width = newWidth;
  192. frameRect.size.height = newHeight;
  193. HIViewSetFrame (dummyView, &frameRect);
  194. }
  195. return;
  196. }
  197. #endif
  198. (void) isNSView;
  199. if (NSView* hostView = (NSView*) window)
  200. {
  201. const int dx = newWidth - component->getWidth();
  202. const int dy = newHeight - component->getHeight();
  203. NSRect r = [hostView frame];
  204. r.size.width += dx;
  205. r.size.height += dy;
  206. r.origin.y -= dy;
  207. [hostView setFrame: r];
  208. }
  209. }
  210. }
  211. void checkWindowVisibility (void* window, Component* comp, bool isNSView);
  212. void checkWindowVisibility (void* window, Component* comp, bool isNSView)
  213. {
  214. (void) window; (void) comp; (void) isNSView;
  215. #if ! JUCE_64BIT
  216. if (! isNSView)
  217. comp->setVisible ([((NSWindow*) window) isVisible]);
  218. #endif
  219. }
  220. bool forwardCurrentKeyEventToHost (Component* comp, bool isNSView);
  221. bool forwardCurrentKeyEventToHost (Component* comp, bool isNSView)
  222. {
  223. #if ! JUCE_64BIT
  224. if (! isNSView)
  225. {
  226. NSWindow* win = [(NSView*) comp->getWindowHandle() window];
  227. [[win parentWindow] makeKeyWindow];
  228. repostCurrentNSEvent();
  229. return true;
  230. }
  231. #endif
  232. (void) comp; (void) isNSView;
  233. return false;
  234. }
  235. } // (juce namespace)
  236. #endif