From 07e1df3676f93e423f5cc5fc219a28e209fec6d6 Mon Sep 17 00:00:00 2001 From: Elias Naur Date: Sun, 29 Aug 2021 18:58:53 +0200 Subject: [PATCH] app: [Android] detach previous View when another is created The Android system can in some cases replace the GioView of our Android Activity before destroying the previous one. This change makes sure the previous view is ignored, in particular its destroy event. Signed-off-by: Elias Naur --- app/GioView.java | 37 ++++++++++++++++++++++++++++++------- app/os_android.go | 20 +++++++++++++++----- 2 files changed, 45 insertions(+), 12 deletions(-) diff --git a/app/GioView.java b/app/GioView.java index 5300ec42..ea550723 100644 --- a/app/GioView.java +++ b/app/GioView.java @@ -113,7 +113,9 @@ public final class GioView extends SurfaceView { } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { - onKeyEvent(nhandle, keyCode, event.getUnicodeChar(), event.getEventTime()); + if (nhandle != 0) { + onKeyEvent(nhandle, keyCode, event.getUnicodeChar(), event.getEventTime()); + } return false; } @@ -229,6 +231,9 @@ public final class GioView extends SurfaceView { } private void dispatchMotionEvent(MotionEvent event) { + if (nhandle == 0) { + return; + } for (int j = 0; j < event.getHistorySize(); j++) { long time = event.getHistoricalEventTime(j); for (int i = 0; i < event.getPointerCount(); i++) { @@ -289,12 +294,16 @@ public final class GioView extends SurfaceView { } @Override protected boolean fitSystemWindows(Rect insets) { - onWindowInsets(nhandle, insets.top, insets.right, insets.bottom, insets.left); + if (nhandle != 0) { + onWindowInsets(nhandle, insets.top, insets.right, insets.bottom, insets.left); + } return true; } @Override protected void onDraw(Canvas canvas) { - onFrameCallback(nhandle); + if (nhandle != 0) { + onFrameCallback(nhandle); + } } int getDensity() { @@ -306,25 +315,39 @@ public final class GioView extends SurfaceView { } public void start() { - onStartView(nhandle); + if (nhandle != 0) { + onStartView(nhandle); + } } public void stop() { - onStopView(nhandle); + if (nhandle != 0) { + onStopView(nhandle); + } } public void destroy() { + if (nhandle != 0) { + onDestroyView(nhandle); + } + } + + protected void unregister() { setOnFocusChangeListener(null); getHolder().removeCallback(surfCallbacks); - onDestroyView(nhandle); nhandle = 0; } public void configurationChanged() { - onConfigurationChanged(nhandle); + if (nhandle != 0) { + onConfigurationChanged(nhandle); + } } public boolean backPressed() { + if (nhandle == 0) { + return false; + } return onBack(nhandle); } diff --git a/app/os_android.go b/app/os_android.go index 40b8b9b4..b80ae749 100644 --- a/app/os_android.go +++ b/app/os_android.go @@ -161,6 +161,7 @@ var gioView struct { setNavigationColor C.jmethodID setStatusColor C.jmethodID setFullscreen C.jmethodID + unregister C.jmethodID } // ViewEvent is sent whenever the Window's underlying Android view @@ -315,6 +316,7 @@ func Java_org_gioui_GioView_onCreateView(env *C.JNIEnv, class C.jclass, view C.j m.setNavigationColor = getMethodID(env, class, "setNavigationColor", "(II)V") m.setStatusColor = getMethodID(env, class, "setStatusColor", "(II)V") m.setFullscreen = getMethodID(env, class, "setFullscreen", "(Z)V") + m.unregister = getMethodID(env, class, "unregister", "()V") }) view = C.jni_NewGlobalRef(env, view) wopts := <-mainWindow.out @@ -325,6 +327,9 @@ func Java_org_gioui_GioView_onCreateView(env *C.JNIEnv, class C.jclass, view C.j } windows[wopts.window] = w } + if w.view != 0 { + w.detach(env) + } w.view = view w.callbacks.SetDriver(w) handle := C.jlong(view) @@ -339,11 +344,7 @@ func Java_org_gioui_GioView_onCreateView(env *C.JNIEnv, class C.jclass, view C.j //export Java_org_gioui_GioView_onDestroyView func Java_org_gioui_GioView_onDestroyView(env *C.JNIEnv, class C.jclass, handle C.jlong) { w := views[handle] - w.callbacks.Event(ViewEvent{View: 0}) - w.callbacks.SetDriver(nil) - delete(views, handle) - C.jni_DeleteGlobalRef(env, w.view) - w.view = 0 + w.detach(env) } //export Java_org_gioui_GioView_onStopView @@ -442,6 +443,15 @@ func Java_org_gioui_GioView_onWindowInsets(env *C.JNIEnv, class C.jclass, view C } } +func (w *window) detach(env *C.JNIEnv) { + callVoidMethod(env, w.view, gioView.unregister) + w.callbacks.Event(ViewEvent{}) + w.callbacks.SetDriver(nil) + delete(views, C.jlong(w.view)) + C.jni_DeleteGlobalRef(env, w.view) + w.view = 0 +} + func (w *window) setVisible() { width, height := C.ANativeWindow_getWidth(w.win), C.ANativeWindow_getHeight(w.win) if width == 0 || height == 0 {