diff --git a/modules/juce_core/native/juce_JNIHelpers_android.h b/modules/juce_core/native/juce_JNIHelpers_android.h index 5856ab57ef..ad2b6b950a 100644 --- a/modules/juce_core/native/juce_JNIHelpers_android.h +++ b/modules/juce_core/native/juce_JNIHelpers_android.h @@ -350,6 +350,7 @@ DECLARE_JNI_CLASS (AndroidContext, "android/content/Context") METHOD (startActivityForResult, "startActivityForResult", "(Landroid/content/Intent;I)V") \ METHOD (getFragmentManager, "getFragmentManager", "()Landroid/app/FragmentManager;") \ METHOD (setContentView, "setContentView", "(Landroid/view/View;)V") \ + METHOD (addContentView, "addContentView", "(Landroid/view/View;Landroid/view/ViewGroup$LayoutParams;)V") \ METHOD (getActionBar, "getActionBar", "()Landroid/app/ActionBar;") \ METHOD (getWindow, "getWindow", "()Landroid/view/Window;") \ METHOD (isInMultiWindowMode, "isInMultiWindowMode", "()Z") \ @@ -679,7 +680,8 @@ DECLARE_JNI_CLASS (AndroidWindow, "android/view/Window") #undef JNI_CLASS_MEMBERS #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \ - METHOD (getDefaultDisplay, "getDefaultDisplay", "()Landroid/view/Display;") + METHOD (getDefaultDisplay, "getDefaultDisplay", "()Landroid/view/Display;") \ + METHOD (removeViewImmediate, "removeViewImmediate", "(Landroid/view/View;)V") \ DECLARE_JNI_CLASS (AndroidWindowManager, "android/view/WindowManager") #undef JNI_CLASS_MEMBERS diff --git a/modules/juce_gui_basics/native/juce_Windowing_android.cpp b/modules/juce_gui_basics/native/juce_Windowing_android.cpp index 1c0c29b964..7a929d9cef 100644 --- a/modules/juce_gui_basics/native/juce_Windowing_android.cpp +++ b/modules/juce_gui_basics/native/juce_Windowing_android.cpp @@ -1319,10 +1319,10 @@ public: getAppContext().get(), (jboolean) component.isOpaque(), (jlong) this))); - if (nativeViewHandle != nullptr) - { - viewGroupIsWindow = false; + userDidSupplyParent = nativeViewHandle != nullptr; + if (userDidSupplyParent) + { // we don't know if the user is holding on to a local ref to this, so // explicitly create a new one auto nativeView = LocalRef (env->NewLocalRef (static_cast (nativeViewHandle))); @@ -1349,8 +1349,6 @@ public: } else { - viewGroupIsWindow = true; - LocalRef viewLayoutParams { env->NewObject (AndroidLayoutParams, AndroidLayoutParams.create, -2, -2) }; env->CallVoidMethod (view.get(), AndroidView.setLayoutParams, viewLayoutParams.get()); @@ -1426,16 +1424,57 @@ public: env->CallVoidMethod (view, ComponentPeerView.clear); frontWindow = nullptr; - GlobalRef localView (view); - GlobalRef localViewGroup (viewGroup); + removeView(); + } - callOnMessageThread ([env, localView, localViewGroup] + static void removeViewFromActivity (jobject localView) + { + if (localView == nullptr) + return; + + auto* env = getEnv(); + + if (LocalRef parent { env->CallObjectMethod (localView, AndroidView.getParent) }) + env->CallVoidMethod (parent, AndroidViewGroup.removeView, localView); + } + + void removeView() + { + auto* env = getEnv(); + + if (userDidSupplyParent) { - if (env->IsInstanceOf (localViewGroup.get(), AndroidActivity)) - env->CallVoidMethod (localViewGroup.get(), AndroidActivity.setContentView, nullptr); - else - env->CallVoidMethod (localViewGroup.get(), AndroidViewManager.removeView, localView.get()); - }); + if (env->IsInstanceOf (viewGroup, AndroidActivity)) + { + removeViewFromActivity (view); + return; + } + + if (env->IsInstanceOf (viewGroup, AndroidViewGroup)) + { + env->CallVoidMethod (viewGroup, AndroidViewGroup.removeView, view.get()); + return; + } + + // The parent was not an activity or view group? + jassertfalse; + return; + } + + if (fullScreen) + { + removeViewFromActivity (view); + return; + } + + if (env->IsInstanceOf (viewGroup, AndroidWindowManager)) + { + env->CallVoidMethod (viewGroup, AndroidWindowManager.removeViewImmediate, view.get()); + return; + } + + // The view's owner didn't have the expected type! + jassertfalse; } void* getNativeHandle() const override @@ -1464,33 +1503,67 @@ public: if (MessageManager::getInstance()->isThisTheMessageThread()) { - fullScreen = isNowFullScreen; + auto* env = getEnv(); - if (viewGroup != nullptr && viewGroupIsWindow) + if (fullScreen != isNowFullScreen && ! userDidSupplyParent) { - auto* env = getEnv(); + removeView(); + + fullScreen = isNowFullScreen; LocalRef windowLayoutParams { env->NewObject (AndroidWindowManagerLayoutParams, AndroidWindowManagerLayoutParams.createDefault) }; setUpLayoutParams (env, windowLayoutParams.get(), bounds); - env->CallVoidMethod (viewGroup.get(), - AndroidViewManager.updateViewLayout, - view.get(), - windowLayoutParams.get()); + if (isNowFullScreen) + { + if (auto activity = getCurrentOrMainActivity()) + env->CallVoidMethod (activity, AndroidActivity.addContentView, view.get(), windowLayoutParams.get()); + } + else if (env->IsInstanceOf (viewGroup, AndroidViewManager)) + { + env->CallVoidMethod (viewGroup.get(), + AndroidViewManager.addView, + view.get(), + windowLayoutParams.get()); + } + else + { + // Not fullscreen but the viewgroup isn't a viewmanager/windowmanager instance + jassertfalse; + } setNavBarsHidden (navBarsHidden); } - else + else if (! fullScreen) { - view.callVoidMethod (AndroidView.layout, - bounds.getX(), - bounds.getY(), - bounds.getRight(), - bounds.getBottom()); + if (viewGroup != nullptr && ! userDidSupplyParent) + { + LocalRef windowLayoutParams { env->NewObject (AndroidWindowManagerLayoutParams, + AndroidWindowManagerLayoutParams.createDefault) }; + setUpLayoutParams (env, windowLayoutParams.get(), bounds); + + env->CallVoidMethod (viewGroup.get(), + AndroidViewManager.updateViewLayout, + view.get(), + windowLayoutParams.get()); + + setNavBarsHidden (navBarsHidden); + } + else + { + view.callVoidMethod (AndroidView.layout, + bounds.getX(), + bounds.getY(), + bounds.getRight(), + bounds.getBottom()); + + } } + + fullScreen = isNowFullScreen; } else { @@ -2109,7 +2182,7 @@ private: if (! env->IsInstanceOf (layoutParams, AndroidWindowManagerLayoutParams)) return; - // When viewGroupIsWindow is true, we're laying out the window within the bounds + // When userDidSupplyParent is false, we're laying out the window within the bounds // provided to the activity, and the userRect is in global screen space. // For fullscreen windows, it's easiest to ask Android to size the view // appropriately by matching the parent view. @@ -2446,7 +2519,7 @@ private: static constexpr jint LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES = 0x1; GlobalRef view, viewGroup, buffer, activityWindow; - bool viewGroupIsWindow = false, fullScreen = false, navBarsHidden = false; + bool userDidSupplyParent = false, fullScreen = false, navBarsHidden = false; int sizeAllocated = 0; //==============================================================================