mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-17 11:11:10 +02:00
fix(android): rebind secondary displays after hotplug
This commit is contained in:
@@ -366,6 +366,7 @@ public class GameActivity extends SDLActivity {
|
|||||||
Log.d("GameActivity", "Cancelling vibration");
|
Log.d("GameActivity", "Cancelling vibration");
|
||||||
vibrator.cancel();
|
vibrator.cancel();
|
||||||
}
|
}
|
||||||
|
unregisterSecondaryDisplayListener();
|
||||||
onHostDestroy();
|
onHostDestroy();
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
}
|
}
|
||||||
@@ -376,6 +377,7 @@ public class GameActivity extends SDLActivity {
|
|||||||
Log.d("GameActivity", "Cancelling vibration");
|
Log.d("GameActivity", "Cancelling vibration");
|
||||||
vibrator.cancel();
|
vibrator.cancel();
|
||||||
}
|
}
|
||||||
|
unregisterSecondaryDisplayListener();
|
||||||
teardownSecondaryDisplay();
|
teardownSecondaryDisplay();
|
||||||
onHostPause();
|
onHostPause();
|
||||||
super.onPause();
|
super.onPause();
|
||||||
@@ -385,6 +387,7 @@ public class GameActivity extends SDLActivity {
|
|||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
onHostResume();
|
onHostResume();
|
||||||
|
if (secondaryEnabled) registerSecondaryDisplayListener();
|
||||||
setupSecondaryDisplay();
|
setupSecondaryDisplay();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1405,6 +1408,7 @@ public class GameActivity extends SDLActivity {
|
|||||||
// in src/jni/love/src/common/android.cpp.
|
// in src/jni/love/src/common/android.cpp.
|
||||||
private static volatile SecondaryPresentation secondaryPresentation;
|
private static volatile SecondaryPresentation secondaryPresentation;
|
||||||
private static volatile boolean secondaryEnabled = false;
|
private static volatile boolean secondaryEnabled = false;
|
||||||
|
private SecondaryDisplayMonitor secondaryDisplayMonitor;
|
||||||
private static final int MAX_SECONDARY_TOUCHES = 32;
|
private static final int MAX_SECONDARY_TOUCHES = 32;
|
||||||
private static final java.util.ArrayDeque<String> secondaryTouches =
|
private static final java.util.ArrayDeque<String> secondaryTouches =
|
||||||
new java.util.ArrayDeque<>();
|
new java.util.ArrayDeque<>();
|
||||||
@@ -1416,11 +1420,44 @@ public class GameActivity extends SDLActivity {
|
|||||||
if (self == null) return;
|
if (self == null) return;
|
||||||
self.runOnUiThread(new Runnable() {
|
self.runOnUiThread(new Runnable() {
|
||||||
@Override public void run() {
|
@Override public void run() {
|
||||||
if (on) setupSecondaryDisplay(); else teardownSecondaryDisplay();
|
if (on) {
|
||||||
|
self.registerSecondaryDisplayListener();
|
||||||
|
setupSecondaryDisplay();
|
||||||
|
} else {
|
||||||
|
self.unregisterSecondaryDisplayListener();
|
||||||
|
teardownSecondaryDisplay();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void registerSecondaryDisplayListener() {
|
||||||
|
if (secondaryDisplayMonitor != null || android.os.Build.VERSION.SDK_INT < 17) return;
|
||||||
|
SecondaryDisplayMonitor monitor = new SecondaryDisplayMonitor(this);
|
||||||
|
if (monitor.register()) secondaryDisplayMonitor = monitor;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void unregisterSecondaryDisplayListener() {
|
||||||
|
SecondaryDisplayMonitor monitor = secondaryDisplayMonitor;
|
||||||
|
secondaryDisplayMonitor = null;
|
||||||
|
if (monitor != null) monitor.unregister();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void refreshSecondaryDisplay() {
|
||||||
|
GameActivity self = (GameActivity) mSingleton;
|
||||||
|
if (self == null || !secondaryEnabled) return;
|
||||||
|
SecondaryPresentation current = secondaryPresentation;
|
||||||
|
Display display = current == null ? null : current.getDisplay();
|
||||||
|
SecondaryDisplayMonitor monitor = self.secondaryDisplayMonitor;
|
||||||
|
if (current == null) {
|
||||||
|
setupSecondaryDisplay();
|
||||||
|
} else if (display == null || monitor == null
|
||||||
|
|| !monitor.hasDisplay(display.getDisplayId())) {
|
||||||
|
teardownSecondaryDisplay();
|
||||||
|
setupSecondaryDisplay();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void setupSecondaryDisplay() {
|
private static void setupSecondaryDisplay() {
|
||||||
GameActivity self = (GameActivity) mSingleton;
|
GameActivity self = (GameActivity) mSingleton;
|
||||||
if (self == null || !secondaryEnabled || secondaryPresentation != null) return;
|
if (self == null || !secondaryEnabled || secondaryPresentation != null) return;
|
||||||
@@ -1466,6 +1503,35 @@ public class GameActivity extends SDLActivity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@android.annotation.TargetApi(17)
|
||||||
|
private static class SecondaryDisplayMonitor
|
||||||
|
implements android.hardware.display.DisplayManager.DisplayListener {
|
||||||
|
private final android.hardware.display.DisplayManager manager;
|
||||||
|
|
||||||
|
SecondaryDisplayMonitor(GameActivity activity) {
|
||||||
|
manager = (android.hardware.display.DisplayManager)
|
||||||
|
activity.getSystemService(Context.DISPLAY_SERVICE);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean register() {
|
||||||
|
if (manager == null) return false;
|
||||||
|
manager.registerDisplayListener(this, new Handler(Looper.getMainLooper()));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void unregister() {
|
||||||
|
manager.unregisterDisplayListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean hasDisplay(int displayId) {
|
||||||
|
return manager.getDisplay(displayId) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void onDisplayAdded(int displayId) { refreshSecondaryDisplay(); }
|
||||||
|
@Override public void onDisplayRemoved(int displayId) { refreshSecondaryDisplay(); }
|
||||||
|
@Override public void onDisplayChanged(int displayId) { refreshSecondaryDisplay(); }
|
||||||
|
}
|
||||||
|
|
||||||
@Keep
|
@Keep
|
||||||
public static boolean hasSecondaryDisplay() {
|
public static boolean hasSecondaryDisplay() {
|
||||||
return secondaryPresentation != null;
|
return secondaryPresentation != null;
|
||||||
|
|||||||
@@ -49,6 +49,16 @@ check(position("onHostPause();") < position("super.onPause();"),
|
|||||||
check(position("onHostDestroy();") < position("super.onDestroy();"),
|
check(position("onHostDestroy();") < position("super.onDestroy();"),
|
||||||
"destroy hook runs before SDL destruction")
|
"destroy hook runs before SDL destruction")
|
||||||
|
|
||||||
|
check(source:find("DisplayManager.DisplayListener", 1, true)
|
||||||
|
and source:find("registerDisplayListener", 1, true)
|
||||||
|
and source:find("unregisterDisplayListener", 1, true),
|
||||||
|
"secondary displays are monitored while the activity is active")
|
||||||
|
check(position("if (secondaryEnabled) registerSecondaryDisplayListener();") <
|
||||||
|
position("setupSecondaryDisplay();"),
|
||||||
|
"secondary display monitoring starts before initial discovery")
|
||||||
|
check(source:find("!monitor.hasDisplay(display.getDisplayId())", 1, true),
|
||||||
|
"a disconnected active display is rebound without replacing a live one")
|
||||||
|
|
||||||
check(not source:lower():find("openxr", 1, true),
|
check(not source:lower():find("openxr", 1, true),
|
||||||
"generic Android activity must not require OpenXR")
|
"generic Android activity must not require OpenXR")
|
||||||
check(not source:find("QuestActivity", 1, true) and
|
check(not source:find("QuestActivity", 1, true) and
|
||||||
|
|||||||
Reference in New Issue
Block a user