diff --git a/PgpConnect.jar b/PgpConnect.jar index 49b2af4..f41371c 100644 Binary files a/PgpConnect.jar and b/PgpConnect.jar differ diff --git a/PgpConnect.java b/PgpConnect.java index b7aad63..552be58 100644 --- a/PgpConnect.java +++ b/PgpConnect.java @@ -29,6 +29,8 @@ import android.content.IntentSender.SendIntentException; import android.os.Bundle; import android.Manifest; import android.content.pm.PackageManager; +import android.content.Context; +import android.view.View; public class PgpConnect extends Fragment { Context ctx; @@ -37,8 +39,19 @@ public class PgpConnect extends Fragment { OpenPgpServiceConnection mServiceConnection; final int PERMISSIONS_REQUEST = 1; - public PgpConnect() { + public PgpConnect(View view) { Log.d("gio", "PgpConnect()"); + this.ctx = view.getContext(); + this.handler = new Handler(this.ctx.getMainLooper()); + PgpConnect inst = this; + handler.post(new Runnable() { + public void run() { + Activity act = (Activity)ctx; + FragmentTransaction ft = act.getFragmentManager().beginTransaction(); + ft.add(inst, "PgpConnect"); + ft.commitNow(); + } + }); } @Override public void onAttach(Context ctx) { @@ -47,14 +60,13 @@ public class PgpConnect extends Fragment { if (ctx instanceof Activity) { Log.d("gio", "It's an Activity!"); } - this.ctx = ctx; - this.handler = new Handler(ctx.getMainLooper()); mServiceConnection = new OpenPgpServiceConnection(ctx, "org.sufficientlysecure.keychain"); mServiceConnection.bindToService(); cb = (ClipboardManager) ctx.getSystemService(Context.CLIPBOARD_SERVICE); if (ctx.checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED || ctx.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, PERMISSIONS_REQUEST); } + System.loadLibrary("gio"); installComplete(this); } diff --git a/cmd/passgo-gui/impl_android.go b/cmd/passgo-gui/impl_android.go index eedeeeb..43f7ac3 100644 --- a/cmd/passgo-gui/impl_android.go +++ b/cmd/passgo-gui/impl_android.go @@ -1,4 +1,4 @@ -//+build !darwin +//+build android package main @@ -7,7 +7,7 @@ import ( "git.wow.st/gmp/passgo" "gioui.org/app" - "gioui.org/font/gofont" + "gioui.org/io/event" ) var ( @@ -18,11 +18,17 @@ func init() { log(Info, "Android start") // Use a larger font on Android fontSize = 24 - gofont.Register() } -func initPgp(w *app.Window) { - passgo.InitPgp(w) +func handleEvent(e event.Event) { + switch e := e.(type) { + case app.ViewEvent: + initPgp(e.View) + } +} + +func initPgp(view uintptr) { + passgo.InitPgp(view) } func getConfDir() (string, error) { diff --git a/cmd/passgo-gui/impl_darwin.go b/cmd/passgo-gui/impl_darwin.go index 0427c79..a3770b1 100644 --- a/cmd/passgo-gui/impl_darwin.go +++ b/cmd/passgo-gui/impl_darwin.go @@ -7,9 +7,6 @@ import ( "os/user" "path" - "gioui.org/app" - "gioui.org/font" - "gioui.org/font/gofont" "gioui.org/font/opentype" "gioui.org/text" ) @@ -30,24 +27,23 @@ func setFont() error { log(Info, "Cannot parse font collection") return err } - face, err := fnts.Font(0) + fnt, err := fnts.Font(0) + if err != nil { + log(Info, "Cannot get font from collection") + return err + } + collection = append(collection, text.FontFace{Font: text.Font{}, Face: fnt}) if err != nil { log(Info, "Cannot access font from font collection") return err } - font.Register(text.Font{}, face) + //font.Register(text.Font{}, face) return nil } func init() { fontSize = 16 - err := setFont() - if err != nil { - gofont.Register() - } -} - -func initPgp(w *app.Window) { + setFont() } func getConfDir() (string, error) { diff --git a/cmd/passgo-gui/impl_others.go b/cmd/passgo-gui/impl_others.go new file mode 100644 index 0000000..523768b --- /dev/null +++ b/cmd/passgo-gui/impl_others.go @@ -0,0 +1,10 @@ +//+build !android + +package main + +import ( + "gioui.org/io/event" +) + +func handleEvent(e event.Event) { +} diff --git a/cmd/passgo-gui/main.go b/cmd/passgo-gui/main.go index 2cb15e6..b90b5ed 100644 --- a/cmd/passgo-gui/main.go +++ b/cmd/passgo-gui/main.go @@ -15,16 +15,16 @@ import ( "time" "gioui.org/app" + "gioui.org/font/gofont" "gioui.org/io/key" "gioui.org/io/system" "gioui.org/layout" + "gioui.org/op" "gioui.org/text" "gioui.org/unit" "gioui.org/widget" "gioui.org/widget/material" - //"gioui.org/font/gofont" - "github.com/fsnotify/fsnotify" "gopkg.in/yaml.v2" @@ -32,6 +32,11 @@ import ( "git.wow.st/gmp/rand" ) +type ( + D = layout.Dimensions + C = layout.Context +) + type conf struct { StoreDir string ClearDelay int @@ -113,6 +118,7 @@ func main() { var ( fontSize float32 + collection []text.FontFace confDir string Config conf l []passgo.Pass @@ -190,15 +196,16 @@ func saveConf(fds ...*os.File) { } func eventLoop() { - //gofont.Register() - th = material.NewTheme() + if collection == nil { + collection = gofont.Collection() + } + + var ops op.Ops + th = material.NewTheme(collection) th.TextSize = unit.Sp(fontSize) w := app.NewWindow( app.Size(unit.Dp(250), unit.Dp(500)), app.Title("passgo")) - initPgp(w) - gtx := layout.NewContext(w.Queue()) - //time.Sleep(time.Second/5) var margincs layout.Constraints @@ -207,7 +214,7 @@ func eventLoop() { sysinset := &layout.Inset{} margin := layout.UniformInset(unit.Dp(10)) - title := th.Body1("passgo") + title := material.Body1(th, "passgo") dotsBtn := &Button{ Size: unit.Sp(fontSize), Label: "\xe2\x8b\xae", @@ -289,7 +296,7 @@ func eventLoop() { Background: gray, } - storeDirLabel := th.Label(unit.Sp(fontSize), "Store directory") + storeDirLabel := material.Label(th, unit.Sp(fontSize), "Store directory") storeDirEd := &widget.Editor{ SingleLine: true} storeDirEd.SetText(store.Dir) saveBtn := &Button{ @@ -306,7 +313,7 @@ func eventLoop() { Color: black, Background: gray, } - confirmLabel := th.Label(unit.Sp(fontSize), "Password exists. Overwrite?") + confirmLabel := material.Label(th, unit.Sp(fontSize), "Password exists. Overwrite?") yesBtn := &Button{ Size: unit.Sp(fontSize), Label: "yes", @@ -315,7 +322,7 @@ func eventLoop() { Background: gray, } - promptLabel := th.Label(unit.Sp(fontSize), "passphrase") + promptLabel := material.Label(th, unit.Sp(fontSize), "passphrase") promptEd := &widget.Editor{ SingleLine: true, Submit: true } okBtn := &Button{ Size: unit.Sp(fontSize), @@ -332,20 +339,20 @@ func eventLoop() { Background: gray, } - insertLabel := th.Label(unit.Sp(fontSize), "Insert") - passnameLabel := th.Label(unit.Sp(fontSize), "password name:") + insertLabel := material.Label(th, unit.Sp(fontSize), "Insert") + passnameLabel := material.Label(th, unit.Sp(fontSize), "password name:") passnameEd := &widget.Editor{ SingleLine: true } - passvalLabel := th.Label(unit.Sp(fontSize), "password value:") + passvalLabel := material.Label(th, unit.Sp(fontSize), "password value:") passvalEd := &widget.Editor{ SingleLine: true, Submit: true } - noidLabel := th.Label(unit.Sp(fontSize), noidLabelText) - idLabel := th.Label(unit.Sp(fontSize), "Select ID") + noidLabel := material.Label(th, unit.Sp(fontSize), noidLabelText) + idLabel := material.Label(th, unit.Sp(fontSize), "Select ID") anim := &time.Ticker{} animating := false animOn := func() { log(Info, "animOn()") - anim = time.NewTicker(time.Second / 30) + anim = time.NewTicker(time.Second / 90) animating = true w.Invalidate() } @@ -355,7 +362,7 @@ func eventLoop() { animating = false } - var listPage, idPage, insertPage, confirmPage, confPage, promptPage, page func() + var listPage, idPage, insertPage, confirmPage, confPage, promptPage, page func(C) D _ = idPage prompt := func() []byte { @@ -365,13 +372,14 @@ func eventLoop() { return <-passch } - listPage = func() { + listPage = func(gtx C) D { // timing variables used for animation fade1a, fade1b := 1.5, 2.0 start2 := float64(Config.ClearDelay) fade2a, end := start2+1.5, start2+2.0 - c2 := layout.Flexed(1.0, func() { + c2 := layout.Flexed(1.0, func(gtx C) D { + var ret D mux.Lock() if lst.Dragging() { key.HideInputOp{}.Add(gtx.Ops) @@ -389,10 +397,10 @@ func eventLoop() { w.Invalidate() page = idPage default: - lst.Layout(gtx, len(passBtns), func(i int) { + ret = lst.Layout(gtx, len(passBtns), func(gtx C, i int) D { btn := passBtns[i] - gtx.Constraints.Width.Min = gtx.Constraints.Width.Max - btn.Layout(gtx) + gtx.Constraints.Min.X = gtx.Constraints.Max.X + ret := btn.Layout(gtx) if btn.Clicked() { log(Info, "Clicked ", btn.Label) // don't block UI thread on decryption attempt @@ -421,11 +429,13 @@ func eventLoop() { } }(pathnames[i]) } + return ret }) } mux.Unlock() + return ret }) - flex.Layout(gtx, c1, c2) + ret := flex.Layout(gtx, c1, c2) x := time.Since(overlayStart).Seconds() if x >= fade1b && x < start2 && animating { animOff() @@ -463,10 +473,9 @@ func eventLoop() { overlay.Background = darkgray } gtx.Constraints = margincs - al := layout.Align(layout.SE) - al.Layout(gtx, func() { - gtx.Constraints.Width.Min = gtx.Constraints.Width.Max - overlay.Layout(gtx) + layout.SE.Layout(gtx, func(gtx C) D { + gtx.Constraints.Min.X = gtx.Constraints.Max.X + return overlay.Layout(gtx) }) } if x > start2 && x < fade2a { @@ -475,6 +484,7 @@ func eventLoop() { if animating && x > end { animOff() } + return ret } updateBtn := &Button{ @@ -493,12 +503,12 @@ func eventLoop() { Background: gray, } - idPage = func() { + idPage = func(gtx C) D { if !animating { animOn() } - c2 := layout.Rigid(func() { - idLabel.Layout(gtx) + c2 := layout.Rigid(func(gtx C) D { + return idLabel.Layout(gtx) }) var c3 layout.FlexChild var c4 layout.FlexChild @@ -506,17 +516,17 @@ func eventLoop() { var c6 layout.FlexChild var c7 layout.FlexChild if len(idBtns) == 0 { - c3 = layout.Rigid(func() { - updateBtn.Layout(gtx) + c3 = layout.Rigid(func(gtx C) D { + return updateBtn.Layout(gtx) }) if updateBtn.Clicked() { updateIdBtns() w.Invalidate() } - c4 = layout.Rigid(func() { - th.Editor("id").Layout(gtx, idEd) + c4 = layout.Rigid(func(gtx C) D { + return material.Editor(th, idEd, "id").Layout(gtx) }) - for _, e := range idEd.Events(gtx) { + for _, e := range idEd.Events() { switch e.(type) { case widget.SubmitEvent: log(Info, "Submit") @@ -524,27 +534,28 @@ func eventLoop() { page = listPage } } - c5 = layout.Rigid(func() { - idSubmitBtn.Layout(gtx) + c5 = layout.Rigid(func(gtx C) D { + return idSubmitBtn.Layout(gtx) }) if idSubmitBtn.Clicked() { store.Id = idEd.Text() page = listPage } - c6 = layout.Rigid(func() { - noidLabel.Layout(gtx) + c6 = layout.Rigid(func(gtx C) D { + return noidLabel.Layout(gtx) }) } else { - c3 = layout.Rigid(func() { }) - c4 = layout.Rigid(func() { }) - c5 = layout.Rigid(func() { }) - c6 = layout.Rigid(func() { }) + c3 = layout.Rigid(func(gtx C) D { return D{} }) + c4 = layout.Rigid(func(gtx C) D { return D{} }) + c5 = layout.Rigid(func(gtx C) D { return D{} }) + c6 = layout.Rigid(func(gtx C) D { return D{} }) } - c7 = layout.Rigid(func() { + c7 = layout.Rigid(func(gtx C) D { + var ret D if len(idBtns) > 0 { // still zero after update for i := 0; i < len(idBtns); i++ { - lst.Layout(gtx, len(idBtns), func(i int) { - idBtns[i].Layout(gtx) + ret = lst.Layout(gtx, len(idBtns), func(gtx C, i int) D { + return idBtns[i].Layout(gtx) }) } for _, btn := range idBtns { @@ -557,8 +568,9 @@ func eventLoop() { } } } + return ret }) - flex.Layout(gtx, c1, c2, c3, c4, c5, c6, c7) + return flex.Layout(gtx, c1, c2, c3, c4, c5, c6, c7) } var insName, insValue string @@ -596,41 +608,40 @@ func eventLoop() { passvalEd.SetText(string(pw)) } - insertPage = func() { - c2 := layout.Rigid(func() { insertLabel.Layout(gtx) }) - c3 := layout.Rigid(func() { passnameLabel.Layout(gtx) }) - c4 := layout.Rigid(func() { th.Editor("name").Layout(gtx, passnameEd) }) - c5 := layout.Rigid(func() { passvalLabel.Layout(gtx) }) - c6 := layout.Rigid(func() { th.Editor("password").Layout(gtx, passvalEd) }) + insertPage = func(gtx C) D { + c2 := layout.Rigid(func(gtx C) D { return insertLabel.Layout(gtx) }) + c3 := layout.Rigid(func(gtx C) D { return passnameLabel.Layout(gtx) }) + c4 := layout.Rigid(func(gtx C) D { return material.Editor(th, passnameEd, "name").Layout(gtx) }) + c5 := layout.Rigid(func(gtx C) D { return passvalLabel.Layout(gtx) }) + c6 := layout.Rigid(func(gtx C) D { return material.Editor(th, passvalEd, "password").Layout(gtx) }) btnflx := &layout.Flex{Axis: layout.Horizontal} - al := layout.Align(layout.E) - c7 := layout.Rigid(func() { - bc1 := layout.Rigid(func() { lBtn.Layout(gtx) }) - bc2 := layout.Rigid(func() { - gtx.Constraints.Width.Min = 60 - th.Editor("len").Layout(gtx, lenEd) + c7 := layout.Rigid(func(gtx C) D { + bc1 := layout.Rigid(func(gtx C) D { return lBtn.Layout(gtx) }) + bc2 := layout.Rigid(func(gtx C) D { + gtx.Constraints.Min.X = 60 + return material.Editor(th, lenEd, "len").Layout(gtx) }) - bc3 := layout.Rigid(func() { rBtn.Layout(gtx) }) - bc4 := layout.Rigid(func() { symBtn.Layout(gtx) }) - bc5 := layout.Rigid(func() { numBtn.Layout(gtx) }) - bc6 := layout.Rigid(func() { genBtn.Layout(gtx) }) + bc3 := layout.Rigid(func(gtx C) D { return rBtn.Layout(gtx) }) + bc4 := layout.Rigid(func(gtx C) D { return symBtn.Layout(gtx) }) + bc5 := layout.Rigid(func(gtx C) D { return numBtn.Layout(gtx) }) + bc6 := layout.Rigid(func(gtx C) D { return genBtn.Layout(gtx) }) - al.Layout(gtx, func() { - btnflx.Layout(gtx, bc1, bc2, bc3, bc4, bc5, bc6) + return layout.E.Layout(gtx, func(gtx C) D { + return btnflx.Layout(gtx, bc1, bc2, bc3, bc4, bc5, bc6) }) }) - c8 := layout.Rigid(func() { - bc1 := layout.Rigid(func() { backBtn.Layout(gtx) }) - bc2 := layout.Rigid(func() { saveBtn.Layout(gtx) }) - al.Layout(gtx, func() { - btnflx.Layout(gtx, bc1, bc2) + c8 := layout.Rigid(func(gtx C) D { + bc1 := layout.Rigid(func(gtx C) D { return backBtn.Layout(gtx) }) + bc2 := layout.Rigid(func(gtx C) D { return saveBtn.Layout(gtx) }) + return layout.E.Layout(gtx, func(gtx C) D { + return btnflx.Layout(gtx, bc1, bc2) }) }) - flex.Layout(gtx, c1, c2, c3, c4, c5, c6, c7, c8) + ret := flex.Layout(gtx, c1, c2, c3, c4, c5, c6, c7, c8) if lBtn.Clicked() { l, _ := strconv.Atoi(lenEd.Text()) @@ -673,7 +684,7 @@ func eventLoop() { log(Info, "Password exists") page = confirmPage w.Invalidate() - return + return ret } } //Do not block the UI thread. @@ -684,23 +695,23 @@ func eventLoop() { } }() } + return ret } - confirmPage = func() { - c2 := layout.Rigid(func() { - confirmLabel.Layout(gtx) + confirmPage = func(gtx C) D { + c2 := layout.Rigid(func(gtx C) D { + return confirmLabel.Layout(gtx) }) - al := layout.Align(layout.E) btnflx := &layout.Flex{Axis: layout.Horizontal} - c3 := layout.Rigid(func() { - bc1 := layout.Rigid(func() { backBtn.Layout(gtx) }) - bc2 := layout.Rigid(func() { yesBtn.Layout(gtx) }) + c3 := layout.Rigid(func(gtx C) D { + bc1 := layout.Rigid(func(gtx C) D { return backBtn.Layout(gtx) }) + bc2 := layout.Rigid(func(gtx C) D { return yesBtn.Layout(gtx) }) - al.Layout(gtx, func() { - btnflx.Layout(gtx, bc1, bc2) + return layout.E.Layout(gtx, func(gtx C) D { + return btnflx.Layout(gtx, bc1, bc2) }) }) - flex.Layout(gtx, c1, c2, c3) + ret := flex.Layout(gtx, c1, c2, c3) if backBtn.Clicked() { w.Invalidate() @@ -716,26 +727,26 @@ func eventLoop() { } }() } + return ret } - confPage = func() { - c2 := layout.Rigid(func() { storeDirLabel.Layout(gtx) }) - c3 := layout.Rigid(func() { th.Editor("directory").Layout(gtx, storeDirEd) }) + confPage = func(gtx C) D { + c2 := layout.Rigid(func(gtx C) D { return storeDirLabel.Layout(gtx) }) + c3 := layout.Rigid(func(gtx C) D { return material.Editor(th, storeDirEd, "directory").Layout(gtx) }) - al := layout.Align(layout.E) - c4 := layout.Rigid(func() { + c4 := layout.Rigid(func(gtx C) D { btnflx := &layout.Flex{Axis: layout.Horizontal} - bc1 := layout.Rigid(func() { - backBtn.Layout(gtx) + bc1 := layout.Rigid(func(gtx C) D { + return backBtn.Layout(gtx) }) - bc2 := layout.Rigid(func() { - saveBtn.Layout(gtx) + bc2 := layout.Rigid(func(gtx C) D { + return saveBtn.Layout(gtx) }) - al.Layout(gtx, func() { - btnflx.Layout(gtx, bc1, bc2) + return layout.E.Layout(gtx, func(gtx C) D { + return btnflx.Layout(gtx, bc1, bc2) }) }) - flex.Layout(gtx, c1, c2, c3, c4) + ret := flex.Layout(gtx, c1, c2, c3, c4) if backBtn.Clicked() { log(Info, "Back") @@ -757,33 +768,33 @@ func eventLoop() { w.Invalidate() page = listPage } + return ret } - promptPage = func() { + promptPage = func(gtx C) D { submit := false - for _, e := range promptEd.Events(gtx) { + for _, e := range promptEd.Events() { switch e.(type) { case widget.SubmitEvent: log(Info, "Submit") submit = true } } - c2 := layout.Rigid(func() { promptLabel.Layout(gtx) }) - c3 := layout.Rigid(func() { th.Editor("password").Layout(gtx, promptEd) }) - c4 := layout.Rigid(func() { - al := layout.Align(layout.E) + c2 := layout.Rigid(func(gtx C) D { return promptLabel.Layout(gtx) }) + c3 := layout.Rigid(func(gtx C) D { return material.Editor(th, promptEd, "password").Layout(gtx) }) + c4 := layout.Rigid(func(gtx C) D { btnflx := &layout.Flex{Axis: layout.Horizontal} - bc1 := layout.Rigid(func() { - backBtn.Layout(gtx) + bc1 := layout.Rigid(func(gtx C) D { + return backBtn.Layout(gtx) }) - bc2 := layout.Rigid(func() { - okBtn.Layout(gtx) + bc2 := layout.Rigid(func(gtx C) D { + return okBtn.Layout(gtx) }) - al.Layout(gtx, func() { - btnflx.Layout(gtx, bc1, bc2) + return layout.E.Layout(gtx, func(gtx C) D { + return btnflx.Layout(gtx, bc1, bc2) }) }) - flex.Layout(gtx, c1, c2, c3, c4) + ret := flex.Layout(gtx, c1, c2, c3, c4) if submit || okBtn.Clicked() { log(Info, "Ok") @@ -801,6 +812,7 @@ func eventLoop() { w.Invalidate() page = listPage } + return ret } page = listPage @@ -832,31 +844,31 @@ func eventLoop() { }() } case system.FrameEvent: - gtx.Reset(e.Config, e.Size) + gtx := layout.NewContext(&ops, e) sysinset.Top = e.Insets.Top sysinset.Bottom = e.Insets.Bottom sysinset.Left = e.Insets.Left sysinset.Right = e.Insets.Right - sysinset.Layout(gtx, func() { - margin.Layout(gtx, func() { + sysinset.Layout(gtx, func(gtx C) D { + return margin.Layout(gtx, func(gtx C) D { margincs = gtx.Constraints - c1 = layout.Rigid(func() { - ct2 := layout.Rigid(func() { - plusBtn.Layout(gtx) + c1 = layout.Rigid(func(gtx C) D { + ct2 := layout.Rigid(func(gtx C) D { + return plusBtn.Layout(gtx) }) - ct3 := layout.Rigid(func() { - dotsBtn.Layout(gtx) + ct3 := layout.Rigid(func(gtx C) D { + return dotsBtn.Layout(gtx) }) - ct1 := layout.Flexed(1.0, func() { - gtx.Constraints.Width.Min = gtx.Constraints.Width.Max - title.Layout(gtx) + ct1 := layout.Flexed(1.0, func(gtx C) D { + gtx.Constraints.Min.X = gtx.Constraints.Max.X + return title.Layout(gtx) }) - titleflex.Layout(gtx, ct1, ct2, ct3) + return titleflex.Layout(gtx, ct1, ct2, ct3) }) - page() + return page(gtx) }) }) @@ -872,6 +884,8 @@ func eventLoop() { page = insertPage } e.Frame(gtx.Ops) + default: + handleEvent(e) } if x == 100 { x = 0 diff --git a/cmd/passgo-gui/ui.go b/cmd/passgo-gui/ui.go index 520e4d2..2f0f60d 100644 --- a/cmd/passgo-gui/ui.go +++ b/cmd/passgo-gui/ui.go @@ -12,6 +12,7 @@ import ( "gioui.org/op/paint" "gioui.org/text" "gioui.org/unit" + "gioui.org/widget/material" ) var ( @@ -30,23 +31,24 @@ type Overlay struct { Alignment text.Alignment } -func (b *Overlay) Layout(gtx *layout.Context) { +func (b *Overlay) Layout(gtx C) D { ins := layout.UniformInset(unit.Dp(1)) - ins.Layout(gtx, func() { + return ins.Layout(gtx, func(gtx C) D { st := layout.Stack{} - c2 := layout.Stacked(func() { - l := th.Label(b.Size, b.Text) + c2 := layout.Stacked(func(gtx C) D { + l := material.Label(th, b.Size, b.Text) ins := layout.UniformInset(unit.Dp(4)) l.Color = b.Color - ins.Layout(gtx, func() { - l.Layout(gtx) + ret := ins.Layout(gtx, func(gtx C) D { + return l.Layout(gtx) }) - pointer.Rect(image.Rect(0, 0, gtx.Dimensions.Size.X, gtx.Dimensions.Size.Y)).Add(gtx.Ops) + pointer.Rect(image.Rect(0, 0, ret.Size.X, ret.Size.Y)).Add(gtx.Ops) + return ret }) - c1 := layout.Expanded(func() { - layoutRRect(b.Background, gtx) + c1 := layout.Expanded(func(gtx C) D { + return layoutRRect(b.Background, gtx) }) - st.Layout(gtx, c1, c2) + return st.Layout(gtx, c1, c2) }) } @@ -66,23 +68,23 @@ type Button struct { clicked bool } -func layoutRRect(col color.RGBA, gtx *layout.Context) { +func layoutRRect(col color.RGBA, gtx C) D { r := float32(gtx.Px(unit.Dp(4))) - sz := image.Point{X: gtx.Constraints.Width.Min, Y: gtx.Constraints.Height.Min} + sz := image.Point{X: gtx.Constraints.Min.X, Y: gtx.Constraints.Min.Y} w, h := float32(sz.X), float32(sz.Y) rect := f32.Rectangle{ f32.Point{0, 0}, f32.Point{w, h}, } //clip.RoundRect(gtx.Ops, rect, r, r, r, r) - clip.Rect{Rect: rect, NE: r, NW: r, SE: r, SW: r}.Op(gtx.Ops).Add(gtx.Ops) + clip.RRect{Rect: rect, NE: r, NW: r, SE: r, SW: r}.Add(gtx.Ops) paint.ColorOp{Color: col}.Add(gtx.Ops) paint.PaintOp{Rect: f32.Rectangle{Max: f32.Point{X: w, Y: h}}}.Add(gtx.Ops) - gtx.Dimensions = layout.Dimensions{Size: sz} + return layout.Dimensions{Size: sz} } -func (b *Button) Layout(gtx *layout.Context) { - mwidth := gtx.Constraints.Width.Min +func (b *Button) Layout(gtx C) D { + mwidth := gtx.Constraints.Min.X b.clicked = false for _, ev := range b.Click.Events(gtx) { if ev.Type == gesture.TypeClick { @@ -90,23 +92,24 @@ func (b *Button) Layout(gtx *layout.Context) { } } ins := layout.UniformInset(unit.Dp(1)) - ins.Layout(gtx, func() { + return ins.Layout(gtx, func(gtx C) D { st := layout.Stack{} - c2 := layout.Stacked(func() { - l := th.Label(b.Size, b.Label) + c2 := layout.Stacked(func(gtx C) D { + l := material.Label(th, b.Size, b.Label) ins := layout.UniformInset(unit.Dp(4)) //paint.ColorOp{Color: b.Color}.Add(ops) - ins.Layout(gtx, func() { - l.Layout(gtx) + ret := ins.Layout(gtx, func(gtx C) D { + return l.Layout(gtx) }) - pointer.Rect(image.Rect(0, 0, gtx.Dimensions.Size.X, gtx.Dimensions.Size.Y)).Add(gtx.Ops) + pointer.Rect(image.Rect(0, 0, ret.Size.X, ret.Size.Y)).Add(gtx.Ops) b.Click.Add(gtx.Ops) + return ret }) - c1 := layout.Expanded(func() { - gtx.Constraints.Width.Min = mwidth - layoutRRect(b.Background, gtx) + c1 := layout.Expanded(func(gtx C) D { + gtx.Constraints.Min.X = mwidth + return layoutRRect(b.Background, gtx) }) - st.Layout(gtx, c1, c2) + return st.Layout(gtx, c1, c2) }) } diff --git a/go.mod b/go.mod index 79b8e47..549aada 100644 --- a/go.mod +++ b/go.mod @@ -3,12 +3,13 @@ module git.wow.st/gmp/passgo go 1.13 require ( - gioui.org v0.0.0-20191218180754-3dd7c8121c67 + gioui.org v0.0.0-20200827132523-d57edbb49d3c git.wow.st/gmp/clip v0.0.0-20191001134149-1458ba6a7cf5 + git.wow.st/gmp/jni v0.0.0-20200827154156-014cd5c7c4c0 git.wow.st/gmp/rand v0.0.0-20191001220155-a81bebfaf8b0 github.com/fsnotify/fsnotify v1.4.7 github.com/jcmdev0/gpgagent v0.0.0-20180509014935-5601b32d936c golang.org/x/crypto v0.0.0-20191122220453-ac88ee75c92c - golang.org/x/image v0.0.0-20190802002840-cff245a6509b + golang.org/x/image v0.0.0-20200618115811-c13761719519 gopkg.in/yaml.v2 v2.2.7 ) diff --git a/go.sum b/go.sum index a6af5d7..e2d84c7 100644 --- a/go.sum +++ b/go.sum @@ -3,8 +3,13 @@ gioui.org v0.0.0-20191126175243-2ca2e5462f16 h1:p31rtmKm51xpj2QtqGNlljAyHEP1oStU gioui.org v0.0.0-20191126175243-2ca2e5462f16/go.mod h1:KqFFi2Dq5gYA3FJ0sDOt8OBXoMsuxMtE8v2f0JExXAY= gioui.org v0.0.0-20191218180754-3dd7c8121c67 h1:y9md+l1thtMqJu/ulhF1Upv3pnOpGotpJDssO8X3LbY= gioui.org v0.0.0-20191218180754-3dd7c8121c67/go.mod h1:KqFFi2Dq5gYA3FJ0sDOt8OBXoMsuxMtE8v2f0JExXAY= +gioui.org v0.0.0-20200827132523-d57edbb49d3c h1:TY1A2dzvxASVC+crmYfkDF8JNkd4rKaXZG2A4WboyU4= +gioui.org v0.0.0-20200827132523-d57edbb49d3c/go.mod h1:Y+uS7hHMvku1Q+ooaoq6fYD5B2LGoT8JtFgvmYmRzTw= +gioui.org v0.0.0-20200829162755-829ee4559c5a h1:mciXRGzQwU0TbgCILZzl6L1nYIWU31lDGIb+8RYige8= git.wow.st/gmp/clip v0.0.0-20191001134149-1458ba6a7cf5 h1:OKeTjZST+/TKvtdA258NXJH+/gIx/xwyZxKrAezNFvk= git.wow.st/gmp/clip v0.0.0-20191001134149-1458ba6a7cf5/go.mod h1:NLdpaBoMQNFqncwP8OVRNWUDw1Kt9XWm3snfT7cXu24= +git.wow.st/gmp/jni v0.0.0-20200827154156-014cd5c7c4c0 h1:Ynp3h+TC8k1clvf45D28VFQlmy0bPx8M/MG5bB24Vj8= +git.wow.st/gmp/jni v0.0.0-20200827154156-014cd5c7c4c0/go.mod h1:+axXBRUTIDlCeE73IKeD/os7LoEnTKdkp8/gQOFjqyo= git.wow.st/gmp/rand v0.0.0-20191001220155-a81bebfaf8b0 h1:08wP00wvbDINsct1fzKV1xGGLvvtNsSb2X4CtIdpBzM= git.wow.st/gmp/rand v0.0.0-20191001220155-a81bebfaf8b0/go.mod h1:8+2Gwnrpc5yuk8Wp6cBhxvGcNLumYiPbQ7n0SQ8h29A= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= @@ -23,6 +28,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= @@ -33,6 +40,8 @@ golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9 h1:1/DFK4b7JH8DmkqhUk48onnSfrPzImPoVxuomtbT2nk= +golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/tools v0.0.0-20190927191325-030b2cf1153e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= diff --git a/impl_android.go b/impl_android.go index cf8a8b8..f33fcd5 100644 --- a/impl_android.go +++ b/impl_android.go @@ -1,6 +1,6 @@ //+build android //go:generate mkdir -p classes -//go:generate javac -bootclasspath $ANDROID_HOME/platforms/android-29/android.jar -classpath openpgp-api.jar -d classes PgpConnect.java +//go:generate javac -bootclasspath $ANDROID_HOME/platforms/android-29/android.jar -classpath openpgp-api.jar -d classes PgpConnect.java Foo.java //go:generate jar cf PgpConnect.jar -C classes . //go:generate rm -rf classes @@ -19,13 +19,15 @@ import ( "log" "strings" "sync" + "unsafe" "gioui.org/app" _ "gioui.org/app/permission/storage" + //"git.wow.st/gmp/jni" ) var ( - h *app.Handle + jvm uintptr waitch chan struct{} //w *app.Window pgp PGP @@ -40,16 +42,18 @@ func init() { func Java_st_wow_git_passgo_PgpConnect_installComplete(env *C.JNIEnv, class C.jclass, p C.jobject) { log.Printf("InstallComplete()") pgp = PGP(C.NewGlobalRef(env, p)) - h = app.PlatformHandle() - SetJVM(h.JVM) installCompleteOnce.Do(func() { close(waitch) }) } -func InitPgp(w *app.Window) { +func InitPgp(view uintptr) { log.Printf("InitPgp()") - w.RegisterFragment("st/wow/git/passgo/PgpConnect") + jvm = app.JavaVM() + SetJVM(jvm) // why? + RunInJVM(func(env *JNIEnv) { + C.registerFragment(env, (C.jobject)(unsafe.Pointer(view))) + }) } func stopPgp() { diff --git a/jni_android.c b/jni_android.c index ecf7865..c1c63d3 100644 --- a/jni_android.c +++ b/jni_android.c @@ -1,16 +1,30 @@ -#include +//#include #include #include #include "jni_android.h" #include "_cgo_export.h" +void +registerFragment(JNIEnv *env, jobject view) { + jclass cls = (*env)->GetObjectClass(env, view); + jmethodID mid = (*env)->GetMethodID(env, cls, "getContext", "()Landroid/content/Context;"); + jobject ctx = (*env)->CallObjectMethod(env, view, mid); + cls = (*env)->GetObjectClass(env, ctx); + mid = (*env)->GetMethodID(env, cls, "getClassLoader", "()Ljava/lang/ClassLoader;"); + jobject loader = (*env)->CallObjectMethod(env, ctx, mid); + cls = (*env)->GetObjectClass(env, loader); + mid = (*env)->GetMethodID(env, cls, "findClass", "(Ljava/lang/String;)Ljava/lang/Class;"); + jstring str = (*env)->NewStringUTF(env, "st/wow/git/passgo/PgpConnect"); + cls = (*env)->CallObjectMethod(env, loader, mid, str); + mid = (*env)->GetMethodID(env, cls, "", "(Landroid/view/View;)V"); + jobject inst = (*env)->NewObject(env, cls, mid, view); +} + void GetId(JNIEnv* env, jobject p, int chint) { jclass cls = (*env)->GetObjectClass(env, p); - printf("GetId(): cls = %p", cls); jmethodID mid = (*env)->GetMethodID(env, cls, "GetId", "(I)V"); - printf("GetId(): mid = %p", mid); (*env)->CallObjectMethod(env, p, mid, chint); } diff --git a/jni_android.go b/jni_android.go index 722fd33..33cffc5 100644 --- a/jni_android.go +++ b/jni_android.go @@ -1,7 +1,7 @@ package passgo /* -#cgo LDFLAGS: -landroid +#cgo LDFLAGS: -landroid -llog #include #include "jni_android.h" diff --git a/jni_android.h b/jni_android.h index c89eb22..ee5eb43 100644 --- a/jni_android.h +++ b/jni_android.h @@ -1,5 +1,6 @@ #include +void registerFragment(JNIEnv *env, jobject view); void GetId(JNIEnv* env, jobject p, int chint); void Decrypt(JNIEnv* env, jobject p, char* cdata, int datalen, int chint); void Encrypt(JNIEnv* env, jobject p, char* cid, int idlen, char* cdata, int datalen, int chint);