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.

206 lines
6.2KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2022 - Raw Material Software Limited
  5. JUCE is an open source library subject to commercial or open-source
  6. licensing.
  7. By using JUCE, you agree to the terms of both the JUCE 7 End-User License
  8. Agreement and JUCE Privacy Policy.
  9. End User License Agreement: www.juce.com/juce-7-licence
  10. Privacy Policy: www.juce.com/juce-privacy-policy
  11. Or: You may also use this code under the terms of the GPL v3 (see
  12. www.gnu.org/licenses).
  13. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  14. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  15. DISCLAIMED.
  16. ==============================================================================
  17. */
  18. namespace juce
  19. {
  20. class NSViewAttachment : public ReferenceCountedObject,
  21. public ComponentMovementWatcher
  22. {
  23. public:
  24. NSViewAttachment (NSView* v, Component& comp)
  25. : ComponentMovementWatcher (&comp),
  26. view (v), owner (comp)
  27. {
  28. [view retain];
  29. [view setPostsFrameChangedNotifications: YES];
  30. updateAlpha();
  31. if (owner.isShowing())
  32. componentPeerChanged();
  33. }
  34. ~NSViewAttachment() override
  35. {
  36. removeFromParent();
  37. [view release];
  38. }
  39. void componentMovedOrResized (Component& comp, bool wasMoved, bool wasResized) override
  40. {
  41. ComponentMovementWatcher::componentMovedOrResized (comp, wasMoved, wasResized);
  42. // The ComponentMovementWatcher version of this method avoids calling
  43. // us when the top-level comp is resized, but if we're listening to the
  44. // top-level comp we still want the NSView to track its size.
  45. if (comp.isOnDesktop() && wasResized)
  46. componentMovedOrResized (wasMoved, wasResized);
  47. }
  48. void componentMovedOrResized (bool /*wasMoved*/, bool /*wasResized*/) override
  49. {
  50. if (auto* peer = owner.getTopLevelComponent()->getPeer())
  51. {
  52. const auto newArea = peer->getAreaCoveredBy (owner);
  53. if (convertToRectInt ([view frame]) != newArea)
  54. [view setFrame: makeNSRect (newArea)];
  55. }
  56. }
  57. void componentPeerChanged() override
  58. {
  59. auto* peer = owner.getPeer();
  60. if (std::exchange (currentPeer, peer) != peer)
  61. {
  62. if (peer != nullptr)
  63. {
  64. auto peerView = (NSView*) peer->getNativeHandle();
  65. [peerView addSubview: view];
  66. if (@available (macOS 10.10, *))
  67. {
  68. previousAccessibilityParent = [view accessibilityParent];
  69. [view setAccessibilityParent:static_cast<id> (owner.getAccessibilityHandler()->getNativeImplementation())];
  70. }
  71. componentMovedOrResized (false, false);
  72. }
  73. else
  74. {
  75. removeFromParent();
  76. }
  77. }
  78. [view setHidden: ! owner.isShowing()];
  79. }
  80. void componentVisibilityChanged() override
  81. {
  82. componentPeerChanged();
  83. }
  84. void updateAlpha()
  85. {
  86. [view setAlphaValue: (CGFloat) owner.getAlpha()];
  87. }
  88. NSView* const view;
  89. using Ptr = ReferenceCountedObjectPtr<NSViewAttachment>;
  90. private:
  91. Component& owner;
  92. ComponentPeer* currentPeer = nullptr;
  93. NSViewFrameWatcher frameWatcher { view, [this] { owner.childBoundsChanged (nullptr); } };
  94. id previousAccessibilityParent = nil;
  95. void removeFromParent()
  96. {
  97. if (@available (macOS 10.10, *))
  98. if (previousAccessibilityParent != nil)
  99. [view setAccessibilityParent: previousAccessibilityParent];
  100. if ([view superview] != nil)
  101. [view removeFromSuperview]; // Must be careful not to call this unless it's required - e.g. some Apple AU views
  102. // override the call and use it as a sign that they're being deleted, which breaks everything..
  103. }
  104. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (NSViewAttachment)
  105. };
  106. //==============================================================================
  107. NSViewComponent::NSViewComponent() = default;
  108. NSViewComponent::~NSViewComponent()
  109. {
  110. AccessibilityHandler::setNativeChildForComponent (*this, nullptr);
  111. }
  112. void NSViewComponent::setView (void* view)
  113. {
  114. if (view != getView())
  115. {
  116. auto old = attachment;
  117. attachment = nullptr;
  118. if (view != nullptr)
  119. attachment = attachViewToComponent (*this, view);
  120. old = nullptr;
  121. AccessibilityHandler::setNativeChildForComponent (*this, getView());
  122. }
  123. }
  124. void* NSViewComponent::getView() const
  125. {
  126. return attachment != nullptr ? static_cast<NSViewAttachment*> (attachment.get())->view
  127. : nullptr;
  128. }
  129. void NSViewComponent::resizeToFitView()
  130. {
  131. if (attachment != nullptr)
  132. {
  133. auto* view = static_cast<NSViewAttachment*> (attachment.get())->view;
  134. auto r = [view frame];
  135. setBounds (Rectangle<int> ((int) r.size.width, (int) r.size.height));
  136. if (auto* peer = getTopLevelComponent()->getPeer())
  137. {
  138. const auto position = peer->getAreaCoveredBy (*this).getPosition();
  139. [view setFrameOrigin: convertToCGPoint (position)];
  140. }
  141. }
  142. }
  143. void NSViewComponent::resizeViewToFit()
  144. {
  145. if (attachment != nullptr)
  146. static_cast<NSViewAttachment*> (attachment.get())->componentMovedOrResized (true, true);
  147. }
  148. void NSViewComponent::paint (Graphics&) {}
  149. void NSViewComponent::alphaChanged()
  150. {
  151. if (attachment != nullptr)
  152. (static_cast<NSViewAttachment*> (attachment.get()))->updateAlpha();
  153. }
  154. ReferenceCountedObject* NSViewComponent::attachViewToComponent (Component& comp, void* view)
  155. {
  156. return new NSViewAttachment ((NSView*) view, comp);
  157. }
  158. std::unique_ptr<AccessibilityHandler> NSViewComponent::createAccessibilityHandler()
  159. {
  160. return std::make_unique<AccessibilityHandler> (*this, AccessibilityRole::group);
  161. }
  162. } // namespace juce