app: plumb through android orientation

While I'm here, make pixelsPerPt local on android and darwin/amd64.
The one place where it's global is darwin/arm, which has another
similar global (screenScale).

Change-Id: I5897e7e5341afca1976fdf0215fb4f6fe2f411be
Reviewed-on: https://go-review.googlesource.com/13446
Reviewed-by: Nigel Tao <nigeltao@golang.org>
diff --git a/app/android.go b/app/android.go
index 901d1e4..57a5df4 100644
--- a/app/android.go
+++ b/app/android.go
@@ -166,13 +166,7 @@
 }
 
 type windowConfig struct {
-	// TODO(crawshaw): report orientation
-	//	ACONFIGURATION_ORIENTATION_ANY
-	//	ACONFIGURATION_ORIENTATION_PORT
-	//	ACONFIGURATION_ORIENTATION_LAND
-	//	ACONFIGURATION_ORIENTATION_SQUARE
-	// Needs to be merged with iOS's notion of orientation first.
-	orientation int
+	orientation config.Orientation
 	pixelsPerPt float32
 }
 
@@ -208,8 +202,16 @@
 		}
 	}
 
+	o := config.OrientationUnknown
+	switch orient {
+	case C.ACONFIGURATION_ORIENTATION_PORT:
+		o = config.OrientationPortrait
+	case C.ACONFIGURATION_ORIENTATION_LAND:
+		o = config.OrientationLandscape
+	}
+
 	return windowConfig{
-		orientation: int(orient),
+		orientation: o,
 		pixelsPerPt: float32(dpi) / 72,
 	}
 }
@@ -250,6 +252,8 @@
 	}()
 
 	var q *C.AInputQueue
+	var pixelsPerPt float32
+	var orientation config.Orientation
 
 	// Android can send a windowRedrawNeeded event any time, including
 	// in the middle of a paint cycle. The redraw event may have changed
@@ -274,8 +278,8 @@
 		case <-donec:
 			return
 		case cfg := <-windowConfigChange:
-			// TODO save orientation
 			pixelsPerPt = cfg.pixelsPerPt
+			orientation = cfg.orientation
 		case w := <-windowRedrawNeeded:
 			if C.surface == nil {
 				if errStr := C.createEGLSurface(w); errStr != nil {
@@ -292,6 +296,7 @@
 				WidthPt:     geom.Pt(float32(widthPx) / pixelsPerPt),
 				HeightPt:    geom.Pt(float32(heightPx) / pixelsPerPt),
 				PixelsPerPt: pixelsPerPt,
+				Orientation: orientation,
 			}
 			redrawGen++
 			eventsIn <- paint.Event{redrawGen}
diff --git a/app/app.go b/app/app.go
index b9a11e2..2ffe589 100644
--- a/app/app.go
+++ b/app/app.go
@@ -45,7 +45,6 @@
 
 var (
 	lifecycleStage = lifecycle.StageDead
-	pixelsPerPt    = float32(1)
 
 	eventsOut = make(chan interface{})
 	eventsIn  = pump(eventsOut)
diff --git a/app/app_test.go b/app/app_test.go
index 921d901..416c338 100644
--- a/app/app_test.go
+++ b/app/app_test.go
@@ -15,6 +15,7 @@
 	"time"
 
 	"golang.org/x/mobile/app/internal/apptest"
+	"golang.org/x/mobile/event/config"
 )
 
 // TestAndroidApp tests the lifecycle, event, and window semantics of a
@@ -67,6 +68,19 @@
 	run(t, "adb", "shell", "input", "keyevent", KeycodePower)
 	run(t, "adb", "shell", "input", "keyevent", KeycodeUnlock)
 
+	const (
+		rotationPortrait  = "0"
+		rotationLandscape = "1"
+	)
+
+	rotate := func(rotation string) {
+		run(t, "adb", "shell", "content", "insert", "--uri", "content://settings/system", "--bind", "name:s:user_rotation", "--bind", "value:i:"+rotation)
+	}
+
+	// turn off automatic rotation and start in portrait
+	run(t, "adb", "shell", "content", "insert", "--uri", "content://settings/system", "--bind", "name:s:accelerometer_rotation", "--bind", "value:i:0")
+	rotate(rotationPortrait)
+
 	// start testapp
 	run(t,
 		"adb", "shell", "am", "start", "-n",
@@ -95,14 +109,15 @@
 		Printf: t.Logf,
 	}
 
-	var PixelsPerPt float32
+	var pixelsPerPt float32
+	var orientation config.Orientation
 
 	comm.Recv("hello_from_testapp")
 	comm.Send("hello_from_host")
 	comm.Recv("lifecycle_visible")
-	comm.Recv("config", &PixelsPerPt)
-	if PixelsPerPt < 0.1 {
-		t.Fatalf("bad PixelsPerPt: %f", PixelsPerPt)
+	comm.Recv("config", &pixelsPerPt, &orientation)
+	if pixelsPerPt < 0.1 {
+		t.Fatalf("bad pixelsPerPt: %f", pixelsPerPt)
 	}
 	comm.Recv("paint")
 
@@ -119,6 +134,17 @@
 		t.Errorf("want touch end(50, 60), got %s(%d,%d)", ty, x, y)
 	}
 
+	rotate(rotationLandscape)
+	comm.Recv("config", &pixelsPerPt, &orientation)
+	if want := config.OrientationLandscape; orientation != want {
+		t.Errorf("want orientation %d, got %d", want, orientation)
+	}
+	rotate(rotationPortrait)
+	comm.Recv("config", &pixelsPerPt, &orientation)
+	if want := config.OrientationPortrait; orientation != want {
+		t.Errorf("want orientation %d, got %d", want, orientation)
+	}
+
 	// TODO: screenshot of gl.Clear to test painting
 	// TODO: lifecycle testing (NOTE: adb shell input keyevent 4 is the back button)
 	// TODO: orientation testing
diff --git a/app/darwin_amd64.go b/app/darwin_amd64.go
index 48df495..c194382 100644
--- a/app/darwin_amd64.go
+++ b/app/darwin_amd64.go
@@ -114,8 +114,7 @@
 var windowHeightPx float32
 
 //export setGeom
-func setGeom(ppp float32, widthPx, heightPx int) {
-	pixelsPerPt = ppp
+func setGeom(pixelsPerPt float32, widthPx, heightPx int) {
 	windowHeightPx = float32(heightPx)
 	eventsIn <- config.Event{
 		WidthPx:     widthPx,
diff --git a/app/darwin_armx.go b/app/darwin_armx.go
index 5a4f6d8..61bbefd 100644
--- a/app/darwin_armx.go
+++ b/app/darwin_armx.go
@@ -64,6 +64,7 @@
 	panic("unexpected return from app.runApp")
 }
 
+var pixelsPerPt float32
 var screenScale int // [UIScreen mainScreen].scale, either 1, 2, or 3.
 
 //export setScreen
diff --git a/app/internal/testapp/testapp.go b/app/internal/testapp/testapp.go
index 561a379..0228d10 100644
--- a/app/internal/testapp/testapp.go
+++ b/app/internal/testapp/testapp.go
@@ -53,7 +53,7 @@
 				}
 			case config.Event:
 				c = e
-				comm.Send("config", c.PixelsPerPt)
+				comm.Send("config", c.PixelsPerPt, c.Orientation)
 			case paint.Event:
 				if sendPainting {
 					comm.Send("paint")
diff --git a/app/x11.go b/app/x11.go
index cb03439..b1a9061 100644
--- a/app/x11.go
+++ b/app/x11.go
@@ -78,7 +78,7 @@
 func onResize(w, h int) {
 	// TODO(nigeltao): don't assume 72 DPI. DisplayWidth and DisplayWidthMM
 	// is probably the best place to start looking.
-	pixelsPerPt = 1
+	pixelsPerPt := 1
 	eventsIn <- config.Event{
 		WidthPx:     w,
 		HeightPx:    h,