1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00

Android: Set fullscreen peers as content views, instead of floating windows

This is intended to fix an issue when running Android 33 or 34 in desktop/windowing mode.
This commit is contained in:
reuk 2025-07-02 20:35:31 +01:00
parent 5eaa1a9c55
commit 5298225ee7
No known key found for this signature in database
2 changed files with 104 additions and 29 deletions

View file

@ -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

View file

@ -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<jobject> (env->NewLocalRef (static_cast<jobject> (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<jobject> 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;
//==============================================================================