Example #1
0
//export updateConfig
func updateConfig(width, height int) {
	eventsIn <- config.Event{
		Width:       geom.Pt(float32(screenScale*width) / pixelsPerPt),
		Height:      geom.Pt(float32(screenScale*height) / pixelsPerPt),
		PixelsPerPt: pixelsPerPt,
	}
}
Example #2
0
File: x11.go Project: Miaque/mojo
//export onResize
func onResize(w, h int) {
	// TODO(nigeltao): don't assume 72 DPI. DisplayWidth / DisplayWidthMM
	// is probably the best place to start looking.
	geom.PixelsPerPt = 1
	geom.Width = geom.Pt(w)
	geom.Height = geom.Pt(h)
}
Example #3
0
func processEvent(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:
		// 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
		upDownType := touch.TypeMove
		switch C.AMotionEvent_getAction(e) & C.AMOTION_EVENT_ACTION_MASK {
		case C.AMOTION_EVENT_ACTION_DOWN, C.AMOTION_EVENT_ACTION_POINTER_DOWN:
			upDownType = touch.TypeBegin
		case C.AMOTION_EVENT_ACTION_UP, C.AMOTION_EVENT_ACTION_POINTER_UP:
			upDownType = touch.TypeEnd
		}

		for i, n := C.size_t(0), C.AMotionEvent_getPointerCount(e); i < n; i++ {
			t := touch.TypeMove
			if i == upDownIndex {
				t = upDownType
			}
			eventsIn <- touch.Event{
				Sequence: touch.Sequence(C.AMotionEvent_getPointerId(e, i)),
				Type:     t,
				Loc: geom.Point{
					X: geom.Pt(float32(C.AMotionEvent_getX(e, i)) / pixelsPerPt),
					Y: geom.Pt(float32(C.AMotionEvent_getY(e, i)) / pixelsPerPt),
				},
			}
		}
	default:
		log.Printf("unknown input event, type=%d", C.AInputEvent_getType(e))
	}
}
Example #4
0
//export onResize
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
	eventsIn <- event.Config{
		Width:       geom.Pt(w),
		Height:      geom.Pt(h),
		PixelsPerPt: pixelsPerPt,
	}

	// This gl.Viewport call has to be in a separate goroutine because any gl
	// call can block until gl.DoWork is called, but this goroutine is the one
	// responsible for calling gl.DoWork.
	// TODO: does this (GL-using) code belong here in the x/mobile/app
	// package?? See similar TODOs in the Android x/mobile/app implementation.
	c := make(chan struct{})
	go func() {
		gl.Viewport(0, 0, w, h)
		close(c)
	}()
	for {
		select {
		case <-gl.WorkAvailable:
			gl.DoWork()
		case <-c:
			return
		}
	}
}
Example #5
0
func main() {
	e := Engine{}

	app.Main(func(a app.App) {
		var c size.Event
		for eve := range a.Events() {
			switch eve := app.Filter(eve).(type) {
			case lifecycle.Event:
				switch eve.Crosses(lifecycle.StageVisible) {
				case lifecycle.CrossOn:
					e.Start()
				case lifecycle.CrossOff:
					e.Stop()
				}
			case size.Event:
				c = eve
				e.touchLoc = geom.Point{c.WidthPt / 2, c.HeightPt / 2}
			case paint.Event:
				e.Draw(c)
				a.EndPaint(eve)
			case touch.Event:
				e.touchLoc = geom.Point{geom.Pt(eve.X), geom.Pt(eve.Y)}
			}
		}
	})
}
Example #6
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.PixelsPerPt),
				Y: geom.Pt(float32(y) / geom.PixelsPerPt),
			},
		})
	default:
		log.Printf("unknown input event, type=%d", C.AInputEvent_getType(e))
	}
}
Example #7
0
//export sendTouch
func sendTouch(touch, touchType uintptr, x, y float32) {
	id := -1
	for i, val := range touchIDs {
		if val == touch {
			id = i
			break
		}
	}
	if id == -1 {
		for i, val := range touchIDs {
			if val == 0 {
				touchIDs[i] = touch
				id = i
				break
			}
		}
		if id == -1 {
			panic("out of touchIDs")
		}
	}

	t := touch.Type(touchType)
	if t == touch.TypeEnd {
		touchIDs[id] = 0
	}

	eventsIn <- touch.Event{
		Sequence: touch.Sequence(id),
		Type:     t,
		Loc: geom.Point{
			X: geom.Pt(x / pixelsPerPt),
			Y: geom.Pt(y / pixelsPerPt),
		},
	}
}
Example #8
0
func windowDrawLoop(cb Callbacks, w *C.ANativeWindow, queue *C.AInputQueue) {
	C.createEGLWindow(w)

	// TODO: is the library or the app responsible for clearing the buffers?
	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.PixelsPerPt)
	geom.Height = geom.Pt(float32(C.windowHeight) / geom.PixelsPerPt)

	for {
		processEvents(cb, queue)
		select {
		case <-windowDestroyed:
			return
		default:
			if cb.Draw != nil {
				cb.Draw()
			}
			C.eglSwapBuffers(C.display, C.surface)
		}
	}
}
Example #9
0
func onPaint(glctx gl.Context, sz size.Event) {

	glctx.ClearColor(236, 240, 241, 1)
	glctx.Clear(gl.COLOR_BUFFER_BIT)

	columnOffset := (sz.WidthPt / 2) - ((geom.Pt(gridColumnsCount) * tileSize) / 2)
	rowOffset := (sz.HeightPt / 2) - ((geom.Pt(gridrowsCount) * tileSize) / 2)

	for c := 0; c < gridColumnsCount; c++ {

		for r := 0; r < gridrowsCount; r++ {

			t := &grid[((c+1)*(r+1))-1]

			t.columnOffset = columnOffset
			t.rowOffset = rowOffset
			t.x = geom.Pt(c) * tileSize
			t.y = geom.Pt(r) * tileSize
			t.Draw(sz)

		}

	}

}
Example #10
0
//export sendTouch
func sendTouch(touch, change uintptr, x, y float32) {
	id := -1
	for i, val := range touchIDs {
		if val == touch {
			id = i
			break
		}
	}
	if id == -1 {
		for i, val := range touchIDs {
			if val == 0 {
				touchIDs[i] = touch
				id = i
				break
			}
		}
		if id == -1 {
			panic("out of touchIDs")
		}
	}

	c := event.Change(change)
	if c == event.ChangeOff {
		touchIDs[id] = 0
	}

	eventsIn <- event.Touch{
		ID:     event.TouchSequenceID(id),
		Change: c,
		Loc: geom.Point{
			X: geom.Pt(x / pixelsPerPt),
			Y: geom.Pt(y / pixelsPerPt),
		},
	}
}
Example #11
0
func main() {
	defer func() {
		if err := recover(); err != nil {
			log.Println(err)
		}
	}()
	e := Engine{}
	app.Main(func(a app.App) {
		var c size.Event
		for eve := range a.Events() {
			switch eve := app.Filter(eve).(type) {
			case lifecycle.Event:
				switch eve.Crosses(lifecycle.StageVisible) {
				case lifecycle.CrossOn:
					e.Start()
				case lifecycle.CrossOff:
					e.Stop()
				}
			case size.Event:
				c = eve
				e.touchLoc = geom.Point{0, 0}
			case paint.Event:
				e.Draw(c)
				a.EndPaint(eve)
			case touch.Event:
				e.touchLoc = geom.Point{geom.Pt(eve.X), geom.Pt(eve.Y)}
			}
		}
	})
}
Example #12
0
func windowDraw(w *C.ANativeWindow, queue *C.AInputQueue, donec chan struct{}) (done bool) {
	// Android can send a windowRedrawNeeded event any time, including
	// in the middle of a paint cycle. The redraw event may have changed
	// the size of the screen, so any partial painting is now invalidated.
	// We must also not return to Android (via sending on windowRedrawDone)
	// until a complete paint with the new configuration is complete.
	//
	// When a windowRedrawNeeded request comes in, we increment redrawGen
	// (Gen is short for generation number), and do not make a paint cycle
	// visible on <-endPaint unless paintGen agrees. If possible,
	// windowRedrawDone is signalled, allowing onNativeWindowRedrawNeeded
	// to return.
	var redrawGen, paintGen uint32
	for {
		processEvents(queue)
		select {
		case <-donec:
			return true
		case cfg := <-windowConfigChange:
			// TODO save orientation
			pixelsPerPt = cfg.pixelsPerPt
		case w := <-windowRedrawNeeded:
			sendLifecycle(lifecycle.StageFocused)
			widthPx := int(C.ANativeWindow_getWidth(w))
			heightPx := int(C.ANativeWindow_getHeight(w))
			eventsIn <- config.Event{
				WidthPx:     widthPx,
				HeightPx:    heightPx,
				WidthPt:     geom.Pt(float32(widthPx) / pixelsPerPt),
				HeightPt:    geom.Pt(float32(heightPx) / pixelsPerPt),
				PixelsPerPt: pixelsPerPt,
			}
			if paintGen == 0 {
				paintGen++
				C.createEGLWindow(w)
				eventsIn <- paint.Event{}
			}
			redrawGen++
		case <-windowDestroyed:
			sendLifecycle(lifecycle.StageAlive)
			return false
		case <-gl.WorkAvailable:
			gl.DoWork()
		case <-endPaint:
			if paintGen == redrawGen {
				// eglSwapBuffers blocks until vsync.
				C.eglSwapBuffers(C.display, C.surface)
				select {
				case windowRedrawDone <- struct{}{}:
				default:
				}
			}
			paintGen = redrawGen
			eventsIn <- paint.Event{}
		}
	}
}
Example #13
0
//export setGeom
func setGeom(ppp float32, width, height int) {
	pixelsPerPt = ppp
	windowHeight = geom.Pt(float32(height) / pixelsPerPt)
	eventsIn <- config.Event{
		Width:       geom.Pt(float32(width) / pixelsPerPt),
		Height:      windowHeight,
		PixelsPerPt: pixelsPerPt,
	}
}
Example #14
0
func sendTouch(t touch.Type, x, y float32) {
	eventsIn <- touch.Event{
		Sequence: 0, // TODO: button??
		Type:     t,
		Loc: geom.Point{
			X: geom.Pt(x / pixelsPerPt),
			Y: geom.Pt(y / pixelsPerPt),
		},
	}
}
Example #15
0
func sendTouch(c event.Change, x, y float32) {
	eventsIn <- event.Touch{
		ID:     0,
		Change: c,
		Loc: geom.Point{
			X: geom.Pt(x / pixelsPerPt),
			Y: windowHeight - geom.Pt(y/pixelsPerPt),
		},
	}
}
Example #16
0
//export onResize
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
	eventsIn <- config.Event{
		Width:       geom.Pt(w),
		Height:      geom.Pt(h),
		PixelsPerPt: pixelsPerPt,
	}
}
Example #17
0
func sendTouch(t touch.Type, x, y float32) {
	eventsIn <- touch.Event{
		Sequence: 0,
		Type:     t,
		Loc: geom.Point{
			X: geom.Pt(x / pixelsPerPt),
			Y: windowHeight - geom.Pt(y/pixelsPerPt),
		},
	}
}
Example #18
0
func sendTouch(c event.Change, x, y float32) {
	eventsIn <- event.Touch{
		ID:     0, // TODO: button??
		Change: c,
		Loc: geom.Point{
			X: geom.Pt(x / pixelsPerPt),
			Y: geom.Pt(y / pixelsPerPt),
		},
	}
}
Example #19
0
//export setGeom
func setGeom(pixelsPerPt float32, widthPx, heightPx int) {
	windowHeightPx = float32(heightPx)
	eventsIn <- size.Event{
		WidthPx:     widthPx,
		HeightPx:    heightPx,
		WidthPt:     geom.Pt(float32(widthPx) / pixelsPerPt),
		HeightPt:    geom.Pt(float32(heightPx) / pixelsPerPt),
		PixelsPerPt: pixelsPerPt,
	}
}
Example #20
0
func sendTouch(ty event.TouchType, x, y float32) {
	events.Lock()
	events.pending = append(events.pending, event.Touch{
		Type: ty,
		Loc: geom.Point{
			X: geom.Pt(x / geom.PixelsPerPt),
			Y: geom.Height - geom.Pt(y/geom.PixelsPerPt),
		},
	})
	events.Unlock()
}
Example #21
0
//export updateConfig
func updateConfig(width, height int) {
	widthPx := screenScale * width
	heightPx := screenScale * height
	eventsIn <- config.Event{
		WidthPx:     widthPx,
		HeightPx:    heightPx,
		WidthPt:     geom.Pt(float32(widthPx) / pixelsPerPt),
		HeightPt:    geom.Pt(float32(heightPx) / pixelsPerPt),
		PixelsPerPt: pixelsPerPt,
	}
}
Example #22
0
func onTouch(t touch.Event) {
	if t.Type != touch.TypeBegin {
		return
	}

	touchLoc = geom.Point{X: geom.Pt(t.X), Y: geom.Pt(t.Y)}
	acceptTouch = true
	if !activate {
		activate = true
	}
}
Example #23
0
func scrollStats() (avg, stddev geom.Pt) {
	n := geom.Pt(len(scrollLoc))
	for _, x := range scrollLoc {
		avg += x
	}
	avg /= n
	for _, x := range scrollLoc {
		stddev += (x - avg) * (x - avg)
	}
	return avg, geom.Pt(math.Sqrt(float64(stddev / n)))
}
Example #24
0
File: x11.go Project: Miaque/mojo
func sendTouch(ty event.TouchType, x, y float32) {
	events.Lock()
	events.pending = append(events.pending, event.Touch{
		Type: ty,
		Loc: geom.Point{
			X: geom.Pt(x),
			Y: geom.Pt(y),
		},
	})
	events.Unlock()
}
Example #25
0
//export setGeom
func setGeom(ppp float32, widthPx, heightPx int) {
	pixelsPerPt = ppp
	windowHeightPx = float32(heightPx)
	eventsIn <- config.Event{
		WidthPx:     widthPx,
		HeightPx:    heightPx,
		WidthPt:     geom.Pt(float32(widthPx) / pixelsPerPt),
		HeightPt:    geom.Pt(float32(heightPx) / pixelsPerPt),
		PixelsPerPt: pixelsPerPt,
	}
}
Example #26
0
//export onResize
func onResize(w, h int) {
	// TODO(nigeltao): don't assume 72 DPI. DisplayWidth and DisplayWidthMM
	// is probably the best place to start looking.
	pixelsPerPt := float32(1)
	eventsIn <- size.Event{
		WidthPx:     w,
		HeightPx:    h,
		WidthPt:     geom.Pt(w),
		HeightPt:    geom.Pt(h),
		PixelsPerPt: pixelsPerPt,
	}
}
Example #27
0
func nearestKey(loc geom.Point) key {
	var key key
	dist := geom.Pt(math.MaxFloat32)
	for _, k := range keys {
		kb := k.base()
		dx := geom.Pt((kb.pitch-pitchOffset)/pitchRange)*geom.Width - loc.X
		dy := geom.Pt(1-kb.y)*geom.Height - loc.Y
		d := geom.Pt(math.Hypot(float64(dx), float64(dy)))
		if d < dist && d < geom.Pt(math.Max(8, kb.size/float64(geom.PixelsPerPt))) {
			dist = d
			key = k
		}
	}
	return key
}
Example #28
0
func sendSizeEvent(hwnd syscall.Handle, r *_RECT) {
	windowsMu.Lock()
	w := windows[hwnd]
	windowsMu.Unlock()

	width := int(r.Right - r.Left)
	height := int(r.Bottom - r.Top)
	// TODO(andlabs): don't assume that PixelsPerPt == 1
	w.Send(size.Event{
		WidthPx:     width,
		HeightPx:    height,
		WidthPt:     geom.Pt(width),
		HeightPt:    geom.Pt(height),
		PixelsPerPt: 1,
	})
}
Example #29
0
// TODO(crawshaw): It looks like we need a gl.RegisterInit feature.
// TODO(crawshaw): The gldebug mode needs to complain loudly when GL functions
//                 are called before init, because often they fail silently.
func fpsInit() {
	font := ""
	switch runtime.GOOS {
	case "android":
		font = "/system/fonts/DroidSansMono.ttf"
	case "darwin":
		font = "/Library/Fonts/Andale Mono.ttf"
	case "linux":
		font = "/usr/share/fonts/truetype/droid/DroidSansMono.ttf"
	default:
		panic(fmt.Sprintf("go.mobile/app/debug: unsupported runtime.GOOS %q", runtime.GOOS))
	}

	b, err := ioutil.ReadFile(font)
	if err != nil {
		panic(err)
	}
	f, err := freetype.ParseFont(b)
	if err != nil {
		panic(err)
	}
	monofont.SetFont(f)
	monofont.SetSrc(image.Black)
	monofont.SetHinting(freetype.FullHinting)

	toPx := func(x geom.Pt) int { return int(math.Ceil(float64(geom.Pt(x).Px()))) }
	fps.Image = glutil.NewImage(toPx(50), toPx(12))
	monofont.SetDst(fps.Image.RGBA)
	monofont.SetClip(fps.Bounds())
	monofont.SetDPI(72 * float64(geom.PixelsPerPt))
	monofont.SetFontSize(12)
}
Example #30
0
func (w *windowImpl) handleConfigureNotify(ev xproto.ConfigureNotifyEvent) {
	// TODO: lifecycle events.

	newWidth, newHeight := int(ev.Width), int(ev.Height)
	if w.width == newWidth && w.height == newHeight {
		return
	}
	w.width, w.height = newWidth, newHeight
	// TODO: don't assume that PixelsPerPt == 1.
	w.Send(size.Event{
		WidthPx:     newWidth,
		HeightPx:    newHeight,
		WidthPt:     geom.Pt(newWidth),
		HeightPt:    geom.Pt(newHeight),
		PixelsPerPt: 1,
	})
}