code: func (u *UserInterface) appMain(a app.App) {
  	var glctx gl.Context
  	touches := map[touch.Sequence]*Touch{}
  	for e := range a.Events() {
  		switch e := a.Filter(e).(type) {
  		case lifecycle.Event:
  			switch e.Crosses(lifecycle.StageVisible) {
  			case lifecycle.CrossOn:
  				glctx, _ = e.DrawContext.(gl.Context)
  				// Assume that glctx is always a same instance.
  				// Then, only once initializing should be enough.
  				if glContextCh != nil {
  					glContextCh <- glctx
  					glContextCh = nil
  				}
  				a.Send(paint.Event{})
  			case lifecycle.CrossOff:
  				glctx = nil
  			}
  		case size.Event:
  			u.setFullscreenImpl(e.WidthPx, e.HeightPx)
  		case paint.Event:
  			if glctx == nil || e.External {
  				continue
  			}
  			renderCh <- struct{}{}
  			<-renderChEnd
  			a.Publish()
  			a.Send(paint.Event{})
  		case touch.Event:
  			switch e.Type {
  			case touch.TypeBegin, touch.TypeMove:
  				s := getDeviceScale()
  				x, y := float64(e.X)/s, float64(e.Y)/s
  				// TODO: Is it ok to cast from int64 to int here?
  				touches[e.Sequence] = &Touch{
  					ID: int(e.Sequence),
  					X:  int(x),
  					Y:  int(y),
  				}
  			case touch.TypeEnd:
  				delete(touches, e.Sequence)
  			}
  			ts := []*Touch{}
  			for _, t := range touches {
  				ts = append(ts, t)
  			}
  			u.input.update(ts)
  		}
  	}
  }
docs: // appMain is the main routine for gomobile-build mode.