Add new events and accompanying logic to notify when the app is paused and resumed on Android devices.

This commit is contained in:
fhuya 2019-09-09 14:42:17 -07:00
parent 2add51d082
commit a7712cc9e4
12 changed files with 123 additions and 29 deletions

View File

@ -60,6 +60,8 @@ public:
NOTIFICATION_WM_ABOUT = 1011, NOTIFICATION_WM_ABOUT = 1011,
NOTIFICATION_CRASH = 1012, NOTIFICATION_CRASH = 1012,
NOTIFICATION_OS_IME_UPDATE = 1013, NOTIFICATION_OS_IME_UPDATE = 1013,
NOTIFICATION_APP_RESUMED = 1014,
NOTIFICATION_APP_PAUSED = 1015,
}; };
virtual void input_event(const Ref<InputEvent> &p_event); virtual void input_event(const Ref<InputEvent> &p_event);

View File

@ -215,5 +215,13 @@
Notification received from the OS when an update of the Input Method Engine occurs (e.g. change of IME cursor position or composition string). Notification received from the OS when an update of the Input Method Engine occurs (e.g. change of IME cursor position or composition string).
Specific to the macOS platform. Specific to the macOS platform.
</constant> </constant>
<constant name="NOTIFICATION_APP_RESUMED" value="1014">
Notification received from the OS when the app is resumed.
Specific to the Android platform.
</constant>
<constant name="NOTIFICATION_APP_PAUSED" value="1015">
Notification received from the OS when the app is paused.
Specific to the Android platform.
</constant>
</constants> </constants>
</class> </class>

View File

@ -962,6 +962,14 @@
Notification received from the OS when an update of the Input Method Engine occurs (e.g. change of IME cursor position or composition string). Notification received from the OS when an update of the Input Method Engine occurs (e.g. change of IME cursor position or composition string).
Specific to the macOS platform. Specific to the macOS platform.
</constant> </constant>
<constant name="NOTIFICATION_APP_RESUMED" value="1014">
Notification received from the OS when the app is resumed.
Specific to the Android platform.
</constant>
<constant name="NOTIFICATION_APP_PAUSED" value="1015">
Notification received from the OS when the app is paused.
Specific to the Android platform.
</constant>
<constant name="PAUSE_MODE_INHERIT" value="0" enum="PauseMode"> <constant name="PAUSE_MODE_INHERIT" value="0" enum="PauseMode">
Inherits pause mode from the node's parent. For the root node, it is equivalent to [constant PAUSE_MODE_STOP]. Default. Inherits pause mode from the node's parent. For the root node, it is equivalent to [constant PAUSE_MODE_STOP]. Default.
</constant> </constant>

View File

@ -669,12 +669,7 @@ public abstract class Godot extends Activity implements SensorEventListener, IDo
return; return;
} }
mView.onPause(); mView.onPause();
mView.queueEvent(new Runnable() {
@Override
public void run() {
GodotLib.focusout();
}
});
mSensorManager.unregisterListener(this); mSensorManager.unregisterListener(this);
for (int i = 0; i < singleton_count; i++) { for (int i = 0; i < singleton_count; i++) {
@ -703,6 +698,7 @@ public abstract class Godot extends Activity implements SensorEventListener, IDo
@Override @Override
protected void onResume() { protected void onResume() {
super.onResume(); super.onResume();
activityResumed = true;
if (!godot_initialized) { if (!godot_initialized) {
if (null != mDownloaderClientStub) { if (null != mDownloaderClientStub) {
mDownloaderClientStub.connect(this); mDownloaderClientStub.connect(this);
@ -711,12 +707,7 @@ public abstract class Godot extends Activity implements SensorEventListener, IDo
} }
mView.onResume(); mView.onResume();
mView.queueEvent(new Runnable() {
@Override
public void run() {
GodotLib.focusin();
}
});
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_GAME); mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_GAME);
mSensorManager.registerListener(this, mGravity, SensorManager.SENSOR_DELAY_GAME); mSensorManager.registerListener(this, mGravity, SensorManager.SENSOR_DELAY_GAME);
mSensorManager.registerListener(this, mMagnetometer, SensorManager.SENSOR_DELAY_GAME); mSensorManager.registerListener(this, mMagnetometer, SensorManager.SENSOR_DELAY_GAME);
@ -737,8 +728,6 @@ public abstract class Godot extends Activity implements SensorEventListener, IDo
singletons[i].onMainResume(); singletons[i].onMainResume();
} }
activityResumed = true;
} }
public void UiChangeListener() { public void UiChangeListener() {

View File

@ -211,4 +211,16 @@ public class GodotLib {
* Invoked on the GL thread to configure the height of the virtual keyboard. * Invoked on the GL thread to configure the height of the virtual keyboard.
*/ */
public static native void setVirtualKeyboardHeight(int p_height); public static native void setVirtualKeyboardHeight(int p_height);
/**
* Invoked on the GL thread when the {@link GodotRenderer} has been resumed.
* @see GodotRenderer#onActivityResumed()
*/
public static native void onRendererResumed();
/**
* Invoked on the GL thread when the {@link GodotRenderer} has been paused.
* @see GodotRenderer#onActivityPaused()
*/
public static native void onRendererPaused();
} }

View File

@ -40,7 +40,14 @@ import org.godotengine.godot.utils.GLUtils;
*/ */
class GodotRenderer implements GLSurfaceView.Renderer { class GodotRenderer implements GLSurfaceView.Renderer {
private boolean activityJustResumed = false;
public void onDrawFrame(GL10 gl) { public void onDrawFrame(GL10 gl) {
if (activityJustResumed) {
GodotLib.onRendererResumed();
activityJustResumed = false;
}
GodotLib.step(); GodotLib.step();
for (int i = 0; i < Godot.singleton_count; i++) { for (int i = 0; i < Godot.singleton_count; i++) {
Godot.singletons[i].onGLDrawFrame(gl); Godot.singletons[i].onGLDrawFrame(gl);
@ -58,4 +65,14 @@ class GodotRenderer implements GLSurfaceView.Renderer {
public void onSurfaceCreated(GL10 gl, EGLConfig config) { public void onSurfaceCreated(GL10 gl, EGLConfig config) {
GodotLib.newcontext(GLUtils.use_32); GodotLib.newcontext(GLUtils.use_32);
} }
void onActivityResumed() {
// We defer invoking GodotLib.onRendererResumed() until the first draw frame call.
// This ensures we have a valid GL context and surface when we do so.
activityJustResumed = true;
}
void onActivityPaused() {
GodotLib.onRendererPaused();
}
} }

View File

@ -68,6 +68,7 @@ public class GodotView extends GLSurfaceView {
private final Godot activity; private final Godot activity;
private final GodotInputHandler inputHandler; private final GodotInputHandler inputHandler;
private final GodotRenderer godotRenderer;
public GodotView(Godot activity, XRMode xrMode, boolean p_use_gl3, boolean p_use_32_bits, boolean p_use_debug_opengl) { public GodotView(Godot activity, XRMode xrMode, boolean p_use_gl3, boolean p_use_32_bits, boolean p_use_debug_opengl) {
super(activity); super(activity);
@ -77,6 +78,7 @@ public class GodotView extends GLSurfaceView {
this.activity = activity; this.activity = activity;
this.inputHandler = new GodotInputHandler(this); this.inputHandler = new GodotInputHandler(this);
this.godotRenderer = new GodotRenderer();
init(xrMode, false, 16, 0); init(xrMode, false, 16, 0);
} }
@ -161,10 +163,38 @@ public class GodotView extends GLSurfaceView {
} }
/* Set the renderer responsible for frame rendering */ /* Set the renderer responsible for frame rendering */
setRenderer(new GodotRenderer()); setRenderer(godotRenderer);
} }
public void onBackPressed() { public void onBackPressed() {
activity.onBackPressed(); activity.onBackPressed();
} }
@Override
public void onResume() {
super.onResume();
queueEvent(new Runnable() {
@Override
public void run() {
// Resume the renderer
godotRenderer.onActivityResumed();
GodotLib.focusin();
}
});
}
@Override
public void onPause() {
super.onPause();
queueEvent(new Runnable() {
@Override
public void run() {
GodotLib.focusout();
// Pause the renderer
godotRenderer.onActivityPaused();
}
});
}
} }

View File

@ -1387,3 +1387,21 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_requestPermissionResu
AudioDriver::get_singleton()->capture_start(); AudioDriver::get_singleton()->capture_start();
} }
} }
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_onRendererResumed(JNIEnv *env, jclass clazz) {
if (step == 0)
return;
if (os_android->get_main_loop()) {
os_android->get_main_loop()->notification(MainLoop::NOTIFICATION_APP_RESUMED);
}
}
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_onRendererPaused(JNIEnv *env, jclass clazz) {
if (step == 0)
return;
if (os_android->get_main_loop()) {
os_android->get_main_loop()->notification(MainLoop::NOTIFICATION_APP_PAUSED);
}
}

View File

@ -64,6 +64,8 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_callobject(JNIEnv *en
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_calldeferred(JNIEnv *env, jobject p_obj, jint ID, jstring method, jobjectArray params); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_calldeferred(JNIEnv *env, jobject p_obj, jint ID, jstring method, jobjectArray params);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setVirtualKeyboardHeight(JNIEnv *env, jobject obj, jint p_height); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setVirtualKeyboardHeight(JNIEnv *env, jobject obj, jint p_height);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_requestPermissionResult(JNIEnv *env, jobject p_obj, jstring p_permission, jboolean p_result); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_requestPermissionResult(JNIEnv *env, jobject p_obj, jstring p_permission, jboolean p_result);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_onRendererResumed(JNIEnv *env, jclass clazz);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_onRendererPaused(JNIEnv *env, jclass clazz);
} }
#endif /* !JAVA_GODOT_LIB_JNI_H */ #endif /* !JAVA_GODOT_LIB_JNI_H */

View File

@ -2861,6 +2861,8 @@ void Node::_bind_methods() {
BIND_CONSTANT(NOTIFICATION_WM_ABOUT); BIND_CONSTANT(NOTIFICATION_WM_ABOUT);
BIND_CONSTANT(NOTIFICATION_CRASH); BIND_CONSTANT(NOTIFICATION_CRASH);
BIND_CONSTANT(NOTIFICATION_OS_IME_UPDATE); BIND_CONSTANT(NOTIFICATION_OS_IME_UPDATE);
BIND_CONSTANT(NOTIFICATION_APP_RESUMED);
BIND_CONSTANT(NOTIFICATION_APP_PAUSED);
BIND_ENUM_CONSTANT(PAUSE_MODE_INHERIT); BIND_ENUM_CONSTANT(PAUSE_MODE_INHERIT);
BIND_ENUM_CONSTANT(PAUSE_MODE_STOP); BIND_ENUM_CONSTANT(PAUSE_MODE_STOP);

View File

@ -250,7 +250,9 @@ public:
NOTIFICATION_TRANSLATION_CHANGED = MainLoop::NOTIFICATION_TRANSLATION_CHANGED, NOTIFICATION_TRANSLATION_CHANGED = MainLoop::NOTIFICATION_TRANSLATION_CHANGED,
NOTIFICATION_WM_ABOUT = MainLoop::NOTIFICATION_WM_ABOUT, NOTIFICATION_WM_ABOUT = MainLoop::NOTIFICATION_WM_ABOUT,
NOTIFICATION_CRASH = MainLoop::NOTIFICATION_CRASH, NOTIFICATION_CRASH = MainLoop::NOTIFICATION_CRASH,
NOTIFICATION_OS_IME_UPDATE = MainLoop::NOTIFICATION_OS_IME_UPDATE NOTIFICATION_OS_IME_UPDATE = MainLoop::NOTIFICATION_OS_IME_UPDATE,
NOTIFICATION_APP_RESUMED = MainLoop::NOTIFICATION_APP_RESUMED,
NOTIFICATION_APP_PAUSED = MainLoop::NOTIFICATION_APP_PAUSED
}; };

View File

@ -630,6 +630,7 @@ void SceneTree::_notification(int p_notification) {
break; break;
} }
} break; } break;
case NOTIFICATION_WM_GO_BACK_REQUEST: { case NOTIFICATION_WM_GO_BACK_REQUEST: {
get_root()->propagate_notification(p_notification); get_root()->propagate_notification(p_notification);
@ -639,28 +640,23 @@ void SceneTree::_notification(int p_notification) {
break; break;
} }
} break; } break;
case NOTIFICATION_OS_MEMORY_WARNING:
case NOTIFICATION_OS_IME_UPDATE:
case NOTIFICATION_WM_MOUSE_ENTER:
case NOTIFICATION_WM_MOUSE_EXIT:
case NOTIFICATION_WM_FOCUS_IN:
case NOTIFICATION_WM_FOCUS_OUT:
case NOTIFICATION_WM_ABOUT: {
if (p_notification == NOTIFICATION_WM_FOCUS_IN) { case NOTIFICATION_WM_FOCUS_IN: {
InputDefault *id = Object::cast_to<InputDefault>(Input::get_singleton());
if (id) { InputDefault *id = Object::cast_to<InputDefault>(Input::get_singleton());
id->ensure_touch_mouse_raised(); if (id) {
} id->ensure_touch_mouse_raised();
} }
get_root()->propagate_notification(p_notification); get_root()->propagate_notification(p_notification);
} break; } break;
case NOTIFICATION_TRANSLATION_CHANGED: { case NOTIFICATION_TRANSLATION_CHANGED: {
if (!Engine::get_singleton()->is_editor_hint()) { if (!Engine::get_singleton()->is_editor_hint()) {
get_root()->propagate_notification(p_notification); get_root()->propagate_notification(p_notification);
} }
} break; } break;
case NOTIFICATION_WM_UNFOCUS_REQUEST: { case NOTIFICATION_WM_UNFOCUS_REQUEST: {
notify_group_flags(GROUP_CALL_REALTIME | GROUP_CALL_MULTILEVEL, "input", NOTIFICATION_WM_UNFOCUS_REQUEST); notify_group_flags(GROUP_CALL_REALTIME | GROUP_CALL_MULTILEVEL, "input", NOTIFICATION_WM_UNFOCUS_REQUEST);
@ -669,7 +665,15 @@ void SceneTree::_notification(int p_notification) {
} break; } break;
case NOTIFICATION_CRASH: { case NOTIFICATION_OS_MEMORY_WARNING:
case NOTIFICATION_OS_IME_UPDATE:
case NOTIFICATION_WM_MOUSE_ENTER:
case NOTIFICATION_WM_MOUSE_EXIT:
case NOTIFICATION_WM_FOCUS_OUT:
case NOTIFICATION_WM_ABOUT:
case NOTIFICATION_CRASH:
case NOTIFICATION_APP_RESUMED:
case NOTIFICATION_APP_PAUSED: {
get_root()->propagate_notification(p_notification); get_root()->propagate_notification(p_notification);
} break; } break;