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.

192 lines
5.5KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2017 - ROLI Ltd.
  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 5 End-User License
  8. Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
  9. 27th April 2017).
  10. End User License Agreement: www.juce.com/juce-5-licence
  11. Privacy Policy: www.juce.com/juce-5-privacy-policy
  12. Or: You may also use this code under the terms of the GPL v3 (see
  13. www.gnu.org/licenses).
  14. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  15. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  16. DISCLAIMED.
  17. ==============================================================================
  18. */
  19. namespace juce
  20. {
  21. class AndroidViewComponent::Pimpl : public ComponentMovementWatcher
  22. {
  23. public:
  24. Pimpl (jobject v, Component& comp, bool makeSiblingRatherThanChild = false)
  25. : ComponentMovementWatcher (&comp),
  26. view (v),
  27. owner (comp),
  28. embedAsSiblingRatherThanChild (makeSiblingRatherThanChild)
  29. {
  30. if (owner.isShowing())
  31. componentPeerChanged();
  32. }
  33. ~Pimpl()
  34. {
  35. removeFromParent();
  36. }
  37. void componentMovedOrResized (bool /*wasMoved*/, bool /*wasResized*/) override
  38. {
  39. auto* topComp = owner.getTopLevelComponent();
  40. if (topComp->getPeer() != nullptr)
  41. {
  42. auto pos = topComp->getLocalPoint (&owner, Point<int>());
  43. Rectangle<int> r (pos.x, pos.y, owner.getWidth(), owner.getHeight());
  44. r *= Desktop::getInstance().getDisplays().getMainDisplay().scale;
  45. getEnv()->CallVoidMethod (view, AndroidView.layout, r.getX(), r.getY(),
  46. r.getRight(), r.getBottom());
  47. }
  48. }
  49. void componentPeerChanged() override
  50. {
  51. auto* peer = owner.getPeer();
  52. if (currentPeer != peer)
  53. {
  54. removeFromParent();
  55. currentPeer = peer;
  56. addToParent();
  57. }
  58. enum
  59. {
  60. VISIBLE = 0,
  61. INVISIBLE = 4
  62. };
  63. getEnv()->CallVoidMethod (view, AndroidView.setVisibility, owner.isShowing() ? VISIBLE : INVISIBLE);
  64. }
  65. void componentVisibilityChanged() override
  66. {
  67. componentPeerChanged();
  68. }
  69. void componentBroughtToFront (Component& comp) override
  70. {
  71. ComponentMovementWatcher::componentBroughtToFront (comp);
  72. // Ensure that the native component doesn't get obscured.
  73. if (embedAsSiblingRatherThanChild)
  74. getEnv()->CallVoidMethod (view, AndroidView.bringToFront);
  75. }
  76. Rectangle<int> getViewBounds() const
  77. {
  78. auto* env = getEnv();
  79. int width = env->CallIntMethod (view, AndroidView.getWidth);
  80. int height = env->CallIntMethod (view, AndroidView.getHeight);
  81. return Rectangle<int> (width, height);
  82. }
  83. GlobalRef view;
  84. private:
  85. void addToParent()
  86. {
  87. if (currentPeer != nullptr)
  88. {
  89. jobject peerView = (jobject) currentPeer->getNativeHandle();
  90. // NB: Assuming a parent is always of ViewGroup type
  91. auto* env = getEnv();
  92. if (embedAsSiblingRatherThanChild)
  93. {
  94. // This is a workaround for a bug in a web browser component where
  95. // scrolling would be very slow and occassionally would scroll in
  96. // opposite direction to dragging direction. In normal circumstances,
  97. // the native view should be a child of peerView instead.
  98. auto parentView = LocalRef<jobject> (env->CallObjectMethod (peerView, AndroidView.getParent));
  99. env->CallVoidMethod (parentView, AndroidViewGroup.addView, view.get());
  100. }
  101. else
  102. {
  103. env->CallVoidMethod (peerView, AndroidViewGroup.addView, view.get());
  104. }
  105. componentMovedOrResized (false, false);
  106. }
  107. }
  108. void removeFromParent()
  109. {
  110. auto* env = getEnv();
  111. auto parentView = env->CallObjectMethod (view, AndroidView.getParent);
  112. if (parentView != 0)
  113. {
  114. // Assuming a parent is always of ViewGroup type
  115. env->CallVoidMethod (parentView, AndroidViewGroup.removeView, view.get());
  116. }
  117. }
  118. Component& owner;
  119. bool embedAsSiblingRatherThanChild;
  120. ComponentPeer* currentPeer = nullptr;
  121. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Pimpl)
  122. };
  123. //==============================================================================
  124. AndroidViewComponent::AndroidViewComponent (bool makeSiblingRatherThanChild)
  125. : embedAsSiblingRatherThanChild (makeSiblingRatherThanChild)
  126. {
  127. }
  128. AndroidViewComponent::~AndroidViewComponent() {}
  129. void AndroidViewComponent::setView (void* view)
  130. {
  131. if (view != getView())
  132. {
  133. pimpl.reset();
  134. if (view != nullptr)
  135. pimpl.reset (new Pimpl ((jobject) view, *this, embedAsSiblingRatherThanChild));
  136. }
  137. }
  138. void* AndroidViewComponent::getView() const
  139. {
  140. return pimpl == nullptr ? nullptr : (void*) pimpl->view;
  141. }
  142. void AndroidViewComponent::resizeToFitView()
  143. {
  144. if (pimpl != nullptr)
  145. setBounds (pimpl->getViewBounds());
  146. }
  147. void AndroidViewComponent::paint (Graphics&) {}
  148. } // namespace juce