mirror of
https://github.com/azahar-emu/azahar.git
synced 2026-11-13 09:39:44 +01:00
android: Fix black screen when relaunching a game from a shortcut (#2656)
* android: Fix black screen when relaunching a game from a shortcut onNewIntent stopped emulation and then called setGraph with an equal graph, which keeps the old emulation fragment, so nothing restarted. A shortcut for the game that is already running now just brings it back. A shortcut for a different game replaces the emulation fragment so the new game boots. The old fragment no longer clears the activity registration the new one already set, and its stats overlay updater stops with its view instead of resetting the new game's stats. After HOME the second screen surface comes back after the main one, so the emulation thread waits briefly for it instead of crashing. Fixes #2329 * android: Update EmulationFragment.kt license header to GPLv3
This commit is contained in:
1 parent
f718556525
commit
7ea9cee479
3 files changed
+43
-2
No files matched your search
@@ -27,6 +27,7 @@ import androidx.core.os.BundleCompat
|
||||
import androidx.core.view.WindowCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import androidx.core.view.WindowInsetsControllerCompat
|
||||
import androidx.navigation.NavOptions
|
||||
import androidx.navigation.fragment.NavHostFragment
|
||||
import androidx.preference.PreferenceManager
|
||||
import org.citra.citra_emu.CitraApplication
|
||||
@@ -184,6 +185,11 @@ class EmulationActivity : AppCompatActivity() {
|
||||
|
||||
override fun onNewIntent(intent: Intent) {
|
||||
super.onNewIntent(intent)
|
||||
val launchUri = getLaunchUri(intent)
|
||||
if (launchUri != null && launchUri != Uri.EMPTY && launchUri == getLaunchUri(this.intent)) {
|
||||
Log.info("[EmulationActivity] Ignoring relaunch of the running game")
|
||||
return
|
||||
}
|
||||
setIntent(intent)
|
||||
|
||||
NativeLibrary.stopEmulation()
|
||||
@@ -203,7 +209,24 @@ class EmulationActivity : AppCompatActivity() {
|
||||
|
||||
val navHostFragment =
|
||||
supportFragmentManager.findFragmentById(R.id.fragment_container) as NavHostFragment
|
||||
navHostFragment.navController.setGraph(R.navigation.emulation_navigation, intent.extras)
|
||||
navHostFragment.navController.navigate(
|
||||
R.id.emulationFragment,
|
||||
intent.extras,
|
||||
NavOptions.Builder().setPopUpTo(R.id.emulationFragment, true).build()
|
||||
)
|
||||
}
|
||||
|
||||
private fun getLaunchUri(intent: Intent): Uri? = try {
|
||||
val game = intent.extras?.let { extras ->
|
||||
BundleCompat.getParcelable(extras, "game", Game::class.java)
|
||||
}
|
||||
if (game != null) {
|
||||
game.launchIntent.data
|
||||
} else {
|
||||
intent.data ?: intent.getStringExtra("SelectedGame")?.toUri()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
null
|
||||
}
|
||||
|
||||
// On some devices, the system bars will not disappear on first boot or after some
|
||||
|
||||
@@ -564,8 +564,16 @@ class EmulationFragment :
|
||||
super.onPause()
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
perfStatsUpdater?.let { perfStatsUpdateHandler.removeCallbacks(it) }
|
||||
perfStatsUpdater = null
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
override fun onDetach() {
|
||||
NativeLibrary.clearEmulationActivity()
|
||||
if (!isRemoving) {
|
||||
NativeLibrary.clearEmulationActivity()
|
||||
}
|
||||
super.onDetach()
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// Refer to the LICENSE.txt file included.
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <codecvt>
|
||||
#include <thread>
|
||||
#include <dlfcn.h>
|
||||
@@ -196,6 +197,12 @@ static bool CheckMicPermission() {
|
||||
IDCache::GetRequestMicPermission());
|
||||
}
|
||||
|
||||
static void WaitForEmulationSurfaces(std::unique_lock<std::recursive_mutex>& surface_lock) {
|
||||
surface_cv.wait_for(surface_lock, std::chrono::seconds(2),
|
||||
[] { return s_secondary_surface != nullptr; });
|
||||
surface_cv.wait(surface_lock, [] { return s_surface != nullptr; });
|
||||
}
|
||||
|
||||
static Core::System::ResultStatus RunCitra(const std::string& filepath) {
|
||||
// Citra core only supports a single running instance
|
||||
std::scoped_lock lock(running_mutex);
|
||||
@@ -221,6 +228,8 @@ static Core::System::ResultStatus RunCitra(const std::string& filepath) {
|
||||
// s_surface/s_secondary_surface while they're still being used.
|
||||
std::unique_lock<std::recursive_mutex> surface_lock(surface_mutex);
|
||||
|
||||
WaitForEmulationSurfaces(surface_lock);
|
||||
|
||||
// We also need to lock the surface mutex when System::Init() is called.
|
||||
// This is because save state saving and loading may call System::Init
|
||||
// on its own which does GPU reinitialization.
|
||||
@@ -467,6 +476,7 @@ void Java_org_citra_citra_1emu_NativeLibrary_secondarySurfaceChanged(JNIEnv* env
|
||||
if (!s_secondary_surface) {
|
||||
return;
|
||||
}
|
||||
surface_cv.notify_all();
|
||||
|
||||
bool notify = false;
|
||||
if (secondary_window) {
|
||||
|
||||
Reference in new issue
Block a user