//+build !darwin !linux package main /* #cgo LDFLAGS: -landroid -llog #include #include "jni_android.h" */ import "C" import ( "errors" "fmt" "runtime" "unsafe" "gioui.org/app" "gioui.org/io/event" _ "gioui.org/app/permission/storage" ) type JNIEnv = C.JNIEnv var ( startpath="/storage/emulated/0/Notes" jvm uintptr theJVM *C.JavaVM ) func impl_start() { } func handleEvent(e event.Event) { switch e := e.(type) { case app.AndroidViewEvent: theJVM = (*C.JavaVM)(unsafe.Pointer(app.JavaVM())) RunInJVM(func(env *JNIEnv) { C.registerFragment(env, (C.jobject)(unsafe.Pointer(e.View))) }) } } func RunInJVM(f func(env *C.JNIEnv)) { runtime.LockOSThread() defer runtime.UnlockOSThread() var env *C.JNIEnv var detach bool if res := C.GetEnv(theJVM, &env, C.JNI_VERSION_1_6); res != C.JNI_OK { if res != C.JNI_EDETACHED { panic(fmt.Errorf("JNI GetEnv failed with error %d", res)) } if C.AttachCurrentThread(theJVM, &env, nil) != C.JNI_OK { panic(errors.New("runInJVM: AttachCurrentThread failed")) } detach = true } if detach { defer func() { C.DetachCurrentThread(theJVM) }() } f(env) } // SetGestureExclusions forwards the selection-handle grab boxes (view-local // px) to View.setSystemGestureExclusionRects on Android so drags starting on // an edge handle are not stolen by the system back gesture (see // jni_android.c). It is called from the frame loop, which runs on the Android // UI thread. No-op (C-side) before API 29. func SetGestureExclusions(rects [][4]int) { if theJVM == nil { return } RunInJVM(func(env *C.JNIEnv) { if len(rects) == 0 { C.SetGestureExclusions(env, 0, nil) return } buf := make([]C.jint, len(rects)*4) for i, rc := range rects { for j, v := range rc { buf[i*4+j] = C.jint(v) } } C.SetGestureExclusions(env, C.jint(len(rects)), &buf[0]) }) } // sessionFilePath is where the relaunch session file (spec ยง7) lives. The // primary storage dir already carries the app's caches (.pad browser index // dirs, PadPerf), and the app holds the storage permission. func sessionFilePath() string { return "/storage/emulated/0/Pad/session.json" } func OpenFile(path string) { var env *C.JNIEnv var detach bool if res := C.GetEnv(theJVM, &env, C.JNI_VERSION_1_6); res != C.JNI_OK { if res != C.JNI_EDETACHED { panic(fmt.Errorf("JNI GetEnv failed with error %d", res)) } if C.AttachCurrentThread(theJVM, &env, nil) != C.JNI_OK { panic(errors.New("OpenFile: AttachCurrentThread failed")) } detach = true } if detach { defer func() { C.DetachCurrentThread(theJVM) }() } cpath := C.CString(path) C.open_file_in_termux(env, cpath) C.free(unsafe.Pointer(cpath)) }