go.mobile/app: Touch callback
LGTM=adg, nigeltao R=nigeltao, adg, bryanturley CC=davidday, golang-codereviews https://golang.org/cl/140450043
This commit is contained in:
parent
3fd6804d3e
commit
56cb2dac4e
@ -127,6 +127,8 @@ void ANativeActivity_onCreate(ANativeActivity *activity, void* savedState, size_
|
||||
//activity->callbacks->onContentRectChanged = onContentRectChanged;
|
||||
activity->callbacks->onConfigurationChanged = onConfigurationChanged;
|
||||
activity->callbacks->onLowMemory = onLowMemory;
|
||||
|
||||
onCreate(activity);
|
||||
}
|
||||
|
||||
// Runtime entry point when embedding Go in a Java App.
|
||||
|
@ -13,6 +13,7 @@ package app
|
||||
/*
|
||||
#cgo LDFLAGS: -llog -landroid
|
||||
#include <android/log.h>
|
||||
#include <android/configuration.h>
|
||||
#include <android/native_activity.h>
|
||||
#include <pthread.h>
|
||||
#include <jni.h>
|
||||
@ -31,10 +32,43 @@ JavaVM* current_vm;
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"log"
|
||||
"runtime"
|
||||
"unsafe"
|
||||
|
||||
"code.google.com/p/go.mobile/geom"
|
||||
)
|
||||
|
||||
//export onCreate
|
||||
func onCreate(activity *C.ANativeActivity) {
|
||||
config := C.AConfiguration_new()
|
||||
C.AConfiguration_fromAssetManager(config, activity.assetManager)
|
||||
density := C.AConfiguration_getDensity(config)
|
||||
C.AConfiguration_delete(config)
|
||||
|
||||
var dpi int
|
||||
switch density {
|
||||
case C.ACONFIGURATION_DENSITY_DEFAULT:
|
||||
dpi = 160
|
||||
case C.ACONFIGURATION_DENSITY_LOW,
|
||||
C.ACONFIGURATION_DENSITY_MEDIUM,
|
||||
C.ACONFIGURATION_DENSITY_TV,
|
||||
C.ACONFIGURATION_DENSITY_HIGH,
|
||||
320, // ACONFIGURATION_DENSITY_XHIGH
|
||||
480, // ACONFIGURATION_DENSITY_XXHIGH
|
||||
640: // ACONFIGURATION_DENSITY_XXXHIGH
|
||||
dpi = int(density)
|
||||
case C.ACONFIGURATION_DENSITY_NONE:
|
||||
log.Print("android device reports no screen density")
|
||||
dpi = 72
|
||||
default:
|
||||
log.Print("android device reports unknown density: %d", density)
|
||||
dpi = int(density) // This is a guess.
|
||||
}
|
||||
|
||||
geom.Scale = float32(dpi) / 72
|
||||
}
|
||||
|
||||
//export onStart
|
||||
func onStart(activity *C.ANativeActivity) {
|
||||
}
|
||||
@ -82,12 +116,16 @@ func onNativeWindowDestroyed(activity *C.ANativeActivity, window *C.ANativeWindo
|
||||
windowDestroyed <- true
|
||||
}
|
||||
|
||||
var queue *C.AInputQueue
|
||||
|
||||
//export onInputQueueCreated
|
||||
func onInputQueueCreated(activity *C.ANativeActivity, queue *C.AInputQueue) {
|
||||
func onInputQueueCreated(activity *C.ANativeActivity, q *C.AInputQueue) {
|
||||
queue = q
|
||||
}
|
||||
|
||||
//export onInputQueueDestroyed
|
||||
func onInputQueueDestroyed(activity *C.ANativeActivity, queue *C.AInputQueue) {
|
||||
queue = nil
|
||||
}
|
||||
|
||||
//export onContentRectChanged
|
||||
@ -135,7 +173,7 @@ func run(cb Callbacks) {
|
||||
for {
|
||||
select {
|
||||
case w := <-windowCreated:
|
||||
windowDrawLoop(cb, w)
|
||||
windowDrawLoop(cb, w, queue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,8 @@
|
||||
|
||||
package app
|
||||
|
||||
import "code.google.com/p/go.mobile/event"
|
||||
|
||||
// Run starts the app.
|
||||
//
|
||||
// It must be called directly from from the main function and will
|
||||
@ -19,6 +21,9 @@ type Callbacks struct {
|
||||
// Drawing is done into a framebuffer, which is then swapped onto the
|
||||
// screen when Draw returns. It is called 60 times a second.
|
||||
Draw func()
|
||||
|
||||
// Touch is called by the app when a touch event occurs.
|
||||
Touch func(event.Touch)
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -8,6 +8,7 @@ package app
|
||||
#cgo android LDFLAGS: -llog -landroid -lEGL -lGLESv2
|
||||
#include <android/log.h>
|
||||
#include <android/native_activity.h>
|
||||
#include <android/input.h>
|
||||
#include <EGL/egl.h>
|
||||
#include <GLES/gl.h>
|
||||
|
||||
@ -72,35 +73,85 @@ void createEGLWindow(ANativeWindow* window) {
|
||||
|
||||
eglQuerySurface(display, surface, EGL_WIDTH, &windowWidth);
|
||||
eglQuerySurface(display, surface, EGL_HEIGHT, &windowHeight);
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glViewport(0, 0, windowWidth, windowHeight);
|
||||
glClearColor(0, 0, 0, 1);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
eglSwapBuffers(display, surface);
|
||||
|
||||
GLenum err;
|
||||
if ((err = glGetError()) != GL_NO_ERROR) {
|
||||
LOG_ERROR("GL error in createEGLWindow: 0x%x", err);
|
||||
}
|
||||
}
|
||||
|
||||
#undef LOG_ERROR
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"log"
|
||||
|
||||
// windowDrawLoop calls Draw at 60 FPS processes input queue events.
|
||||
func windowDrawLoop(cb Callbacks, window *C.ANativeWindow) {
|
||||
C.createEGLWindow(window)
|
||||
"code.google.com/p/go.mobile/event"
|
||||
"code.google.com/p/go.mobile/geom"
|
||||
"code.google.com/p/go.mobile/gl"
|
||||
)
|
||||
|
||||
func windowDrawLoop(cb Callbacks, w *C.ANativeWindow, queue *C.AInputQueue) {
|
||||
C.createEGLWindow(w)
|
||||
|
||||
gl.Enable(gl.CULL_FACE)
|
||||
gl.ClearColor(0, 0, 0, 1)
|
||||
gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
|
||||
C.eglSwapBuffers(C.display, C.surface)
|
||||
|
||||
if errv := gl.GetError(); errv != gl.NO_ERROR {
|
||||
log.Printf("GL initialization error: %s", errv)
|
||||
}
|
||||
|
||||
geom.Width = geom.Pt(float32(C.windowWidth) / geom.Scale)
|
||||
geom.Height = geom.Pt(float32(C.windowHeight) / geom.Scale)
|
||||
|
||||
for {
|
||||
processEvents(cb, queue)
|
||||
select {
|
||||
case <-windowDestroyed:
|
||||
return
|
||||
// TODO(crawshaw): Event processing goes here.
|
||||
default:
|
||||
cb.Draw()
|
||||
C.eglSwapBuffers(C.display, C.surface)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func processEvents(cb Callbacks, queue *C.AInputQueue) {
|
||||
var event *C.AInputEvent
|
||||
for C.AInputQueue_getEvent(queue, &event) >= 0 {
|
||||
if C.AInputQueue_preDispatchEvent(queue, event) != 0 {
|
||||
continue
|
||||
}
|
||||
processEvent(cb, event)
|
||||
C.AInputQueue_finishEvent(queue, event, 0)
|
||||
}
|
||||
}
|
||||
|
||||
func processEvent(cb Callbacks, e *C.AInputEvent) {
|
||||
switch C.AInputEvent_getType(e) {
|
||||
case C.AINPUT_EVENT_TYPE_KEY:
|
||||
log.Printf("TODO input event: key")
|
||||
case C.AINPUT_EVENT_TYPE_MOTION:
|
||||
if cb.Touch == nil {
|
||||
return
|
||||
}
|
||||
x := C.AMotionEvent_getX(e, 0)
|
||||
y := C.AMotionEvent_getY(e, 0)
|
||||
|
||||
var ty event.TouchType
|
||||
switch C.AMotionEvent_getAction(e) {
|
||||
case C.AMOTION_EVENT_ACTION_DOWN:
|
||||
ty = event.TouchStart
|
||||
case C.AMOTION_EVENT_ACTION_MOVE:
|
||||
ty = event.TouchMove
|
||||
case C.AMOTION_EVENT_ACTION_UP:
|
||||
ty = event.TouchEnd
|
||||
}
|
||||
cb.Touch(event.Touch{
|
||||
Type: ty,
|
||||
Loc: geom.Point{
|
||||
X: geom.Pt(float32(x) / geom.Scale),
|
||||
Y: geom.Pt(float32(y) / geom.Scale),
|
||||
},
|
||||
})
|
||||
default:
|
||||
log.Printf("unknown input event, type=%d", C.AInputEvent_getType(e))
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user