From 1e65963bd465271f49072e47cb990f3641a9d1cc Mon Sep 17 00:00:00 2001 From: Greg Date: Fri, 19 Jun 2020 14:08:20 -0400 Subject: [PATCH] Bump gio version. Add examples/fragment --- examples/dex/main.go | 28 ++++--- examples/fragment/AFrag.jar | Bin 0 -> 1217 bytes examples/fragment/AFrag.java | 27 ++++++ examples/fragment/jni_android.go | 138 +++++++++++++++++++++++++++++++ examples/fragment/main.go | 79 ++++++++++++++++++ examples/fragment/os_android.go | 35 ++++++++ examples/fragment/os_other.go | 8 ++ examples/jni/main.go | 1 + go.mod | 2 +- go.sum | 4 + 10 files changed, 308 insertions(+), 14 deletions(-) create mode 100644 examples/fragment/AFrag.jar create mode 100644 examples/fragment/AFrag.java create mode 100644 examples/fragment/jni_android.go create mode 100644 examples/fragment/main.go create mode 100644 examples/fragment/os_android.go create mode 100644 examples/fragment/os_other.go diff --git a/examples/dex/main.go b/examples/dex/main.go index 427ec41..5b2d819 100644 --- a/examples/dex/main.go +++ b/examples/dex/main.go @@ -55,21 +55,23 @@ func eventloop() { for { select { case x := <-labchan: labels = append(labels, material.Body1(th, x)) + w.Invalidate() case e := <-w.Events(): - switch e := e.(type) { - case system.DestroyEvent: - return - case system.FrameEvent: - gtx := layout.NewContext(&ops, e) - resetSysinset(e.Insets) - sysinset.Layout(gtx, func(gtx C) D { - return margin.Layout(gtx, func(gtx C) D { - return list.Layout(gtx, len(labels), func(gtx C, i int) D { - return labels[i].Layout(gtx) + switch e := e.(type) { + case system.DestroyEvent: + return + case system.FrameEvent: + gtx := layout.NewContext(&ops, e) + resetSysinset(e.Insets) + sysinset.Layout(gtx, func(gtx C) D { + return margin.Layout(gtx, func(gtx C) D { + return list.Layout(gtx, len(labels), func(gtx C, i int) D { + return labels[i].Layout(gtx) + }) }) }) - }) - e.Frame(gtx.Ops) + e.Frame(gtx.Ops) + } } - }} + } } diff --git a/examples/fragment/AFrag.jar b/examples/fragment/AFrag.jar new file mode 100644 index 0000000000000000000000000000000000000000..37ef4f226ad36a6c99feccbfff49a3d8288180cc GIT binary patch literal 1217 zcmWIWW@Zs#;Nak3n3#DvfB^|`GO#fCx`sIFdiuHP|2xINz|0Wf&CUT*!30$nfK#&w zPz7AGucM!*n`>~0p0C?y-!rFuymj?1@_OrPojY@WbCAIm;|EWR^t^m^Jbf>gu43Vg zcp-U2dX}VS#t(5-wdYH;ES`&tJ`q=)#&9+JQ_;sFMzAZ^PT#Q61!#vW5aV_QH&E8m zttc^FFF7Z%xVSeYGFaGA;Gdez?ls;_r&X1NTvCPmz8>f^M9DvMCz>FRP)U}@>|OiA;$i@t6si*w|@V;moI0^+wZSoHfRl((o1qVYASl& z^v;15SA1DHdDmW=H>Jquu!Wk5&!I`Ld_}jL+&L!88m#p$tK;Fkw%-*C9xZIkToQ7| z!*X?k-$5Ja*FCRyCiN{m>62q@qW^2#VS&>-=1sQMd1rM{?7r><*ROlG2-s{tUU2hF z!Fj%#>)VRR0}f`){+BqRcv_6-+NIN( z=FPwJ+&#wKUe9n#h|ZIhs;0tRaxXoS9gi!lGx*}UCGF1vbZ zcIV3-XQbx$zK%GO%<5mFlNfn0SXMjY>c+Ovwnn#_TiZId|MhJW&y43Xvbr`g^~Jik z&GIr4FXt5W$9!y5yeAPOWFue{!*WNvkm={VK3<#P4>8BNbA)`A=iM%gd9zcMHQFk! z=~R-*uHw3lFSul_H!1y9O`Q67)70|T(CE3LYcJ(zN3XJyw90zs{7`I7kH1HnanG!o zm$!P)-Kr9{!nEW3M~#$6b0!>-4F1XzG-cbySjO?y1%Udo;4>%DQ+2mfb0bJKtI?(z_tYoZ}*9{6Wv^-BhhsMQaw zzE{MRT?ugZNbX$Cz$N{od$!po@8z#@ug-2te8NA4S7DLtFZLEa-LC?NXI1LmtUUfp zKJvDol>Y1KhCOywMNh7?sI6D)WnRKNDMclE((#1(8BYC7y=z4myD8tjs8u2)_^WY+ zpy4dL#g*!oWj)iXe5R~ml-0WRvVT%3$H%NU?w?F2*JQiwTlDp-p@=i@MKduc?!v}2 z#S%}?D{q4)DgTn)SbE8NiJjac9tm)E2%MGGc>l9q54 z*D1Mt_-1qEm!z3o8y%P4Sg5pT<&?x38w6wivV!t$poDh&PhiGf%L>Xdj7%a7sM#Kt zr$N~s6~OZ`s1QKcikuNanH~XbflRnoq#^*_1Z0PSGAsfd1~QSdZ-6%|8%UBF2)6<0 IugoAG0J`zTIsgCw literal 0 HcmV?d00001 diff --git a/examples/fragment/AFrag.java b/examples/fragment/AFrag.java new file mode 100644 index 0000000..de83e2d --- /dev/null +++ b/examples/fragment/AFrag.java @@ -0,0 +1,27 @@ +package st.wow.git.fragment; + +import android.app.Activity; +import android.app.Fragment; +import android.app.FragmentTransaction; +import android.content.Context; +import android.util.Log; +import android.view.View; + +public class AFrag extends Fragment { + @Override public void onAttach(Context ctx) { + Log.d("AFrag", "onAttach()"); + super.onAttach(ctx); + } + + public void register(View view) { + Log.d("AFrag", "register(): view = " + view.getClass().getCanonicalName()); + Log.d("AFrag", "register(): Adding fragment"); + Activity act = (Activity)view.getContext(); + Log.d("AFrag", "register(): starting transaction"); + FragmentTransaction ft = act.getFragmentManager().beginTransaction(); + Log.d("AFrag", "register(): add this"); + ft.add(this, "AFrag"); + Log.d("AFrag", "register(): commit"); + ft.commitNow(); + } +} diff --git a/examples/fragment/jni_android.go b/examples/fragment/jni_android.go new file mode 100644 index 0000000..63b035f --- /dev/null +++ b/examples/fragment/jni_android.go @@ -0,0 +1,138 @@ +package main + +/* +#cgo LDFLAGS: -landroid + +#include +#include +#include + +static jobject gClassLoader; +static jmethodID gFindClassMethod; + +void +SetLoader(JNIEnv* env, jobject context) { + jclass cclass = (*env)->GetObjectClass(env, context); + jmethodID gcl_id = (*env)->GetMethodID(env, cclass, "getClassLoader", "()Ljava/lang/ClassLoader;"); + jobject loader = (*env)->CallObjectMethod(env, context, gcl_id); + gClassLoader = (*env)->NewGlobalRef(env, loader); + jclass lclass = (*env)->GetObjectClass(env, loader); + gFindClassMethod = (*env)->GetMethodID(env, lclass, "findClass", "(Ljava/lang/String;)Ljava/lang/Class;"); +} + +jclass +FindClass(JNIEnv* env, char* name) { + jstring strClassName = (*env)->NewStringUTF(env, name); + return (*env)->CallObjectMethod(env, gClassLoader, gFindClassMethod, strClassName); +} + +JNIEXPORT jobject +CreateObject(JNIEnv* env, jclass cls) { + jmethodID init = (*env)->GetMethodID(env, cls, "", "()V"); + return (*env)->NewObject(env, cls, init); +} + +void CallVoidMethod(JNIEnv *env, jobject obj, jmethodID methodID) { + (*env)->CallVoidMethod(env, obj, methodID); +} + +void CallVoidMethod1(JNIEnv *env, jobject obj, jmethodID methodID, jobject param) { + (*env)->CallVoidMethod(env, obj, methodID, param); +} + +jint CallIntMethod(JNIEnv *env, jobject obj, jmethodID methodID) { + return (*env)->CallIntMethod(env, obj, methodID); +} + +jmethodID GetMethodID(JNIEnv *env, jclass clazz, const char *name, const char *sig) { + return (*env)->GetMethodID(env, clazz, name, sig); +} + +jint GetEnv(JavaVM *vm, JNIEnv **env, jint version) { + return (*vm)->GetEnv(vm, (void **)env, version); +} + +jint AttachCurrentThread(JavaVM *vm, JNIEnv **p_env, void *thr_args) { + return (*vm)->AttachCurrentThread(vm, p_env, thr_args); +} + +jint DetachCurrentThread(JavaVM *vm) { + return (*vm)->DetachCurrentThread(vm); +} + +*/ +import "C" + +import ( + "errors" + "fmt" + "log" + "runtime" + "unsafe" +) + +var theJVM *C.JavaVM +type JNIEnv = C.JNIEnv + +func SetJVM(jvm, context uintptr) { + log.Print("set theJVM") + theJVM = (*C.JavaVM)(unsafe.Pointer(jvm)) + log.Printf("theJVM = %d", uintptr(unsafe.Pointer(theJVM))) + RunInJVM(func(env *C.JNIEnv) { + C.SetLoader(env, (C.jobject)(context)) + }) +} + +func FindClass(env *C.JNIEnv, name string) C.jclass { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + return C.FindClass((*C.JNIEnv)(env), cname) +} + +func JniCallVoidMethod(env *C.JNIEnv, obj C.jobject, methodID C.jmethodID) { + C.CallVoidMethod(env, obj, methodID) +} + +func JniCallVoidMethod1(env *C.JNIEnv, obj C.jobject, methodID C.jmethodID, param uintptr) { + C.CallVoidMethod1(env, obj, methodID, (C.jobject)(unsafe.Pointer(param))) +} + +func JniCallIntMethod(env *C.JNIEnv, obj C.jobject, methodID C.jmethodID) int { + return (int)(C.CallIntMethod(env, obj, methodID)) +} + +func JniGetMethodID(env *C.JNIEnv, cls C.jclass, name, sig string) C.jmethodID { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + csig := C.CString(sig) + defer C.free(unsafe.Pointer(csig)) + return C.GetMethodID(env, cls, cname, csig) +} + +func CreateObject(env *C.JNIEnv, cls C.jclass) C.jobject { + return C.CreateObject(env, (C.jclass)(cls)) +} + +func RunInJVM(f func(env *C.JNIEnv)) { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + var env *C.JNIEnv + var detach bool + log.Printf("RunInJVM(): theJVM = %d", uintptr(unsafe.Pointer(theJVM))) + 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) +} diff --git a/examples/fragment/main.go b/examples/fragment/main.go new file mode 100644 index 0000000..4abf88b --- /dev/null +++ b/examples/fragment/main.go @@ -0,0 +1,79 @@ +// +build darwin linux + +package main + +import ( + "log" + + "gioui.org/app" + "gioui.org/io/system" + "gioui.org/layout" + "gioui.org/op" + "gioui.org/unit" + "gioui.org/widget/material" + + "gioui.org/font/gofont" +) + +var ( + labchan chan string +) + +type ( + D = layout.Dimensions + C = layout.Context +) + +func main() { + labchan = make(chan string) + log.Print("Staring event loop") + go eventloop() + app.Main() + log.Print("app.Main() returned") +} + +func eventloop() { + w := app.NewWindow( + app.Size(unit.Dp(400), unit.Dp(400)), + app.Title("Hello")) + th := material.NewTheme(gofont.Collection()) + var ops op.Ops + + sysinset := &layout.Inset{} + margin := layout.UniformInset(unit.Dp(10)) + labels := []material.LabelStyle{} + list := &layout.List{Axis: layout.Vertical} + + resetSysinset := func(x system.Insets) { + sysinset.Top = x.Top + sysinset.Bottom = x.Bottom + sysinset.Left = x.Left + sysinset.Right = x.Right + } + go func() { + labchan <- "Starting" + registerFragment(w) + }() + for { + select { + case x := <-labchan: + labels = append(labels, material.Body1(th, x)) + case e := <-w.Events(): + switch e := e.(type) { + case system.DestroyEvent: + return + case system.FrameEvent: + gtx := layout.NewContext(&ops, e) + resetSysinset(e.Insets) + sysinset.Layout(gtx, func(gtx C) D { + return margin.Layout(gtx, func(gtx C) D { + return list.Layout(gtx, len(labels), func(gtx C, i int) D { + return labels[i].Layout(gtx) + }) + }) + }) + e.Frame(gtx.Ops) + } + } + } +} diff --git a/examples/fragment/os_android.go b/examples/fragment/os_android.go new file mode 100644 index 0000000..685cdf6 --- /dev/null +++ b/examples/fragment/os_android.go @@ -0,0 +1,35 @@ +//go:generate javac -bootclasspath $ANDROID_HOME/platforms/android-29/android.jar AFrag.java +//go:generate jar cf AFrag.jar AFrag.class +//go:generate rm AFrag.class + +package main + +import ( + "log" + + "gioui.org/app" +) + +func registerFragment(w *app.Window) { + labchan <- "registerFragment()" + SetJVM(app.JavaVM(), app.AppContext()) + + w.Do(func(view uintptr) { + RunInJVM(func(env *JNIEnv) { + log.Print("finding class") + cls := FindClass(env, "st/wow/git/fragment/AFrag") + log.Print("getting methodID") + mth := JniGetMethodID(env, cls, "register", "(Landroid/view/View;)V"); + if mth == nil { + labchan <- "nil method" + return + } + log.Print("creating object") + inst := CreateObject(env, cls) + log.Print("calling method") + JniCallVoidMethod1(env, inst, mth, view) + log.Print("got result") + }) + }) +} + diff --git a/examples/fragment/os_other.go b/examples/fragment/os_other.go new file mode 100644 index 0000000..4d8166c --- /dev/null +++ b/examples/fragment/os_other.go @@ -0,0 +1,8 @@ +// +build !android + +package main + +func registerFragment() { + labchan <- "nothing to do" +} + diff --git a/examples/jni/main.go b/examples/jni/main.go index e05b494..36360ba 100644 --- a/examples/jni/main.go +++ b/examples/jni/main.go @@ -58,6 +58,7 @@ func eventloop() { select { case x := <-labchan: labels = append(labels, material.Body1(th, x)) + w.Invalidate() case e := <-w.Events(): switch e := e.(type) { case system.DestroyEvent: diff --git a/go.mod b/go.mod index 8323903..92b614c 100644 --- a/go.mod +++ b/go.mod @@ -2,4 +2,4 @@ module git.wow.st/gmp/android-go go 1.14 -require gioui.org v0.0.0-20200611133933-6d5fbcba3f21 +require gioui.org v0.0.0-20200619121558-88ced59dad93 diff --git a/go.sum b/go.sum index d5fed71..7d5be8b 100644 --- a/go.sum +++ b/go.sum @@ -5,6 +5,8 @@ gioui.org v0.0.0-20191112235626-1bf2c7ef293c h1:jhUehzf6xTCgEewbJyjd+WE2Kq5pvPIx gioui.org v0.0.0-20191112235626-1bf2c7ef293c/go.mod h1:KqFFi2Dq5gYA3FJ0sDOt8OBXoMsuxMtE8v2f0JExXAY= gioui.org v0.0.0-20200611133933-6d5fbcba3f21 h1:VFB+0QxUPABMgEarfyJeHQvUNc++9TASnDVXcFgxLcA= gioui.org v0.0.0-20200611133933-6d5fbcba3f21/go.mod h1:AHI9rFr6AEEHCb8EPVtb/p5M+NMJRKH58IOp8O3Je04= +gioui.org v0.0.0-20200619121558-88ced59dad93 h1:Llh4Tigdbu++FrRXL/KzqDHnH2Q5LPmAEk0djh6NLwk= +gioui.org v0.0.0-20200619121558-88ced59dad93/go.mod h1:jiUwifN9cRl/zmco43aAqh0aV+s9GbhG13KcD+gEpkU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -15,6 +17,8 @@ golang.org/x/exp v0.0.0-20191002040644-a1355ae1e2c3/go.mod h1:NOZ3BPKG0ec/BKJQgn golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b h1:+qEpEAPhDZ1o0x3tHzZTQDArnOixOzGD9HUJfcg0mb4= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20200618115811-c13761719519 h1:1e2ufUJNM3lCHEY5jIgac/7UTjd6cgJNdatjPdFWf34= +golang.org/x/image v0.0.0-20200618115811-c13761719519/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=