(R.id.godot_fragment_container)
+ gameView?.addOnLayoutChangeListener { v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom ->
+ gameView.getGlobalVisibleRect(gameViewSourceRectHint)
+ }
+ }
+
+ pipButton?.setOnClickListener { enterPiPMode() }
+
+ handleStartIntent(intent)
+ }
+
+ override fun onNewIntent(newIntent: Intent) {
+ super.onNewIntent(newIntent)
+ handleStartIntent(newIntent)
+ }
+
+ private fun handleStartIntent(intent: Intent) {
+ pipAvailable = intent.getBooleanExtra(EXTRA_PIP_AVAILABLE, pipAvailable)
+ updatePiPButtonVisibility()
+
+ val pipLaunchRequested = intent.getBooleanExtra(EXTRA_LAUNCH_IN_PIP, false)
+ if (pipLaunchRequested) {
+ enterPiPMode()
+ }
+ }
+
+ private fun updatePiPButtonVisibility() {
+ pipButton?.visibility = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && pipAvailable && !isInPictureInPictureMode) {
+ View.VISIBLE
+ } else {
+ View.GONE
+ }
+ }
+
+ private fun enterPiPMode() {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && pipAvailable) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ val builder = PictureInPictureParams.Builder().setSourceRectHint(gameViewSourceRectHint)
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+ builder.setSeamlessResizeEnabled(false)
+ }
+ setPictureInPictureParams(builder.build())
+ }
+
+ Log.v(TAG, "Entering PiP mode")
+ enterPictureInPictureMode()
+ }
+ }
+
+ override fun onPictureInPictureModeChanged(isInPictureInPictureMode: Boolean) {
+ super.onPictureInPictureModeChanged(isInPictureInPictureMode)
+ Log.v(TAG, "onPictureInPictureModeChanged: $isInPictureInPictureMode")
+ updatePiPButtonVisibility()
+ }
+
+ override fun onStop() {
+ super.onStop()
+
+ val isInPiPMode = Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && isInPictureInPictureMode
+ if (isInPiPMode && !isFinishing) {
+ // We get in this state when PiP is closed, so we terminate the activity.
+ finish()
+ }
+ }
+
+ override fun getGodotAppLayout() = R.layout.godot_game_layout
+
+ override fun getEditorId() = RUN_GAME_INFO.windowId
override fun overrideOrientationRequest() = false
diff --git a/platform/android/java/editor/src/main/res/drawable/ic_play_window_foreground.xml b/platform/android/java/editor/src/main/res/drawable/ic_play_window_foreground.xml
new file mode 100644
index 00000000000..41bc5475c8b
--- /dev/null
+++ b/platform/android/java/editor/src/main/res/drawable/ic_play_window_foreground.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
diff --git a/platform/android/java/editor/src/main/res/drawable/outline_fullscreen_exit_48.xml b/platform/android/java/editor/src/main/res/drawable/outline_fullscreen_exit_48.xml
new file mode 100644
index 00000000000..c8b5a15d195
--- /dev/null
+++ b/platform/android/java/editor/src/main/res/drawable/outline_fullscreen_exit_48.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
diff --git a/platform/android/java/editor/src/main/res/drawable/pip_button_activated_bg_drawable.xml b/platform/android/java/editor/src/main/res/drawable/pip_button_activated_bg_drawable.xml
new file mode 100644
index 00000000000..aeaa96ce547
--- /dev/null
+++ b/platform/android/java/editor/src/main/res/drawable/pip_button_activated_bg_drawable.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
diff --git a/platform/android/java/editor/src/main/res/drawable/pip_button_bg_drawable.xml b/platform/android/java/editor/src/main/res/drawable/pip_button_bg_drawable.xml
new file mode 100644
index 00000000000..e9b2959275f
--- /dev/null
+++ b/platform/android/java/editor/src/main/res/drawable/pip_button_bg_drawable.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/platform/android/java/editor/src/main/res/drawable/pip_button_default_bg_drawable.xml b/platform/android/java/editor/src/main/res/drawable/pip_button_default_bg_drawable.xml
new file mode 100644
index 00000000000..a8919689feb
--- /dev/null
+++ b/platform/android/java/editor/src/main/res/drawable/pip_button_default_bg_drawable.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
diff --git a/platform/android/java/editor/src/main/res/layout/godot_game_layout.xml b/platform/android/java/editor/src/main/res/layout/godot_game_layout.xml
new file mode 100644
index 00000000000..d53787c87e7
--- /dev/null
+++ b/platform/android/java/editor/src/main/res/layout/godot_game_layout.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
diff --git a/platform/android/java/editor/src/main/res/mipmap-anydpi-v26/ic_play_window.xml b/platform/android/java/editor/src/main/res/mipmap-anydpi-v26/ic_play_window.xml
new file mode 100644
index 00000000000..a3aabf2ee06
--- /dev/null
+++ b/platform/android/java/editor/src/main/res/mipmap-anydpi-v26/ic_play_window.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/platform/android/java/editor/src/main/res/mipmap-hdpi/ic_play_window.png b/platform/android/java/editor/src/main/res/mipmap-hdpi/ic_play_window.png
new file mode 100644
index 00000000000..a5ce40241f5
Binary files /dev/null and b/platform/android/java/editor/src/main/res/mipmap-hdpi/ic_play_window.png differ
diff --git a/platform/android/java/editor/src/main/res/mipmap-mdpi/ic_play_window.png b/platform/android/java/editor/src/main/res/mipmap-mdpi/ic_play_window.png
new file mode 100644
index 00000000000..147adb6127f
Binary files /dev/null and b/platform/android/java/editor/src/main/res/mipmap-mdpi/ic_play_window.png differ
diff --git a/platform/android/java/editor/src/main/res/mipmap-xhdpi/ic_play_window.png b/platform/android/java/editor/src/main/res/mipmap-xhdpi/ic_play_window.png
new file mode 100644
index 00000000000..0b1db1b9230
Binary files /dev/null and b/platform/android/java/editor/src/main/res/mipmap-xhdpi/ic_play_window.png differ
diff --git a/platform/android/java/editor/src/main/res/mipmap-xxhdpi/ic_play_window.png b/platform/android/java/editor/src/main/res/mipmap-xxhdpi/ic_play_window.png
new file mode 100644
index 00000000000..39d74503907
Binary files /dev/null and b/platform/android/java/editor/src/main/res/mipmap-xxhdpi/ic_play_window.png differ
diff --git a/platform/android/java/editor/src/main/res/mipmap-xxxhdpi/ic_play_window.png b/platform/android/java/editor/src/main/res/mipmap-xxxhdpi/ic_play_window.png
new file mode 100644
index 00000000000..b7a09a15b50
Binary files /dev/null and b/platform/android/java/editor/src/main/res/mipmap-xxxhdpi/ic_play_window.png differ
diff --git a/platform/android/java/editor/src/main/res/values/dimens.xml b/platform/android/java/editor/src/main/res/values/dimens.xml
index 98bfe401797..1e486872e6f 100644
--- a/platform/android/java/editor/src/main/res/values/dimens.xml
+++ b/platform/android/java/editor/src/main/res/values/dimens.xml
@@ -1,5 +1,5 @@
- 600dp
+ 640dp
1024dp
diff --git a/platform/android/java/editor/src/main/res/values/strings.xml b/platform/android/java/editor/src/main/res/values/strings.xml
index 909711ab180..0ad54ac3a13 100644
--- a/platform/android/java/editor/src/main/res/values/strings.xml
+++ b/platform/android/java/editor/src/main/res/values/strings.xml
@@ -1,4 +1,6 @@
+ Godot Play window
Missing storage access permission!
+ Button used to toggle picture-in-picture mode for the Play window
diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotActivity.kt b/platform/android/java/lib/src/org/godotengine/godot/GodotActivity.kt
index 913e3d04c5d..474c6e9b2fb 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/GodotActivity.kt
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotActivity.kt
@@ -52,8 +52,6 @@ abstract class GodotActivity : FragmentActivity(), GodotHost {
companion object {
private val TAG = GodotActivity::class.java.simpleName
- @JvmStatic
- protected val EXTRA_FORCE_QUIT = "force_quit_requested"
@JvmStatic
protected val EXTRA_NEW_LAUNCH = "new_launch_requested"
}
@@ -128,12 +126,6 @@ abstract class GodotActivity : FragmentActivity(), GodotHost {
}
private fun handleStartIntent(intent: Intent, newLaunch: Boolean) {
- val forceQuitRequested = intent.getBooleanExtra(EXTRA_FORCE_QUIT, false)
- if (forceQuitRequested) {
- Log.d(TAG, "Force quit requested, terminating..")
- ProcessPhoenix.forceQuit(this)
- return
- }
if (!newLaunch) {
val newLaunchRequested = intent.getBooleanExtra(EXTRA_NEW_LAUNCH, false)
if (newLaunchRequested) {
diff --git a/platform/android/java/lib/src/org/godotengine/godot/utils/ProcessPhoenix.java b/platform/android/java/lib/src/org/godotengine/godot/utils/ProcessPhoenix.java
index b1bce45fbba..d9afdf90b13 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/utils/ProcessPhoenix.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/utils/ProcessPhoenix.java
@@ -24,6 +24,7 @@ package org.godotengine.godot.utils;
import android.app.Activity;
import android.app.ActivityManager;
+import android.app.ActivityOptions;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
@@ -44,6 +45,9 @@ import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
*/
public final class ProcessPhoenix extends Activity {
private static final String KEY_RESTART_INTENTS = "phoenix_restart_intents";
+ // -- GODOT start --
+ private static final String KEY_RESTART_ACTIVITY_OPTIONS = "phoenix_restart_activity_options";
+ // -- GODOT end --
private static final String KEY_MAIN_PROCESS_PID = "phoenix_main_process_pid";
/**
@@ -56,12 +60,23 @@ public final class ProcessPhoenix extends Activity {
triggerRebirth(context, getRestartIntent(context));
}
+ // -- GODOT start --
/**
* Call to restart the application process using the specified intents.
*
* Behavior of the current process after invoking this method is undefined.
*/
public static void triggerRebirth(Context context, Intent... nextIntents) {
+ triggerRebirth(context, null, nextIntents);
+ }
+
+ /**
+ * Call to restart the application process using the specified intents launched with the given
+ * {@link ActivityOptions}.
+ *
+ * Behavior of the current process after invoking this method is undefined.
+ */
+ public static void triggerRebirth(Context context, Bundle activityOptions, Intent... nextIntents) {
if (nextIntents.length < 1) {
throw new IllegalArgumentException("intents cannot be empty");
}
@@ -72,10 +87,12 @@ public final class ProcessPhoenix extends Activity {
intent.addFlags(FLAG_ACTIVITY_NEW_TASK); // In case we are called with non-Activity context.
intent.putParcelableArrayListExtra(KEY_RESTART_INTENTS, new ArrayList<>(Arrays.asList(nextIntents)));
intent.putExtra(KEY_MAIN_PROCESS_PID, Process.myPid());
+ if (activityOptions != null) {
+ intent.putExtra(KEY_RESTART_ACTIVITY_OPTIONS, activityOptions);
+ }
context.startActivity(intent);
}
- // -- GODOT start --
/**
* Finish the activity and kill its process
*/
@@ -112,9 +129,11 @@ public final class ProcessPhoenix extends Activity {
super.onCreate(savedInstanceState);
// -- GODOT start --
- ArrayList intents = getIntent().getParcelableArrayListExtra(KEY_RESTART_INTENTS);
- startActivities(intents.toArray(new Intent[intents.size()]));
- forceQuit(this, getIntent().getIntExtra(KEY_MAIN_PROCESS_PID, -1));
+ Intent launchIntent = getIntent();
+ ArrayList intents = launchIntent.getParcelableArrayListExtra(KEY_RESTART_INTENTS);
+ Bundle activityOptions = launchIntent.getBundleExtra(KEY_RESTART_ACTIVITY_OPTIONS);
+ startActivities(intents.toArray(new Intent[intents.size()]), activityOptions);
+ forceQuit(this, launchIntent.getIntExtra(KEY_MAIN_PROCESS_PID, -1));
// -- GODOT end --
}