event: rename event.Foo to foo.Event.
Fixes golang/go#10444 Change-Id: Ie5a8ab8a09b1b1a4f7037da7cf945d39ab6a98fc Reviewed-on: https://go-review.googlesource.com/12225 Reviewed-by: David Crawshaw <crawshaw@golang.org>
This commit is contained in:
parent
a2120ea61f
commit
e4c6af17e3
46
app/app.go
46
app/app.go
@ -8,6 +8,10 @@ package app
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"golang.org/x/mobile/event"
|
"golang.org/x/mobile/event"
|
||||||
|
"golang.org/x/mobile/event/config"
|
||||||
|
"golang.org/x/mobile/event/lifecycle"
|
||||||
|
"golang.org/x/mobile/event/paint"
|
||||||
|
"golang.org/x/mobile/event/touch"
|
||||||
"golang.org/x/mobile/gl"
|
"golang.org/x/mobile/gl"
|
||||||
_ "golang.org/x/mobile/internal/mobileinit"
|
_ "golang.org/x/mobile/internal/mobileinit"
|
||||||
)
|
)
|
||||||
@ -24,12 +28,12 @@ func Main(f func(App)) {
|
|||||||
type App interface {
|
type App interface {
|
||||||
// Events returns the events channel. It carries events from the system to
|
// Events returns the events channel. It carries events from the system to
|
||||||
// the app. The type of such events include:
|
// the app. The type of such events include:
|
||||||
// - event.Config
|
// - config.Event
|
||||||
// - event.Draw
|
// - lifecycle.Event
|
||||||
// - event.Lifecycle
|
// - paint.Event
|
||||||
// - event.Touch
|
// - touch.Event
|
||||||
// from the golang.org/x/mobile/events package. Other packages may define
|
// from the golang.org/x/mobile/event/etc packages. Other packages may
|
||||||
// other event types that are carried on this channel.
|
// define other event types that are carried on this channel.
|
||||||
Events() <-chan interface{}
|
Events() <-chan interface{}
|
||||||
|
|
||||||
// Send sends an event on the events channel. It does not block.
|
// Send sends an event on the events channel. It does not block.
|
||||||
@ -40,7 +44,7 @@ type App interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
lifecycleStage = event.LifecycleStageDead
|
lifecycleStage = lifecycle.StageDead
|
||||||
pixelsPerPt = float32(1)
|
pixelsPerPt = float32(1)
|
||||||
|
|
||||||
eventsOut = make(chan interface{})
|
eventsOut = make(chan interface{})
|
||||||
@ -48,11 +52,11 @@ var (
|
|||||||
endDraw = make(chan struct{}, 1)
|
endDraw = make(chan struct{}, 1)
|
||||||
)
|
)
|
||||||
|
|
||||||
func sendLifecycle(to event.LifecycleStage) {
|
func sendLifecycle(to lifecycle.Stage) {
|
||||||
if lifecycleStage == to {
|
if lifecycleStage == to {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
eventsIn <- event.Lifecycle{
|
eventsIn <- lifecycle.Event{
|
||||||
From: lifecycleStage,
|
From: lifecycleStage,
|
||||||
To: to,
|
To: to,
|
||||||
}
|
}
|
||||||
@ -157,31 +161,31 @@ func pump(dst chan interface{}) (src chan interface{}) {
|
|||||||
// Deprecated: call Main directly instead.
|
// Deprecated: call Main directly instead.
|
||||||
func Run(cb Callbacks) {
|
func Run(cb Callbacks) {
|
||||||
Main(func(a App) {
|
Main(func(a App) {
|
||||||
var c event.Config
|
var c config.Event
|
||||||
for e := range a.Events() {
|
for e := range a.Events() {
|
||||||
switch e := event.Filter(e).(type) {
|
switch e := event.Filter(e).(type) {
|
||||||
case event.Lifecycle:
|
case lifecycle.Event:
|
||||||
switch e.Crosses(event.LifecycleStageVisible) {
|
switch e.Crosses(lifecycle.StageVisible) {
|
||||||
case event.ChangeOn:
|
case lifecycle.CrossOn:
|
||||||
if cb.Start != nil {
|
if cb.Start != nil {
|
||||||
cb.Start()
|
cb.Start()
|
||||||
}
|
}
|
||||||
case event.ChangeOff:
|
case lifecycle.CrossOff:
|
||||||
if cb.Stop != nil {
|
if cb.Stop != nil {
|
||||||
cb.Stop()
|
cb.Stop()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case event.Config:
|
case config.Event:
|
||||||
if cb.Config != nil {
|
if cb.Config != nil {
|
||||||
cb.Config(e, c)
|
cb.Config(e, c)
|
||||||
}
|
}
|
||||||
c = e
|
c = e
|
||||||
case event.Draw:
|
case paint.Event:
|
||||||
if cb.Draw != nil {
|
if cb.Draw != nil {
|
||||||
cb.Draw(c)
|
cb.Draw(c)
|
||||||
}
|
}
|
||||||
a.EndDraw()
|
a.EndDraw()
|
||||||
case event.Touch:
|
case touch.Event:
|
||||||
if cb.Touch != nil {
|
if cb.Touch != nil {
|
||||||
cb.Touch(e, c)
|
cb.Touch(e, c)
|
||||||
}
|
}
|
||||||
@ -231,13 +235,13 @@ type Callbacks struct {
|
|||||||
//
|
//
|
||||||
// Drawing is done into a framebuffer, which is then swapped onto the
|
// Drawing is done into a framebuffer, which is then swapped onto the
|
||||||
// screen when Draw returns. It is called 60 times a second.
|
// screen when Draw returns. It is called 60 times a second.
|
||||||
Draw func(event.Config)
|
Draw func(config.Event)
|
||||||
|
|
||||||
// Touch is called by the app when a touch event occurs.
|
// Touch is called by the app when a touch event occurs.
|
||||||
Touch func(event.Touch, event.Config)
|
Touch func(touch.Event, config.Event)
|
||||||
|
|
||||||
// Config is called by the app when configuration has changed.
|
// Config is called by the app when configuration has changed.
|
||||||
Config func(new, old event.Config)
|
Config func(new, old config.Event)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: do this for all build targets, not just linux (x11 and Android)? If
|
// TODO: do this for all build targets, not just linux (x11 and Android)? If
|
||||||
@ -247,7 +251,7 @@ type Callbacks struct {
|
|||||||
// KitKat). If only x11 needs this, should we move this to x11.go??
|
// KitKat). If only x11 needs this, should we move this to x11.go??
|
||||||
func registerGLViewportFilter() {
|
func registerGLViewportFilter() {
|
||||||
event.RegisterFilter(func(e interface{}) interface{} {
|
event.RegisterFilter(func(e interface{}) interface{} {
|
||||||
if e, ok := e.(event.Config); ok {
|
if e, ok := e.(config.Event); ok {
|
||||||
w := int(e.PixelsPerPt * float32(e.Width))
|
w := int(e.PixelsPerPt * float32(e.Width))
|
||||||
h := int(e.PixelsPerPt * float32(e.Height))
|
h := int(e.PixelsPerPt * float32(e.Height))
|
||||||
gl.Viewport(0, 0, w, h)
|
gl.Viewport(0, 0, w, h)
|
||||||
|
@ -27,7 +27,10 @@ import (
|
|||||||
"runtime"
|
"runtime"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"golang.org/x/mobile/event"
|
"golang.org/x/mobile/event/config"
|
||||||
|
"golang.org/x/mobile/event/lifecycle"
|
||||||
|
"golang.org/x/mobile/event/paint"
|
||||||
|
"golang.org/x/mobile/event/touch"
|
||||||
"golang.org/x/mobile/geom"
|
"golang.org/x/mobile/geom"
|
||||||
"golang.org/x/mobile/gl"
|
"golang.org/x/mobile/gl"
|
||||||
)
|
)
|
||||||
@ -75,7 +78,7 @@ func loop(ctx C.GLintptr) {
|
|||||||
C.makeCurrentContext(ctx)
|
C.makeCurrentContext(ctx)
|
||||||
|
|
||||||
for range draw {
|
for range draw {
|
||||||
eventsIn <- event.Draw{}
|
eventsIn <- paint.Event{}
|
||||||
loop1:
|
loop1:
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
@ -112,7 +115,7 @@ var windowHeight geom.Pt
|
|||||||
func setGeom(ppp float32, width, height int) {
|
func setGeom(ppp float32, width, height int) {
|
||||||
pixelsPerPt = ppp
|
pixelsPerPt = ppp
|
||||||
windowHeight = geom.Pt(float32(height) / pixelsPerPt)
|
windowHeight = geom.Pt(float32(height) / pixelsPerPt)
|
||||||
eventsIn <- event.Config{
|
eventsIn <- config.Event{
|
||||||
Width: geom.Pt(float32(width) / pixelsPerPt),
|
Width: geom.Pt(float32(width) / pixelsPerPt),
|
||||||
Height: windowHeight,
|
Height: windowHeight,
|
||||||
PixelsPerPt: pixelsPerPt,
|
PixelsPerPt: pixelsPerPt,
|
||||||
@ -121,13 +124,13 @@ func setGeom(ppp float32, width, height int) {
|
|||||||
|
|
||||||
var touchEvents struct {
|
var touchEvents struct {
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
pending []event.Touch
|
pending []touch.Event
|
||||||
}
|
}
|
||||||
|
|
||||||
func sendTouch(c event.Change, x, y float32) {
|
func sendTouch(t touch.Type, x, y float32) {
|
||||||
eventsIn <- event.Touch{
|
eventsIn <- touch.Event{
|
||||||
ID: 0,
|
Sequence: 0,
|
||||||
Change: c,
|
Type: t,
|
||||||
Loc: geom.Point{
|
Loc: geom.Point{
|
||||||
X: geom.Pt(x / pixelsPerPt),
|
X: geom.Pt(x / pixelsPerPt),
|
||||||
Y: windowHeight - geom.Pt(y/pixelsPerPt),
|
Y: windowHeight - geom.Pt(y/pixelsPerPt),
|
||||||
@ -136,22 +139,22 @@ func sendTouch(c event.Change, x, y float32) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//export eventMouseDown
|
//export eventMouseDown
|
||||||
func eventMouseDown(x, y float32) { sendTouch(event.ChangeOn, x, y) }
|
func eventMouseDown(x, y float32) { sendTouch(touch.TypeStart, x, y) }
|
||||||
|
|
||||||
//export eventMouseDragged
|
//export eventMouseDragged
|
||||||
func eventMouseDragged(x, y float32) { sendTouch(event.ChangeNone, x, y) }
|
func eventMouseDragged(x, y float32) { sendTouch(touch.TypeMove, x, y) }
|
||||||
|
|
||||||
//export eventMouseEnd
|
//export eventMouseEnd
|
||||||
func eventMouseEnd(x, y float32) { sendTouch(event.ChangeOff, x, y) }
|
func eventMouseEnd(x, y float32) { sendTouch(touch.TypeEnd, x, y) }
|
||||||
|
|
||||||
//export lifecycleDead
|
//export lifecycleDead
|
||||||
func lifecycleDead() { sendLifecycle(event.LifecycleStageDead) }
|
func lifecycleDead() { sendLifecycle(lifecycle.StageDead) }
|
||||||
|
|
||||||
//export lifecycleAlive
|
//export lifecycleAlive
|
||||||
func lifecycleAlive() { sendLifecycle(event.LifecycleStageAlive) }
|
func lifecycleAlive() { sendLifecycle(lifecycle.StageAlive) }
|
||||||
|
|
||||||
//export lifecycleVisible
|
//export lifecycleVisible
|
||||||
func lifecycleVisible() { sendLifecycle(event.LifecycleStageVisible) }
|
func lifecycleVisible() { sendLifecycle(lifecycle.StageVisible) }
|
||||||
|
|
||||||
//export lifecycleFocused
|
//export lifecycleFocused
|
||||||
func lifecycleFocused() { sendLifecycle(event.LifecycleStageFocused) }
|
func lifecycleFocused() { sendLifecycle(lifecycle.StageFocused) }
|
||||||
|
@ -28,7 +28,10 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"golang.org/x/mobile/event"
|
"golang.org/x/mobile/event/config"
|
||||||
|
"golang.org/x/mobile/event/lifecycle"
|
||||||
|
"golang.org/x/mobile/event/paint"
|
||||||
|
"golang.org/x/mobile/event/touch"
|
||||||
"golang.org/x/mobile/geom"
|
"golang.org/x/mobile/geom"
|
||||||
"golang.org/x/mobile/gl"
|
"golang.org/x/mobile/gl"
|
||||||
)
|
)
|
||||||
@ -95,7 +98,7 @@ func setScreen(scale int) {
|
|||||||
|
|
||||||
//export updateConfig
|
//export updateConfig
|
||||||
func updateConfig(width, height int) {
|
func updateConfig(width, height int) {
|
||||||
eventsIn <- event.Config{
|
eventsIn <- config.Event{
|
||||||
Width: geom.Pt(float32(screenScale*width) / pixelsPerPt),
|
Width: geom.Pt(float32(screenScale*width) / pixelsPerPt),
|
||||||
Height: geom.Pt(float32(screenScale*height) / pixelsPerPt),
|
Height: geom.Pt(float32(screenScale*height) / pixelsPerPt),
|
||||||
PixelsPerPt: pixelsPerPt,
|
PixelsPerPt: pixelsPerPt,
|
||||||
@ -113,11 +116,11 @@ var touchIDs [11]uintptr
|
|||||||
|
|
||||||
var touchEvents struct {
|
var touchEvents struct {
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
pending []event.Touch
|
pending []touch.Event
|
||||||
}
|
}
|
||||||
|
|
||||||
//export sendTouch
|
//export sendTouch
|
||||||
func sendTouch(touch, change uintptr, x, y float32) {
|
func sendTouch(touch, touchType uintptr, x, y float32) {
|
||||||
id := -1
|
id := -1
|
||||||
for i, val := range touchIDs {
|
for i, val := range touchIDs {
|
||||||
if val == touch {
|
if val == touch {
|
||||||
@ -138,14 +141,14 @@ func sendTouch(touch, change uintptr, x, y float32) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
c := event.Change(change)
|
t := touch.Type(touchType)
|
||||||
if c == event.ChangeOff {
|
if t == touch.TypeEnd {
|
||||||
touchIDs[id] = 0
|
touchIDs[id] = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
eventsIn <- event.Touch{
|
eventsIn <- touch.Event{
|
||||||
ID: event.TouchSequenceID(id),
|
Sequence: touch.Sequence(id),
|
||||||
Change: c,
|
Type: t,
|
||||||
Loc: geom.Point{
|
Loc: geom.Point{
|
||||||
X: geom.Pt(x / pixelsPerPt),
|
X: geom.Pt(x / pixelsPerPt),
|
||||||
Y: geom.Pt(y / pixelsPerPt),
|
Y: geom.Pt(y / pixelsPerPt),
|
||||||
@ -159,10 +162,10 @@ func drawgl(ctx uintptr) {
|
|||||||
startedgl = true
|
startedgl = true
|
||||||
C.setContext(unsafe.Pointer(ctx))
|
C.setContext(unsafe.Pointer(ctx))
|
||||||
// TODO(crawshaw): not just on process start.
|
// TODO(crawshaw): not just on process start.
|
||||||
sendLifecycle(event.LifecycleStageFocused)
|
sendLifecycle(lifecycle.StageFocused)
|
||||||
}
|
}
|
||||||
|
|
||||||
eventsIn <- event.Draw{}
|
eventsIn <- paint.Event{}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
|
@ -65,9 +65,9 @@ struct utsname sysInfo;
|
|||||||
drawgl((GoUintptr)self.context);
|
drawgl((GoUintptr)self.context);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CHANGE_NONE 0 // event.ChangeNone
|
#define TOUCH_TYPE_START 0 // touch.TypeStart
|
||||||
#define CHANGE_ON 1 // event.ChangeOn
|
#define TOUCH_TYPE_MOVE 1 // touch.TypeMove
|
||||||
#define CHANGE_OFF 2 // event.ChangeOff
|
#define TOUCH_TYPE_END 2 // touch.TypeEnd
|
||||||
|
|
||||||
static void sendTouches(int change, NSSet* touches) {
|
static void sendTouches(int change, NSSet* touches) {
|
||||||
CGFloat scale = [UIScreen mainScreen].scale;
|
CGFloat scale = [UIScreen mainScreen].scale;
|
||||||
@ -78,15 +78,15 @@ static void sendTouches(int change, NSSet* touches) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {
|
- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {
|
||||||
sendTouches(CHANGE_ON, touches);
|
sendTouches(TOUCH_TYPE_START, touches);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event {
|
- (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event {
|
||||||
sendTouches(CHANGE_NONE, touches);
|
sendTouches(TOUCH_TYPE_MOVE, touches);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event {
|
- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event {
|
||||||
sendTouches(CHANGE_OFF, touches);
|
sendTouches(TOUCH_TYPE_END, touches);
|
||||||
}
|
}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@ -42,15 +42,18 @@ function exits, the app exits.
|
|||||||
"log"
|
"log"
|
||||||
|
|
||||||
"golang.org/x/mobile/app"
|
"golang.org/x/mobile/app"
|
||||||
|
"golang.org/x/mobile/event"
|
||||||
|
"golang.org/x/mobile/event/lifecycle"
|
||||||
|
"golang.org/x/mobile/event/paint"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
app.Main(func(a app.App) {
|
app.Main(func(a app.App) {
|
||||||
for e := range a.Events() {
|
for e := range a.Events() {
|
||||||
switch e := event.Filter(e).(type) {
|
switch e := event.Filter(e).(type) {
|
||||||
case event.Lifecycle:
|
case lifecycle.Event:
|
||||||
// ...
|
// ...
|
||||||
case event.Draw:
|
case paint.Event:
|
||||||
log.Print("Call OpenGL here.")
|
log.Print("Call OpenGL here.")
|
||||||
a.EndDraw()
|
a.EndDraw()
|
||||||
}
|
}
|
||||||
|
@ -84,7 +84,10 @@ import "C"
|
|||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"golang.org/x/mobile/event"
|
"golang.org/x/mobile/event/config"
|
||||||
|
"golang.org/x/mobile/event/lifecycle"
|
||||||
|
"golang.org/x/mobile/event/paint"
|
||||||
|
"golang.org/x/mobile/event/touch"
|
||||||
"golang.org/x/mobile/geom"
|
"golang.org/x/mobile/geom"
|
||||||
"golang.org/x/mobile/gl"
|
"golang.org/x/mobile/gl"
|
||||||
)
|
)
|
||||||
@ -95,16 +98,16 @@ func windowDraw(w *C.ANativeWindow, queue *C.AInputQueue, donec chan struct{}) (
|
|||||||
C.createEGLWindow(w)
|
C.createEGLWindow(w)
|
||||||
|
|
||||||
// TODO: is this needed if we also have the "case <-windowRedrawNeeded:" below??
|
// TODO: is this needed if we also have the "case <-windowRedrawNeeded:" below??
|
||||||
sendLifecycle(event.LifecycleStageFocused)
|
sendLifecycle(lifecycle.StageFocused)
|
||||||
eventsIn <- event.Config{
|
eventsIn <- config.Event{
|
||||||
Width: geom.Pt(float32(C.windowWidth) / pixelsPerPt),
|
Width: geom.Pt(float32(C.windowWidth) / pixelsPerPt),
|
||||||
Height: geom.Pt(float32(C.windowHeight) / pixelsPerPt),
|
Height: geom.Pt(float32(C.windowHeight) / pixelsPerPt),
|
||||||
PixelsPerPt: pixelsPerPt,
|
PixelsPerPt: pixelsPerPt,
|
||||||
}
|
}
|
||||||
if firstWindowDraw {
|
if firstWindowDraw {
|
||||||
firstWindowDraw = false
|
firstWindowDraw = false
|
||||||
// TODO: be more principled about when to send a draw event.
|
// TODO: be more principled about when to send a paint event.
|
||||||
eventsIn <- event.Draw{}
|
eventsIn <- paint.Event{}
|
||||||
}
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
@ -115,21 +118,21 @@ func windowDraw(w *C.ANativeWindow, queue *C.AInputQueue, donec chan struct{}) (
|
|||||||
case <-windowRedrawNeeded:
|
case <-windowRedrawNeeded:
|
||||||
// Re-query the width and height.
|
// Re-query the width and height.
|
||||||
C.querySurfaceWidthAndHeight()
|
C.querySurfaceWidthAndHeight()
|
||||||
sendLifecycle(event.LifecycleStageFocused)
|
sendLifecycle(lifecycle.StageFocused)
|
||||||
eventsIn <- event.Config{
|
eventsIn <- config.Event{
|
||||||
Width: geom.Pt(float32(C.windowWidth) / pixelsPerPt),
|
Width: geom.Pt(float32(C.windowWidth) / pixelsPerPt),
|
||||||
Height: geom.Pt(float32(C.windowHeight) / pixelsPerPt),
|
Height: geom.Pt(float32(C.windowHeight) / pixelsPerPt),
|
||||||
PixelsPerPt: pixelsPerPt,
|
PixelsPerPt: pixelsPerPt,
|
||||||
}
|
}
|
||||||
case <-windowDestroyed:
|
case <-windowDestroyed:
|
||||||
sendLifecycle(event.LifecycleStageAlive)
|
sendLifecycle(lifecycle.StageAlive)
|
||||||
return false
|
return false
|
||||||
case <-gl.WorkAvailable:
|
case <-gl.WorkAvailable:
|
||||||
gl.DoWork()
|
gl.DoWork()
|
||||||
case <-endDraw:
|
case <-endDraw:
|
||||||
// eglSwapBuffers blocks until vsync.
|
// eglSwapBuffers blocks until vsync.
|
||||||
C.eglSwapBuffers(C.display, C.surface)
|
C.eglSwapBuffers(C.display, C.surface)
|
||||||
eventsIn <- event.Draw{}
|
eventsIn <- paint.Event{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -152,22 +155,22 @@ func processEvent(e *C.AInputEvent) {
|
|||||||
case C.AINPUT_EVENT_TYPE_MOTION:
|
case C.AINPUT_EVENT_TYPE_MOTION:
|
||||||
// At most one of the events in this batch is an up or down event; get its index and change.
|
// At most one of the events in this batch is an up or down event; get its index and change.
|
||||||
upDownIndex := C.size_t(C.AMotionEvent_getAction(e)&C.AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> C.AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT
|
upDownIndex := C.size_t(C.AMotionEvent_getAction(e)&C.AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> C.AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT
|
||||||
upDownChange := event.ChangeNone
|
upDownType := touch.TypeMove
|
||||||
switch C.AMotionEvent_getAction(e) & C.AMOTION_EVENT_ACTION_MASK {
|
switch C.AMotionEvent_getAction(e) & C.AMOTION_EVENT_ACTION_MASK {
|
||||||
case C.AMOTION_EVENT_ACTION_DOWN, C.AMOTION_EVENT_ACTION_POINTER_DOWN:
|
case C.AMOTION_EVENT_ACTION_DOWN, C.AMOTION_EVENT_ACTION_POINTER_DOWN:
|
||||||
upDownChange = event.ChangeOn
|
upDownType = touch.TypeStart
|
||||||
case C.AMOTION_EVENT_ACTION_UP, C.AMOTION_EVENT_ACTION_POINTER_UP:
|
case C.AMOTION_EVENT_ACTION_UP, C.AMOTION_EVENT_ACTION_POINTER_UP:
|
||||||
upDownChange = event.ChangeOff
|
upDownType = touch.TypeEnd
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, n := C.size_t(0), C.AMotionEvent_getPointerCount(e); i < n; i++ {
|
for i, n := C.size_t(0), C.AMotionEvent_getPointerCount(e); i < n; i++ {
|
||||||
change := event.ChangeNone
|
t := touch.TypeMove
|
||||||
if i == upDownIndex {
|
if i == upDownIndex {
|
||||||
change = upDownChange
|
t = upDownType
|
||||||
}
|
}
|
||||||
eventsIn <- event.Touch{
|
eventsIn <- touch.Event{
|
||||||
ID: event.TouchSequenceID(C.AMotionEvent_getPointerId(e, i)),
|
Sequence: touch.Sequence(C.AMotionEvent_getPointerId(e, i)),
|
||||||
Change: change,
|
Type: t,
|
||||||
Loc: geom.Point{
|
Loc: geom.Point{
|
||||||
X: geom.Pt(float32(C.AMotionEvent_getX(e, i)) / pixelsPerPt),
|
X: geom.Pt(float32(C.AMotionEvent_getX(e, i)) / pixelsPerPt),
|
||||||
Y: geom.Pt(float32(C.AMotionEvent_getY(e, i)) / pixelsPerPt),
|
Y: geom.Pt(float32(C.AMotionEvent_getY(e, i)) / pixelsPerPt),
|
||||||
|
27
app/x11.go
27
app/x11.go
@ -27,7 +27,10 @@ import (
|
|||||||
"runtime"
|
"runtime"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"golang.org/x/mobile/event"
|
"golang.org/x/mobile/event/config"
|
||||||
|
"golang.org/x/mobile/event/lifecycle"
|
||||||
|
"golang.org/x/mobile/event/paint"
|
||||||
|
"golang.org/x/mobile/event/touch"
|
||||||
"golang.org/x/mobile/geom"
|
"golang.org/x/mobile/geom"
|
||||||
"golang.org/x/mobile/gl"
|
"golang.org/x/mobile/gl"
|
||||||
)
|
)
|
||||||
@ -41,7 +44,7 @@ func main(f func(App)) {
|
|||||||
C.createWindow()
|
C.createWindow()
|
||||||
|
|
||||||
// TODO: send lifecycle events when e.g. the X11 window is iconified or moved off-screen.
|
// TODO: send lifecycle events when e.g. the X11 window is iconified or moved off-screen.
|
||||||
sendLifecycle(event.LifecycleStageFocused)
|
sendLifecycle(lifecycle.StageFocused)
|
||||||
|
|
||||||
donec := make(chan struct{})
|
donec := make(chan struct{})
|
||||||
go func() {
|
go func() {
|
||||||
@ -65,7 +68,7 @@ func main(f func(App)) {
|
|||||||
tc = ticker.C
|
tc = ticker.C
|
||||||
case <-tc:
|
case <-tc:
|
||||||
tc = nil
|
tc = nil
|
||||||
eventsIn <- event.Draw{}
|
eventsIn <- paint.Event{}
|
||||||
}
|
}
|
||||||
C.processEvents()
|
C.processEvents()
|
||||||
}
|
}
|
||||||
@ -76,17 +79,17 @@ func onResize(w, h int) {
|
|||||||
// TODO(nigeltao): don't assume 72 DPI. DisplayWidth and DisplayWidthMM
|
// TODO(nigeltao): don't assume 72 DPI. DisplayWidth and DisplayWidthMM
|
||||||
// is probably the best place to start looking.
|
// is probably the best place to start looking.
|
||||||
pixelsPerPt = 1
|
pixelsPerPt = 1
|
||||||
eventsIn <- event.Config{
|
eventsIn <- config.Event{
|
||||||
Width: geom.Pt(w),
|
Width: geom.Pt(w),
|
||||||
Height: geom.Pt(h),
|
Height: geom.Pt(h),
|
||||||
PixelsPerPt: pixelsPerPt,
|
PixelsPerPt: pixelsPerPt,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func sendTouch(c event.Change, x, y float32) {
|
func sendTouch(t touch.Type, x, y float32) {
|
||||||
eventsIn <- event.Touch{
|
eventsIn <- touch.Event{
|
||||||
ID: 0, // TODO: button??
|
Sequence: 0, // TODO: button??
|
||||||
Change: c,
|
Type: t,
|
||||||
Loc: geom.Point{
|
Loc: geom.Point{
|
||||||
X: geom.Pt(x / pixelsPerPt),
|
X: geom.Pt(x / pixelsPerPt),
|
||||||
Y: geom.Pt(y / pixelsPerPt),
|
Y: geom.Pt(y / pixelsPerPt),
|
||||||
@ -95,13 +98,13 @@ func sendTouch(c event.Change, x, y float32) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//export onTouchStart
|
//export onTouchStart
|
||||||
func onTouchStart(x, y float32) { sendTouch(event.ChangeOn, x, y) }
|
func onTouchStart(x, y float32) { sendTouch(touch.TypeStart, x, y) }
|
||||||
|
|
||||||
//export onTouchMove
|
//export onTouchMove
|
||||||
func onTouchMove(x, y float32) { sendTouch(event.ChangeNone, x, y) }
|
func onTouchMove(x, y float32) { sendTouch(touch.TypeMove, x, y) }
|
||||||
|
|
||||||
//export onTouchEnd
|
//export onTouchEnd
|
||||||
func onTouchEnd(x, y float32) { sendTouch(event.ChangeOff, x, y) }
|
func onTouchEnd(x, y float32) { sendTouch(touch.TypeEnd, x, y) }
|
||||||
|
|
||||||
var stopped bool
|
var stopped bool
|
||||||
|
|
||||||
@ -111,6 +114,6 @@ func onStop() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
stopped = true
|
stopped = true
|
||||||
sendLifecycle(event.LifecycleStageDead)
|
sendLifecycle(lifecycle.StageDead)
|
||||||
eventsIn <- stopPumping{}
|
eventsIn <- stopPumping{}
|
||||||
}
|
}
|
||||||
|
27
event/config/config.go
Normal file
27
event/config/config.go
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
// Copyright 2015 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package config defines an event for the dimensions and physical resolution
|
||||||
|
// of the app's window.
|
||||||
|
//
|
||||||
|
// See the golang.org/x/mobile/event package for details on the event model.
|
||||||
|
package config // import "golang.org/x/mobile/event/config"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"golang.org/x/mobile/geom"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Event holds the dimensions and physical resolution of the app's window.
|
||||||
|
type Event struct {
|
||||||
|
// Width and Height are the window's dimensions.
|
||||||
|
Width, Height geom.Pt
|
||||||
|
|
||||||
|
// PixelsPerPt is the window's physical resolution. It is the number of
|
||||||
|
// pixels in a single geom.Pt, from the golang.org/x/mobile/geom package.
|
||||||
|
//
|
||||||
|
// There are a wide variety of pixel densities in existing phones and
|
||||||
|
// tablets, so apps should be written to expect various non-integer
|
||||||
|
// PixelsPerPt values. In general, work in geom.Pt.
|
||||||
|
PixelsPerPt float32
|
||||||
|
}
|
173
event/event.go
173
event/event.go
@ -2,15 +2,16 @@
|
|||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// Package event defines mobile app events, such as user input events.
|
// Package event defines a model for mobile app events, such as user input
|
||||||
|
// events.
|
||||||
//
|
//
|
||||||
// An event is represented by the empty interface type interface{}. Any value
|
// An event is represented by the empty interface type interface{}. Any value
|
||||||
// can be an event. This package defines a number of commonly used events used
|
// can be an event. Packages under this directory define a number of commonly
|
||||||
// by the golang.org/x/mobile/app package:
|
// used events used by the golang.org/x/mobile/app package:
|
||||||
// - Config
|
// - golang.org/x/mobile/event/config.Event
|
||||||
// - Draw
|
// - golang.org/x/mobile/event/lifecycle.Event
|
||||||
// - Lifecycle
|
// - golang.org/x/mobile/event/paint.Event
|
||||||
// - Touch
|
// - golang.org/x/mobile/event/touch.Event
|
||||||
// Other packages may define their own events, and post them onto an app's
|
// Other packages may define their own events, and post them onto an app's
|
||||||
// event channel.
|
// event channel.
|
||||||
//
|
//
|
||||||
@ -28,19 +29,6 @@
|
|||||||
// }
|
// }
|
||||||
package event // import "golang.org/x/mobile/event"
|
package event // import "golang.org/x/mobile/event"
|
||||||
|
|
||||||
// The best source on android input events is the NDK: include/android/input.h
|
|
||||||
//
|
|
||||||
// iOS event handling guide:
|
|
||||||
// https://developer.apple.com/library/ios/documentation/EventHandling/Conceptual/EventHandlingiPhoneOS
|
|
||||||
|
|
||||||
// TODO: keyboard events.
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"golang.org/x/mobile/geom"
|
|
||||||
)
|
|
||||||
|
|
||||||
var filters []func(interface{}) interface{}
|
var filters []func(interface{}) interface{}
|
||||||
|
|
||||||
// Filter calls each registered filter function in sequence.
|
// Filter calls each registered filter function in sequence.
|
||||||
@ -60,148 +48,3 @@ func Filter(event interface{}) interface{} {
|
|||||||
func RegisterFilter(f func(interface{}) interface{}) {
|
func RegisterFilter(f func(interface{}) interface{}) {
|
||||||
filters = append(filters, f)
|
filters = append(filters, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Change is a change in state, such as key or mouse button being up (off) or
|
|
||||||
// down (on). Some events with a Change-typed field can have no change in
|
|
||||||
// state, such as a key repeat or a mouse or touch drag.
|
|
||||||
type Change uint32
|
|
||||||
|
|
||||||
func (c Change) String() string {
|
|
||||||
switch c {
|
|
||||||
case ChangeOn:
|
|
||||||
return "on"
|
|
||||||
case ChangeOff:
|
|
||||||
return "off"
|
|
||||||
}
|
|
||||||
return "none"
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
ChangeNone Change = 0
|
|
||||||
ChangeOn Change = 1
|
|
||||||
ChangeOff Change = 2
|
|
||||||
)
|
|
||||||
|
|
||||||
// Config holds the dimensions and physical resolution of the app's window.
|
|
||||||
type Config struct {
|
|
||||||
// Width and Height are the window's dimensions.
|
|
||||||
Width, Height geom.Pt
|
|
||||||
|
|
||||||
// PixelsPerPt is the window's physical resolution. It is the number of
|
|
||||||
// pixels in a single geom.Pt, from the golang.org/x/mobile/geom package.
|
|
||||||
//
|
|
||||||
// There are a wide variety of pixel densities in existing phones and
|
|
||||||
// tablets, so apps should be written to expect various non-integer
|
|
||||||
// PixelsPerPt values. In general, work in geom.Pt.
|
|
||||||
PixelsPerPt float32
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw indicates that the app is ready to draw the next frame of the GUI. A
|
|
||||||
// frame is completed by calling the App's EndDraw method.
|
|
||||||
type Draw struct{}
|
|
||||||
|
|
||||||
// Lifecycle is a lifecycle change from an old stage to a new stage.
|
|
||||||
type Lifecycle struct {
|
|
||||||
From, To LifecycleStage
|
|
||||||
}
|
|
||||||
|
|
||||||
// Crosses returns whether the transition from From to To crosses the stage s:
|
|
||||||
// - It returns ChangeOn if it does, and the Lifecycle change is positive.
|
|
||||||
// - It returns ChangeOff if it does, and the Lifecycle change is negative.
|
|
||||||
// - Otherwise, it returns ChangeNone.
|
|
||||||
// See the documentation for LifecycleStage for more discussion of positive and
|
|
||||||
// negative changes, and crosses.
|
|
||||||
func (l Lifecycle) Crosses(s LifecycleStage) Change {
|
|
||||||
switch {
|
|
||||||
case l.From < s && l.To >= s:
|
|
||||||
return ChangeOn
|
|
||||||
case l.From >= s && l.To < s:
|
|
||||||
return ChangeOff
|
|
||||||
}
|
|
||||||
return ChangeNone
|
|
||||||
}
|
|
||||||
|
|
||||||
// LifecycleStage is a stage in the app's lifecycle. The values are ordered, so
|
|
||||||
// that a lifecycle change from stage From to stage To implicitly crosses every
|
|
||||||
// stage in the range (min, max], exclusive on the low end and inclusive on the
|
|
||||||
// high end, where min is the minimum of From and To, and max is the maximum.
|
|
||||||
//
|
|
||||||
// The documentation for individual stages talk about positive and negative
|
|
||||||
// crosses. A positive Lifecycle change is one where its From stage is less
|
|
||||||
// than its To stage. Similarly, a negative Lifecycle change is one where From
|
|
||||||
// is greater than To. Thus, a positive Lifecycle change crosses every stage in
|
|
||||||
// the range (From, To] in increasing order, and a negative Lifecycle change
|
|
||||||
// crosses every stage in the range (To, From] in decreasing order.
|
|
||||||
type LifecycleStage uint32
|
|
||||||
|
|
||||||
// TODO: how does iOS map to these stages? What do cross-platform mobile
|
|
||||||
// abstractions do?
|
|
||||||
|
|
||||||
const (
|
|
||||||
// LifecycleStageDead is the zero stage. No Lifecycle change crosses this
|
|
||||||
// stage, but:
|
|
||||||
// - A positive change from this stage is the very first lifecycle change.
|
|
||||||
// - A negative change to this stage is the very last lifecycle change.
|
|
||||||
LifecycleStageDead LifecycleStage = iota
|
|
||||||
|
|
||||||
// LifecycleStageAlive means that the app is alive.
|
|
||||||
// - A positive cross means that the app has been created.
|
|
||||||
// - A negative cross means that the app is being destroyed.
|
|
||||||
// Each cross, either from or to LifecycleStageDead, will occur only once.
|
|
||||||
// On Android, these correspond to onCreate and onDestroy.
|
|
||||||
LifecycleStageAlive
|
|
||||||
|
|
||||||
// LifecycleStageVisible means that the app window is visible.
|
|
||||||
// - A positive cross means that the app window has become visible.
|
|
||||||
// - A negative cross means that the app window has become invisible.
|
|
||||||
// On Android, these correspond to onStart and onStop.
|
|
||||||
// On Desktop, an app window can become invisible if e.g. it is minimized,
|
|
||||||
// unmapped, or not on a visible workspace.
|
|
||||||
LifecycleStageVisible
|
|
||||||
|
|
||||||
// LifecycleStageFocused means that the app window has the focus.
|
|
||||||
// - A positive cross means that the app window has gained the focus.
|
|
||||||
// - A negative cross means that the app window has lost the focus.
|
|
||||||
// On Android, these correspond to onResume and onFreeze.
|
|
||||||
LifecycleStageFocused
|
|
||||||
)
|
|
||||||
|
|
||||||
func (l LifecycleStage) String() string {
|
|
||||||
switch l {
|
|
||||||
case LifecycleStageDead:
|
|
||||||
return "LifecycleStageDead"
|
|
||||||
case LifecycleStageAlive:
|
|
||||||
return "LifecycleStageAlive"
|
|
||||||
case LifecycleStageVisible:
|
|
||||||
return "LifecycleStageVisible"
|
|
||||||
case LifecycleStageFocused:
|
|
||||||
return "LifecycleStageFocused"
|
|
||||||
default:
|
|
||||||
return fmt.Sprintf("LifecycleStageInvalid:%d", l)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// On Android, Touch is an AInputEvent with AINPUT_EVENT_TYPE_MOTION:
|
|
||||||
// - ChangeOn is an AMOTION_EVENT_ACTION_DOWN.
|
|
||||||
// - ChangeNone is an AMOTION_EVENT_ACTION_MOVE.
|
|
||||||
// - ChangeOff is an AMOTION_EVENT_ACTION_UP.
|
|
||||||
//
|
|
||||||
// On iOS, Touch is the UIEvent delivered to a UIView:
|
|
||||||
// - ChangeOn is a call to touchesBegan.
|
|
||||||
// - ChangeNone is a call to touchesMoved.
|
|
||||||
// - ChangeOff is a call to touchesEnded.
|
|
||||||
|
|
||||||
// Touch is a user touch event.
|
|
||||||
//
|
|
||||||
// The same ID is shared by all events in a sequence. A sequence starts with a
|
|
||||||
// single ChangeOn (a touch start), is followed by zero or more ChangeNones
|
|
||||||
// (touch moves), and ends with a single ChangeOff (a touch end). An ID
|
|
||||||
// distinguishes concurrent sequences but is subsequently reused.
|
|
||||||
type Touch struct {
|
|
||||||
ID TouchSequenceID
|
|
||||||
Change Change
|
|
||||||
Loc geom.Point
|
|
||||||
}
|
|
||||||
|
|
||||||
// TouchSequenceID identifies a sequence of Touch events.
|
|
||||||
type TouchSequenceID int64
|
|
||||||
|
124
event/lifecycle/lifecycle.go
Normal file
124
event/lifecycle/lifecycle.go
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
// Copyright 2015 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package lifecycle defines an event for an app's lifecycle.
|
||||||
|
//
|
||||||
|
// The app lifecycle consists of moving back and forth between an ordered
|
||||||
|
// sequence of stages. For example, being at a stage greater than or equal to
|
||||||
|
// StageVisible means that the app is visible on the screen.
|
||||||
|
//
|
||||||
|
// A lifecycle event is a change from one stage to another, which crosses every
|
||||||
|
// intermediate stage. For example, changing from StageAlive to StageFocused
|
||||||
|
// implicitly crosses StageVisible.
|
||||||
|
//
|
||||||
|
// Crosses can be in a positive or negative direction. A positive crossing of
|
||||||
|
// StageFocused means that the app has gained the focus. A negative crossing
|
||||||
|
// means it has lost the focus.
|
||||||
|
//
|
||||||
|
// See the golang.org/x/mobile/event package for details on the event model.
|
||||||
|
package lifecycle // import "golang.org/x/mobile/event/lifecycle"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Cross is whether a lifecycle stage was crossed.
|
||||||
|
type Cross uint32
|
||||||
|
|
||||||
|
func (c Cross) String() string {
|
||||||
|
switch c {
|
||||||
|
case CrossOn:
|
||||||
|
return "on"
|
||||||
|
case CrossOff:
|
||||||
|
return "off"
|
||||||
|
}
|
||||||
|
return "none"
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
CrossNone Cross = 0
|
||||||
|
CrossOn Cross = 1
|
||||||
|
CrossOff Cross = 2
|
||||||
|
)
|
||||||
|
|
||||||
|
// Event is a lifecycle change from an old stage to a new stage.
|
||||||
|
type Event struct {
|
||||||
|
From, To Stage
|
||||||
|
}
|
||||||
|
|
||||||
|
// Crosses returns whether the transition from From to To crosses the stage s:
|
||||||
|
// - It returns CrossOn if it does, and the lifecycle change is positive.
|
||||||
|
// - It returns CrossOff if it does, and the lifecycle change is negative.
|
||||||
|
// - Otherwise, it returns CrossNone.
|
||||||
|
// See the documentation for Stage for more discussion of positive and negative
|
||||||
|
// crosses.
|
||||||
|
func (e Event) Crosses(s Stage) Cross {
|
||||||
|
switch {
|
||||||
|
case e.From < s && e.To >= s:
|
||||||
|
return CrossOn
|
||||||
|
case e.From >= s && e.To < s:
|
||||||
|
return CrossOff
|
||||||
|
}
|
||||||
|
return CrossNone
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stage is a stage in the app's lifecycle. The values are ordered, so that a
|
||||||
|
// lifecycle change from stage From to stage To implicitly crosses every stage
|
||||||
|
// in the range (min, max], exclusive on the low end and inclusive on the high
|
||||||
|
// end, where min is the minimum of From and To, and max is the maximum.
|
||||||
|
//
|
||||||
|
// The documentation for individual stages talk about positive and negative
|
||||||
|
// crosses. A positive lifecycle change is one where its From stage is less
|
||||||
|
// than its To stage. Similarly, a negative lifecycle change is one where From
|
||||||
|
// is greater than To. Thus, a positive lifecycle change crosses every stage in
|
||||||
|
// the range (From, To] in increasing order, and a negative lifecycle change
|
||||||
|
// crosses every stage in the range (To, From] in decreasing order.
|
||||||
|
type Stage uint32
|
||||||
|
|
||||||
|
// TODO: how does iOS map to these stages? What do cross-platform mobile
|
||||||
|
// abstractions do?
|
||||||
|
|
||||||
|
const (
|
||||||
|
// StageDead is the zero stage. No lifecycle change crosses this stage,
|
||||||
|
// but:
|
||||||
|
// - A positive change from this stage is the very first lifecycle change.
|
||||||
|
// - A negative change to this stage is the very last lifecycle change.
|
||||||
|
StageDead Stage = iota
|
||||||
|
|
||||||
|
// StageAlive means that the app is alive.
|
||||||
|
// - A positive cross means that the app has been created.
|
||||||
|
// - A negative cross means that the app is being destroyed.
|
||||||
|
// Each cross, either from or to StageDead, will occur only once.
|
||||||
|
// On Android, these correspond to onCreate and onDestroy.
|
||||||
|
StageAlive
|
||||||
|
|
||||||
|
// StageVisible means that the app window is visible.
|
||||||
|
// - A positive cross means that the app window has become visible.
|
||||||
|
// - A negative cross means that the app window has become invisible.
|
||||||
|
// On Android, these correspond to onStart and onStop.
|
||||||
|
// On Desktop, an app window can become invisible if e.g. it is minimized,
|
||||||
|
// unmapped, or not on a visible workspace.
|
||||||
|
StageVisible
|
||||||
|
|
||||||
|
// StageFocused means that the app window has the focus.
|
||||||
|
// - A positive cross means that the app window has gained the focus.
|
||||||
|
// - A negative cross means that the app window has lost the focus.
|
||||||
|
// On Android, these correspond to onResume and onFreeze.
|
||||||
|
StageFocused
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s Stage) String() string {
|
||||||
|
switch s {
|
||||||
|
case StageDead:
|
||||||
|
return "StageDead"
|
||||||
|
case StageAlive:
|
||||||
|
return "StageAlive"
|
||||||
|
case StageVisible:
|
||||||
|
return "StageVisible"
|
||||||
|
case StageFocused:
|
||||||
|
return "StageFocused"
|
||||||
|
default:
|
||||||
|
return fmt.Sprintf("lifecycle.Stage(%d)", s)
|
||||||
|
}
|
||||||
|
}
|
17
event/paint/paint.go
Normal file
17
event/paint/paint.go
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// Copyright 2015 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package paint defines an event for the app being ready to paint.
|
||||||
|
//
|
||||||
|
// See the golang.org/x/mobile/event package for details on the event model.
|
||||||
|
package paint // import "golang.org/x/mobile/event/paint"
|
||||||
|
|
||||||
|
// TODO: rename App.EndDraw to App.EndPaint.
|
||||||
|
//
|
||||||
|
// This is "package paint", not "package draw", to avoid conflicting with the
|
||||||
|
// standard library's "image/draw" package.
|
||||||
|
|
||||||
|
// Event indicates that the app is ready to paint the next frame of the GUI. A
|
||||||
|
// frame is completed by calling the App's EndDraw method.
|
||||||
|
type Event struct{}
|
71
event/touch/touch.go
Normal file
71
event/touch/touch.go
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
// Copyright 2015 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package touch defines an event for touch input.
|
||||||
|
//
|
||||||
|
// See the golang.org/x/mobile/event package for details on the event model.
|
||||||
|
package touch // import "golang.org/x/mobile/event/touch"
|
||||||
|
|
||||||
|
// The best source on android input events is the NDK: include/android/input.h
|
||||||
|
//
|
||||||
|
// iOS event handling guide:
|
||||||
|
// https://developer.apple.com/library/ios/documentation/EventHandling/Conceptual/EventHandlingiPhoneOS
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"golang.org/x/mobile/geom"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Event is a touch event.
|
||||||
|
//
|
||||||
|
// The same Sequence is shared by all events in a sequence. A sequence starts
|
||||||
|
// with a single TypeStart, is followed by zero or more TypeMoves, and ends
|
||||||
|
// with a single TypeEnd. A Sequence distinguishes concurrent sequences but its
|
||||||
|
// value is subsequently reused.
|
||||||
|
type Event struct {
|
||||||
|
Sequence Sequence
|
||||||
|
Type Type
|
||||||
|
Loc geom.Point
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sequence identifies a sequence of touch events.
|
||||||
|
type Sequence int64
|
||||||
|
|
||||||
|
// Type describes the type of a touch event.
|
||||||
|
type Type byte
|
||||||
|
|
||||||
|
const (
|
||||||
|
// TypeStart is a user first touching the device.
|
||||||
|
//
|
||||||
|
// On Android, this is a AMOTION_EVENT_ACTION_DOWN.
|
||||||
|
// On iOS, this is a call to touchesBegan.
|
||||||
|
TypeStart Type = iota
|
||||||
|
|
||||||
|
// TypeMove is a user dragging across the device.
|
||||||
|
//
|
||||||
|
// A TypeMove is delivered between a TypeStart and TypeEnd.
|
||||||
|
//
|
||||||
|
// On Android, this is a AMOTION_EVENT_ACTION_MOVE.
|
||||||
|
// On iOS, this is a call to touchesMoved.
|
||||||
|
TypeMove
|
||||||
|
|
||||||
|
// TypeEnd is a user no longer touching the device.
|
||||||
|
//
|
||||||
|
// On Android, this is a AMOTION_EVENT_ACTION_UP.
|
||||||
|
// On iOS, this is a call to touchesEnded.
|
||||||
|
TypeEnd
|
||||||
|
)
|
||||||
|
|
||||||
|
func (t Type) String() string {
|
||||||
|
switch t {
|
||||||
|
case TypeStart:
|
||||||
|
return "start"
|
||||||
|
case TypeMove:
|
||||||
|
return "move"
|
||||||
|
case TypeEnd:
|
||||||
|
return "end"
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("touch.Type(%d)", t)
|
||||||
|
}
|
@ -39,7 +39,7 @@ import (
|
|||||||
|
|
||||||
"golang.org/x/mobile/app"
|
"golang.org/x/mobile/app"
|
||||||
"golang.org/x/mobile/asset"
|
"golang.org/x/mobile/asset"
|
||||||
"golang.org/x/mobile/event"
|
"golang.org/x/mobile/event/config"
|
||||||
"golang.org/x/mobile/exp/app/debug"
|
"golang.org/x/mobile/exp/app/debug"
|
||||||
"golang.org/x/mobile/exp/audio"
|
"golang.org/x/mobile/exp/audio"
|
||||||
"golang.org/x/mobile/exp/f32"
|
"golang.org/x/mobile/exp/f32"
|
||||||
@ -65,13 +65,13 @@ var (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
app.Run(app.Callbacks{
|
app.Run(app.Callbacks{
|
||||||
Start: start,
|
Start: onStart,
|
||||||
Stop: stop,
|
Stop: onStop,
|
||||||
Draw: draw,
|
Draw: onDraw,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func start() {
|
func onStart() {
|
||||||
rc, err := asset.Open("boing.wav")
|
rc, err := asset.Open("boing.wav")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
@ -82,11 +82,11 @@ func start() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func stop() {
|
func onStop() {
|
||||||
player.Close()
|
player.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func draw(c event.Config) {
|
func onDraw(c config.Event) {
|
||||||
if scene == nil {
|
if scene == nil {
|
||||||
loadScene(c)
|
loadScene(c)
|
||||||
}
|
}
|
||||||
@ -104,7 +104,7 @@ func newNode() *sprite.Node {
|
|||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadScene(c event.Config) {
|
func loadScene(c config.Event) {
|
||||||
gopher := loadGopher()
|
gopher := loadGopher()
|
||||||
scene = &sprite.Node{}
|
scene = &sprite.Node{}
|
||||||
eng.Register(scene)
|
eng.Register(scene)
|
||||||
|
@ -31,7 +31,8 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
|
|
||||||
"golang.org/x/mobile/app"
|
"golang.org/x/mobile/app"
|
||||||
"golang.org/x/mobile/event"
|
"golang.org/x/mobile/event/config"
|
||||||
|
"golang.org/x/mobile/event/touch"
|
||||||
"golang.org/x/mobile/exp/app/debug"
|
"golang.org/x/mobile/exp/app/debug"
|
||||||
"golang.org/x/mobile/exp/f32"
|
"golang.org/x/mobile/exp/f32"
|
||||||
"golang.org/x/mobile/exp/gl/glutil"
|
"golang.org/x/mobile/exp/gl/glutil"
|
||||||
@ -52,15 +53,15 @@ var (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
app.Run(app.Callbacks{
|
app.Run(app.Callbacks{
|
||||||
Start: start,
|
Start: onStart,
|
||||||
Stop: stop,
|
Stop: onStop,
|
||||||
Draw: draw,
|
Draw: onDraw,
|
||||||
Touch: touch,
|
Touch: onTouch,
|
||||||
Config: config,
|
Config: onConfig,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func start() {
|
func onStart() {
|
||||||
var err error
|
var err error
|
||||||
program, err = glutil.CreateProgram(vertexShader, fragmentShader)
|
program, err = glutil.CreateProgram(vertexShader, fragmentShader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -80,20 +81,20 @@ func start() {
|
|||||||
// Can this be an event.Register call now??
|
// Can this be an event.Register call now??
|
||||||
}
|
}
|
||||||
|
|
||||||
func stop() {
|
func onStop() {
|
||||||
gl.DeleteProgram(program)
|
gl.DeleteProgram(program)
|
||||||
gl.DeleteBuffer(buf)
|
gl.DeleteBuffer(buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
func config(new, old event.Config) {
|
func onConfig(new, old config.Event) {
|
||||||
touchLoc = geom.Point{new.Width / 2, new.Height / 2}
|
touchLoc = geom.Point{new.Width / 2, new.Height / 2}
|
||||||
}
|
}
|
||||||
|
|
||||||
func touch(t event.Touch, c event.Config) {
|
func onTouch(t touch.Event, c config.Event) {
|
||||||
touchLoc = t.Loc
|
touchLoc = t.Loc
|
||||||
}
|
}
|
||||||
|
|
||||||
func draw(c event.Config) {
|
func onDraw(c config.Event) {
|
||||||
gl.ClearColor(1, 0, 0, 1)
|
gl.ClearColor(1, 0, 0, 1)
|
||||||
gl.Clear(gl.COLOR_BUFFER_BIT)
|
gl.Clear(gl.COLOR_BUFFER_BIT)
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"golang.org/x/mobile/app"
|
"golang.org/x/mobile/app"
|
||||||
"golang.org/x/mobile/event"
|
"golang.org/x/mobile/event/config"
|
||||||
"golang.org/x/mobile/exp/app/debug"
|
"golang.org/x/mobile/exp/app/debug"
|
||||||
"golang.org/x/mobile/gl"
|
"golang.org/x/mobile/gl"
|
||||||
)
|
)
|
||||||
@ -51,7 +51,7 @@ func main() {
|
|||||||
go checkNetwork()
|
go checkNetwork()
|
||||||
|
|
||||||
app.Run(app.Callbacks{
|
app.Run(app.Callbacks{
|
||||||
Draw: draw,
|
Draw: onDraw,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,7 +70,7 @@ func checkNetwork() {
|
|||||||
ok = true
|
ok = true
|
||||||
}
|
}
|
||||||
|
|
||||||
func draw(c event.Config) {
|
func onDraw(c config.Event) {
|
||||||
select {
|
select {
|
||||||
case <-determined:
|
case <-determined:
|
||||||
if ok {
|
if ok {
|
||||||
|
@ -36,7 +36,7 @@ import (
|
|||||||
|
|
||||||
"golang.org/x/mobile/app"
|
"golang.org/x/mobile/app"
|
||||||
"golang.org/x/mobile/asset"
|
"golang.org/x/mobile/asset"
|
||||||
"golang.org/x/mobile/event"
|
"golang.org/x/mobile/event/config"
|
||||||
"golang.org/x/mobile/exp/app/debug"
|
"golang.org/x/mobile/exp/app/debug"
|
||||||
"golang.org/x/mobile/exp/f32"
|
"golang.org/x/mobile/exp/f32"
|
||||||
"golang.org/x/mobile/exp/sprite"
|
"golang.org/x/mobile/exp/sprite"
|
||||||
@ -53,11 +53,11 @@ var (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
app.Run(app.Callbacks{
|
app.Run(app.Callbacks{
|
||||||
Draw: draw,
|
Draw: onDraw,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func draw(c event.Config) {
|
func onDraw(c config.Event) {
|
||||||
if scene == nil {
|
if scene == nil {
|
||||||
loadScene()
|
loadScene()
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"golang.org/x/mobile/event"
|
"golang.org/x/mobile/event/config"
|
||||||
"golang.org/x/mobile/exp/gl/glutil"
|
"golang.org/x/mobile/exp/gl/glutil"
|
||||||
"golang.org/x/mobile/geom"
|
"golang.org/x/mobile/geom"
|
||||||
)
|
)
|
||||||
@ -21,12 +21,12 @@ var lastDraw = time.Now()
|
|||||||
|
|
||||||
var fps struct {
|
var fps struct {
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
c event.Config
|
c config.Event
|
||||||
m *glutil.Image
|
m *glutil.Image
|
||||||
}
|
}
|
||||||
|
|
||||||
// DrawFPS draws the per second framerate in the bottom-left of the screen.
|
// DrawFPS draws the per second framerate in the bottom-left of the screen.
|
||||||
func DrawFPS(c event.Config) {
|
func DrawFPS(c config.Event) {
|
||||||
const imgW, imgH = 7*(fontWidth+1) + 1, fontHeight + 2
|
const imgW, imgH = 7*(fontWidth+1) + 1, fontHeight + 2
|
||||||
|
|
||||||
fps.mu.Lock()
|
fps.mu.Lock()
|
||||||
|
@ -14,6 +14,8 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"golang.org/x/mobile/event"
|
"golang.org/x/mobile/event"
|
||||||
|
"golang.org/x/mobile/event/config"
|
||||||
|
"golang.org/x/mobile/event/lifecycle"
|
||||||
"golang.org/x/mobile/exp/f32"
|
"golang.org/x/mobile/exp/f32"
|
||||||
"golang.org/x/mobile/geom"
|
"golang.org/x/mobile/geom"
|
||||||
"golang.org/x/mobile/gl"
|
"golang.org/x/mobile/gl"
|
||||||
@ -32,11 +34,11 @@ var glimage struct {
|
|||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
event.RegisterFilter(func(e interface{}) interface{} {
|
event.RegisterFilter(func(e interface{}) interface{} {
|
||||||
if e, ok := e.(event.Lifecycle); ok {
|
if e, ok := e.(lifecycle.Event); ok {
|
||||||
switch e.Crosses(event.LifecycleStageVisible) {
|
switch e.Crosses(lifecycle.StageVisible) {
|
||||||
case event.ChangeOn:
|
case lifecycle.CrossOn:
|
||||||
start()
|
start()
|
||||||
case event.ChangeOff:
|
case lifecycle.CrossOff:
|
||||||
stop()
|
stop()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -223,7 +225,7 @@ func (img *Image) Delete() {
|
|||||||
|
|
||||||
// Draw draws the srcBounds part of the image onto a parallelogram, defined by
|
// Draw draws the srcBounds part of the image onto a parallelogram, defined by
|
||||||
// three of its corners, in the current GL framebuffer.
|
// three of its corners, in the current GL framebuffer.
|
||||||
func (img *Image) Draw(c event.Config, topLeft, topRight, bottomLeft geom.Point, srcBounds image.Rectangle) {
|
func (img *Image) Draw(c config.Event, topLeft, topRight, bottomLeft geom.Point, srcBounds image.Rectangle) {
|
||||||
// TODO(crawshaw): Adjust viewport for the top bar on android?
|
// TODO(crawshaw): Adjust viewport for the top bar on android?
|
||||||
gl.UseProgram(glimage.program)
|
gl.UseProgram(glimage.program)
|
||||||
tex := texmap.get(*img.key)
|
tex := texmap.get(*img.key)
|
||||||
|
@ -18,7 +18,7 @@ import (
|
|||||||
"runtime"
|
"runtime"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"golang.org/x/mobile/event"
|
"golang.org/x/mobile/event/config"
|
||||||
"golang.org/x/mobile/geom"
|
"golang.org/x/mobile/geom"
|
||||||
"golang.org/x/mobile/gl"
|
"golang.org/x/mobile/gl"
|
||||||
)
|
)
|
||||||
@ -65,7 +65,7 @@ func TestImage(t *testing.T) {
|
|||||||
ptW = geom.Pt(50)
|
ptW = geom.Pt(50)
|
||||||
ptH = geom.Pt(50)
|
ptH = geom.Pt(50)
|
||||||
)
|
)
|
||||||
cfg := event.Config{
|
cfg := config.Event{
|
||||||
Width: ptW,
|
Width: ptW,
|
||||||
Height: ptH,
|
Height: ptH,
|
||||||
PixelsPerPt: float32(pixW) / float32(ptW),
|
PixelsPerPt: float32(pixW) / float32(ptW),
|
||||||
|
@ -12,7 +12,7 @@ import (
|
|||||||
"image"
|
"image"
|
||||||
"image/draw"
|
"image/draw"
|
||||||
|
|
||||||
"golang.org/x/mobile/event"
|
"golang.org/x/mobile/event/config"
|
||||||
"golang.org/x/mobile/exp/f32"
|
"golang.org/x/mobile/exp/f32"
|
||||||
"golang.org/x/mobile/exp/gl/glutil"
|
"golang.org/x/mobile/exp/gl/glutil"
|
||||||
"golang.org/x/mobile/exp/sprite"
|
"golang.org/x/mobile/exp/sprite"
|
||||||
@ -91,7 +91,7 @@ func (e *engine) SetTransform(n *sprite.Node, m f32.Affine) {
|
|||||||
e.nodes[n.EngineFields.Index].relTransform = m
|
e.nodes[n.EngineFields.Index].relTransform = m
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *engine) Render(scene *sprite.Node, t clock.Time, cfg event.Config) {
|
func (e *engine) Render(scene *sprite.Node, t clock.Time, cfg config.Event) {
|
||||||
e.absTransforms = append(e.absTransforms[:0], f32.Affine{
|
e.absTransforms = append(e.absTransforms[:0], f32.Affine{
|
||||||
{1, 0, 0},
|
{1, 0, 0},
|
||||||
{0, 1, 0},
|
{0, 1, 0},
|
||||||
@ -99,7 +99,7 @@ func (e *engine) Render(scene *sprite.Node, t clock.Time, cfg event.Config) {
|
|||||||
e.render(scene, t, cfg)
|
e.render(scene, t, cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *engine) render(n *sprite.Node, t clock.Time, cfg event.Config) {
|
func (e *engine) render(n *sprite.Node, t clock.Time, cfg config.Event) {
|
||||||
if n.EngineFields.Index == 0 {
|
if n.EngineFields.Index == 0 {
|
||||||
panic("glsprite: sprite.Node not registered")
|
panic("glsprite: sprite.Node not registered")
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"golang.org/x/mobile/event"
|
"golang.org/x/mobile/event/config"
|
||||||
"golang.org/x/mobile/exp/f32"
|
"golang.org/x/mobile/exp/f32"
|
||||||
"golang.org/x/mobile/geom"
|
"golang.org/x/mobile/geom"
|
||||||
)
|
)
|
||||||
@ -38,7 +38,7 @@ func TestAffine(t *testing.T) {
|
|||||||
ptW = geom.Pt(50)
|
ptW = geom.Pt(50)
|
||||||
ptH = geom.Pt(50)
|
ptH = geom.Pt(50)
|
||||||
)
|
)
|
||||||
cfg := event.Config{
|
cfg := config.Event{
|
||||||
Width: ptW,
|
Width: ptW,
|
||||||
Height: ptH,
|
Height: ptH,
|
||||||
PixelsPerPt: float32(pixW) / float32(ptW),
|
PixelsPerPt: float32(pixW) / float32(ptW),
|
||||||
|
@ -13,7 +13,7 @@ import (
|
|||||||
"image"
|
"image"
|
||||||
"image/draw"
|
"image/draw"
|
||||||
|
|
||||||
"golang.org/x/mobile/event"
|
"golang.org/x/mobile/event/config"
|
||||||
"golang.org/x/mobile/exp/f32"
|
"golang.org/x/mobile/exp/f32"
|
||||||
"golang.org/x/mobile/exp/sprite"
|
"golang.org/x/mobile/exp/sprite"
|
||||||
"golang.org/x/mobile/exp/sprite/clock"
|
"golang.org/x/mobile/exp/sprite/clock"
|
||||||
@ -92,7 +92,7 @@ func (e *engine) SetTransform(n *sprite.Node, m f32.Affine) {
|
|||||||
e.nodes[n.EngineFields.Index].relTransform = m
|
e.nodes[n.EngineFields.Index].relTransform = m
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *engine) Render(scene *sprite.Node, t clock.Time, cfg event.Config) {
|
func (e *engine) Render(scene *sprite.Node, t clock.Time, cfg config.Event) {
|
||||||
// Affine transforms are done in geom.Pt. When finally drawing
|
// Affine transforms are done in geom.Pt. When finally drawing
|
||||||
// the geom.Pt onto an image.Image we need to convert to system
|
// the geom.Pt onto an image.Image we need to convert to system
|
||||||
// pixels. We scale by cfg.PixelsPerPt to do this.
|
// pixels. We scale by cfg.PixelsPerPt to do this.
|
||||||
|
@ -28,7 +28,7 @@ import (
|
|||||||
"image"
|
"image"
|
||||||
"image/draw"
|
"image/draw"
|
||||||
|
|
||||||
"golang.org/x/mobile/event"
|
"golang.org/x/mobile/event/config"
|
||||||
"golang.org/x/mobile/exp/f32"
|
"golang.org/x/mobile/exp/f32"
|
||||||
"golang.org/x/mobile/exp/sprite/clock"
|
"golang.org/x/mobile/exp/sprite/clock"
|
||||||
)
|
)
|
||||||
@ -60,7 +60,7 @@ type Engine interface {
|
|||||||
|
|
||||||
// Render renders the scene arranged at the given time, for the given
|
// Render renders the scene arranged at the given time, for the given
|
||||||
// window configuration (dimensions and resolution).
|
// window configuration (dimensions and resolution).
|
||||||
Render(scene *Node, t clock.Time, c event.Config)
|
Render(scene *Node, t clock.Time, c config.Event)
|
||||||
}
|
}
|
||||||
|
|
||||||
// A Node is a renderable element and forms a tree of Nodes.
|
// A Node is a renderable element and forms a tree of Nodes.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user