2
0
mirror of synced 2025-02-20 13:38:20 +00:00

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:
David Crawshaw 2014-09-11 19:39:16 -04:00
parent 3fd6804d3e
commit 56cb2dac4e
4 changed files with 113 additions and 17 deletions

View File

@ -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.

View File

@ -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)
}
}
}

View File

@ -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)
}
/*

View File

@ -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))
}
}