Fixed bug 4580 - Android 8: immersive fullscreen notification causes flickering between fullscreen and non-fullscreen and app is unresponsive Sylvain 2019-04-18 21:22:59 UTC Changes: - SDL_WINDOWEVENT_FOCUS_GAINED and SDL_WINDOWEVENT_FOCUS_LOST are sent when the java method onWindowFocusChanged() is called. - If we have support for MultiWindow (eg API >= 24), SDL event loop is blocked/un-blocked (or simply egl-backed-up or not), when java onStart()/onStop() are called. - If not, this behaves like now, SDL event loop is blocked/un-blocked when onPause()/onResume() are called. So if we have two app on screen and switch from one to the other, only FOCUS events are sent (and onPause()/onResume() are called but empty. onStart()/onStop() are not called). The SDL app, un-focused, would still continue to run and display frames (currently the App would be displayed, but paused). Like a video player app or a chronometer that would still be refreshed, even if the window hasn't the focus. It should work also on ChromeBooks (not tested), with two apps opened at the same time. I am not sure this fix Dan's issue. Because focus lost event triggers Minimize function (which BTW is not provided on android). https://hg.libsdl.org/SDL/file/bb41b3635c34/src/video/SDL_video.c#l2653 https://hg.libsdl.org/SDL/file/bb41b3635c34/src/video/SDL_video.c#l2634 So, in addition, it would need to add by default SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS to 0. So that the lost focus event doesn't try to minimize the window. And this should fix also the issue.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
diff --git a/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java b/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java
index 420acd7..5e5eb04 100644
--- a/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java
+++ b/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java
@@ -38,6 +38,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
private static final String TAG = "SDL";
public static boolean mIsResumedCalled, mHasFocus;
+ public static final boolean mHasMultiWindow = (Build.VERSION.SDK_INT >= 24);
// Cursor types
private static final int SDL_SYSTEM_CURSOR_NONE = -1;
@@ -274,16 +275,12 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
}
}
- // Events
- @Override
- protected void onPause() {
- Log.v(TAG, "onPause()");
- super.onPause();
+ protected void pauseNativeThread() {
mNextNativeState = NativeState.PAUSED;
mIsResumedCalled = false;
if (SDLActivity.mBrokenLibraries) {
- return;
+ return;
}
if (mHIDDeviceManager != null) {
@@ -293,10 +290,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
SDLActivity.handleNativeState();
}
- @Override
- protected void onResume() {
- Log.v(TAG, "onResume()");
- super.onResume();
+ protected void resumeNativeThread() {
mNextNativeState = NativeState.RESUMED;
mIsResumedCalled = true;
@@ -311,6 +305,43 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
SDLActivity.handleNativeState();
}
+ // Events
+ @Override
+ protected void onPause() {
+ Log.v(TAG, "onPause()");
+ super.onPause();
+ if (!mHasMultiWindow) {
+ pauseNativeThread();
+ }
+ }
+
+ @Override
+ protected void onResume() {
+ Log.v(TAG, "onResume()");
+ super.onResume();
+ if (!mHasMultiWindow) {
+ resumeNativeThread();
+ }
+ }
+
+ @Override
+ protected void onStop() {
+ Log.v(TAG, "onStop()");
+ super.onStop();
+ if (mHasMultiWindow) {
+ pauseNativeThread();
+ }
+ }
+
+ @Override
+ protected void onStart() {
+ Log.v(TAG, "onStart()");
+ super.onStart();
+ if (mHasMultiWindow) {
+ resumeNativeThread();
+ }
+ }
+
public static int getCurrentOrientation() {
final Context context = SDLActivity.getContext();
final Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
@@ -347,15 +378,21 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
return;
}
- SDLActivity.mHasFocus = hasFocus;
+ mHasFocus = hasFocus;
if (hasFocus) {
mNextNativeState = NativeState.RESUMED;
SDLActivity.getMotionListener().reclaimRelativeMouseModeIfNeeded();
+
+ SDLActivity.handleNativeState();
+ nativeFocusChanged(true);
+
} else {
- mNextNativeState = NativeState.PAUSED;
+ nativeFocusChanged(false);
+ if (!mHasMultiWindow) {
+ mNextNativeState = NativeState.PAUSED;
+ SDLActivity.handleNativeState();
+ }
}
-
- SDLActivity.handleNativeState();
}
@Override
@@ -719,6 +756,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
public static native void nativeQuit();
public static native void nativePause();
public static native void nativeResume();
+ public static native void nativeFocusChanged(boolean hasFocus);
public static native void onNativeDropFile(String filename);
public static native void nativeSetScreenResolution(int surfaceWidth, int surfaceHeight, int deviceWidth, int deviceHeight, int format, float rate);
public static native void onNativeResize();
diff --git a/src/core/android/SDL_android.c b/src/core/android/SDL_android.c
index fe0af26..2e7240d 100644
--- a/src/core/android/SDL_android.c
+++ b/src/core/android/SDL_android.c
@@ -131,6 +131,9 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativePause)(
JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeResume)(
JNIEnv *env, jclass cls);
+JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeFocusChanged)(
+ JNIEnv *env, jclass cls, jboolean hasFocus);
+
JNIEXPORT jstring JNICALL SDL_JAVA_INTERFACE(nativeGetHint)(
JNIEnv *env, jclass cls,
jstring name);
@@ -1034,7 +1037,6 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativePause)(
__android_log_print(ANDROID_LOG_VERBOSE, "SDL", "nativePause()");
if (Android_Window) {
- SDL_SendWindowEvent(Android_Window, SDL_WINDOWEVENT_FOCUS_LOST, 0, 0);
SDL_SendWindowEvent(Android_Window, SDL_WINDOWEVENT_MINIMIZED, 0, 0);
SDL_SendAppEvent(SDL_APP_WILLENTERBACKGROUND);
SDL_SendAppEvent(SDL_APP_DIDENTERBACKGROUND);
@@ -1060,7 +1062,6 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeResume)(
if (Android_Window) {
SDL_SendAppEvent(SDL_APP_WILLENTERFOREGROUND);
SDL_SendAppEvent(SDL_APP_DIDENTERFOREGROUND);
- SDL_SendWindowEvent(Android_Window, SDL_WINDOWEVENT_FOCUS_GAINED, 0, 0);
SDL_SendWindowEvent(Android_Window, SDL_WINDOWEVENT_RESTORED, 0, 0);
}
@@ -1073,6 +1074,19 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeResume)(
SDL_UnlockMutex(Android_ActivityMutex);
}
+JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeFocusChanged)(
+ JNIEnv *env, jclass cls, jboolean hasFocus)
+{
+ SDL_LockMutex(Android_ActivityMutex);
+
+ if (Android_Window) {
+ __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "nativeFocusChanged()");
+ SDL_SendWindowEvent(Android_Window, (hasFocus ? SDL_WINDOWEVENT_FOCUS_GAINED : SDL_WINDOWEVENT_FOCUS_LOST), 0, 0);
+ }
+
+ SDL_UnlockMutex(Android_ActivityMutex);
+}
+
JNIEXPORT void JNICALL SDL_JAVA_INTERFACE_INPUT_CONNECTION(nativeCommitText)(
JNIEnv *env, jclass cls,
jstring text, jint newCursorPosition)