mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-06 09:55:40 +00:00
app/internal/window: [Android] make runOnThread independent of a valid GioView
Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
@@ -5,12 +5,15 @@ package org.gioui;
|
|||||||
import android.content.ClipboardManager;
|
import android.content.ClipboardManager;
|
||||||
import android.content.ClipData;
|
import android.content.ClipData;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
|
|
||||||
public final class Gio {
|
public final class Gio {
|
||||||
private final static Object initLock = new Object();
|
private static final Object initLock = new Object();
|
||||||
private static boolean jniLoaded;
|
private static boolean jniLoaded;
|
||||||
|
private static final Handler handler = new Handler(Looper.getMainLooper());
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* init loads and initializes the Go native library and runs
|
* init loads and initializes the Go native library and runs
|
||||||
@@ -53,4 +56,13 @@ public final class Gio {
|
|||||||
return c.getItemAt(0).coerceToText(ctx).toString();
|
return c.getItemAt(0).coerceToText(ctx).toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void wakeupMainThread() {
|
||||||
|
handler.post(new Runnable() {
|
||||||
|
@Override public void run() {
|
||||||
|
scheduleMainFuncs();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static private native void scheduleMainFuncs();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import android.app.FragmentTransaction;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Handler;
|
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.view.Choreographer;
|
import android.view.Choreographer;
|
||||||
@@ -40,7 +39,6 @@ public final class GioView extends SurfaceView implements Choreographer.FrameCal
|
|||||||
private final SurfaceHolder.Callback surfCallbacks;
|
private final SurfaceHolder.Callback surfCallbacks;
|
||||||
private final View.OnFocusChangeListener focusCallback;
|
private final View.OnFocusChangeListener focusCallback;
|
||||||
private final InputMethodManager imm;
|
private final InputMethodManager imm;
|
||||||
private final Handler handler;
|
|
||||||
private long nhandle;
|
private long nhandle;
|
||||||
|
|
||||||
public GioView(Context context) {
|
public GioView(Context context) {
|
||||||
@@ -50,7 +48,6 @@ public final class GioView extends SurfaceView implements Choreographer.FrameCal
|
|||||||
public GioView(Context context, AttributeSet attrs) {
|
public GioView(Context context, AttributeSet attrs) {
|
||||||
super(context, attrs);
|
super(context, attrs);
|
||||||
|
|
||||||
handler = new Handler();
|
|
||||||
// Late initialization of the Go runtime to wait for a valid context.
|
// Late initialization of the Go runtime to wait for a valid context.
|
||||||
Gio.init(context.getApplicationContext());
|
Gio.init(context.getApplicationContext());
|
||||||
|
|
||||||
@@ -194,14 +191,6 @@ public final class GioView extends SurfaceView implements Choreographer.FrameCal
|
|||||||
return onBack(nhandle);
|
return onBack(nhandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void wakeupMainThread() {
|
|
||||||
handler.post(new Runnable() {
|
|
||||||
@Override public void run() {
|
|
||||||
scheduleMainFuncs();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void registerFragment(String del) {
|
void registerFragment(String del) {
|
||||||
final Class cls;
|
final Class cls;
|
||||||
try {
|
try {
|
||||||
@@ -241,7 +230,6 @@ public final class GioView extends SurfaceView implements Choreographer.FrameCal
|
|||||||
static private native void onFrameCallback(long handle, long nanos);
|
static private native void onFrameCallback(long handle, long nanos);
|
||||||
static private native boolean onBack(long handle);
|
static private native boolean onBack(long handle);
|
||||||
static private native void onFocusChange(long handle, boolean focus);
|
static private native void onFocusChange(long handle, boolean focus);
|
||||||
static private native void scheduleMainFuncs();
|
|
||||||
|
|
||||||
private static class InputConnection extends BaseInputConnection {
|
private static class InputConnection extends BaseInputConnection {
|
||||||
private final Editable editable;
|
private final Editable editable;
|
||||||
|
|||||||
@@ -81,7 +81,6 @@ type window struct {
|
|||||||
mhideTextInput C.jmethodID
|
mhideTextInput C.jmethodID
|
||||||
mpostFrameCallback C.jmethodID
|
mpostFrameCallback C.jmethodID
|
||||||
mRegisterFragment C.jmethodID
|
mRegisterFragment C.jmethodID
|
||||||
mwakeupMainThread C.jmethodID
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type jvalue uint64 // The largest JNI type fits in 64 bits.
|
type jvalue uint64 // The largest JNI type fits in 64 bits.
|
||||||
@@ -100,8 +99,9 @@ var android struct {
|
|||||||
// gioCls is the class of the Gio class.
|
// gioCls is the class of the Gio class.
|
||||||
gioCls C.jclass
|
gioCls C.jclass
|
||||||
|
|
||||||
mwriteClipboard C.jmethodID
|
mwriteClipboard C.jmethodID
|
||||||
mreadClipboard C.jmethodID
|
mreadClipboard C.jmethodID
|
||||||
|
mwakeupMainThread C.jmethodID
|
||||||
}
|
}
|
||||||
|
|
||||||
var views = make(map[C.jlong]*window)
|
var views = make(map[C.jlong]*window)
|
||||||
@@ -159,6 +159,7 @@ func initJVM(env *C.JNIEnv, gio C.jclass, ctx C.jobject) {
|
|||||||
android.gioCls = C.jclass(C.gio_jni_NewGlobalRef(env, C.jobject(gio)))
|
android.gioCls = C.jclass(C.gio_jni_NewGlobalRef(env, C.jobject(gio)))
|
||||||
android.mwriteClipboard = getStaticMethodID(env, gio, "writeClipboard", "(Landroid/content/Context;Ljava/lang/String;)V")
|
android.mwriteClipboard = getStaticMethodID(env, gio, "writeClipboard", "(Landroid/content/Context;Ljava/lang/String;)V")
|
||||||
android.mreadClipboard = getStaticMethodID(env, gio, "readClipboard", "(Landroid/content/Context;)Ljava/lang/String;")
|
android.mreadClipboard = getStaticMethodID(env, gio, "readClipboard", "(Landroid/content/Context;)Ljava/lang/String;")
|
||||||
|
android.mwakeupMainThread = getStaticMethodID(env, gio, "wakeupMainThread", "()V")
|
||||||
}
|
}
|
||||||
|
|
||||||
func JavaVM() uintptr {
|
func JavaVM() uintptr {
|
||||||
@@ -193,7 +194,6 @@ func Java_org_gioui_GioView_onCreateView(env *C.JNIEnv, class C.jclass, view C.j
|
|||||||
mhideTextInput: getMethodID(env, class, "hideTextInput", "()V"),
|
mhideTextInput: getMethodID(env, class, "hideTextInput", "()V"),
|
||||||
mpostFrameCallback: getMethodID(env, class, "postFrameCallback", "()V"),
|
mpostFrameCallback: getMethodID(env, class, "postFrameCallback", "()V"),
|
||||||
mRegisterFragment: getMethodID(env, class, "registerFragment", "(Ljava/lang/String;)V"),
|
mRegisterFragment: getMethodID(env, class, "registerFragment", "(Ljava/lang/String;)V"),
|
||||||
mwakeupMainThread: getMethodID(env, class, "wakeupMainThread", "()V"),
|
|
||||||
}
|
}
|
||||||
wopts := <-mainWindow.out
|
wopts := <-mainWindow.out
|
||||||
w.callbacks = wopts.window
|
w.callbacks = wopts.window
|
||||||
@@ -372,7 +372,7 @@ func (w *window) SetAnimating(anim bool) {
|
|||||||
w.animating = anim
|
w.animating = anim
|
||||||
w.mu.Unlock()
|
w.mu.Unlock()
|
||||||
if anim {
|
if anim {
|
||||||
w.runOnMain(func(env *C.JNIEnv) {
|
runOnMain(func(env *C.JNIEnv) {
|
||||||
if w.view == 0 {
|
if w.view == 0 {
|
||||||
// View was destroyed while switching to main thread.
|
// View was destroyed while switching to main thread.
|
||||||
return
|
return
|
||||||
@@ -626,7 +626,7 @@ func NewWindow(window Callbacks, opts *Options) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (w *window) WriteClipboard(s string) {
|
func (w *window) WriteClipboard(s string) {
|
||||||
w.runOnMain(func(env *C.JNIEnv) {
|
runOnMain(func(env *C.JNIEnv) {
|
||||||
jstr := javaString(env, s)
|
jstr := javaString(env, s)
|
||||||
callStaticVoidMethod(env, android.gioCls, android.mwriteClipboard,
|
callStaticVoidMethod(env, android.gioCls, android.mwriteClipboard,
|
||||||
jvalue(android.appCtx), jvalue(jstr))
|
jvalue(android.appCtx), jvalue(jstr))
|
||||||
@@ -634,7 +634,7 @@ func (w *window) WriteClipboard(s string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (w *window) ReadClipboard() {
|
func (w *window) ReadClipboard() {
|
||||||
w.runOnMain(func(env *C.JNIEnv) {
|
runOnMain(func(env *C.JNIEnv) {
|
||||||
c, err := callStaticObjectMethod(env, android.gioCls, android.mreadClipboard,
|
c, err := callStaticObjectMethod(env, android.gioCls, android.mreadClipboard,
|
||||||
jvalue(android.appCtx))
|
jvalue(android.appCtx))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -646,17 +646,17 @@ func (w *window) ReadClipboard() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// runOnMain runs a function on the Java main thread.
|
// runOnMain runs a function on the Java main thread.
|
||||||
func (w *window) runOnMain(f func(env *C.JNIEnv)) {
|
func runOnMain(f func(env *C.JNIEnv)) {
|
||||||
go func() {
|
go func() {
|
||||||
mainFuncs <- f
|
mainFuncs <- f
|
||||||
runInJVM(javaVM(), func(env *C.JNIEnv) {
|
runInJVM(javaVM(), func(env *C.JNIEnv) {
|
||||||
callVoidMethod(env, w.view, w.mwakeupMainThread)
|
callStaticVoidMethod(env, android.gioCls, android.mwakeupMainThread)
|
||||||
})
|
})
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
//export Java_org_gioui_GioView_scheduleMainFuncs
|
//export Java_org_gioui_Gio_scheduleMainFuncs
|
||||||
func Java_org_gioui_GioView_scheduleMainFuncs(env *C.JNIEnv, this C.jobject) {
|
func Java_org_gioui_Gio_scheduleMainFuncs(env *C.JNIEnv, cls C.jclass) {
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case f := <-mainFuncs:
|
case f := <-mainFuncs:
|
||||||
|
|||||||
Reference in New Issue
Block a user