diff --git a/contrib/mobile/CMakeLists.txt b/contrib/mobile/CMakeLists.txt
index 9b13e723821c5fa06c197cf3972096047633d5d7..6359a8e411fab2419ccf729bc7ce3aed19d78b28 100644
--- a/contrib/mobile/CMakeLists.txt
+++ b/contrib/mobile/CMakeLists.txt
@@ -5,8 +5,8 @@ cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
 set(DEFAULT ON CACHE INTERNAL "Default value for enabled-by-default options")
 
 if(APPLE)
- option(ENABLE_BUILD_IOS "Build library for iOS (ARM)" OFF)
- option(ENABLE_BUILD_IOS_EMULATOR "Build library for iOS emulator (x86)" ON)
+ option(ENABLE_BUILD_IOS "Build XCode project for iOS (ARM)" OFF)
+ option(ENABLE_BUILD_IOS_EMULATOR "Build XCode project for iOS emulator (x86)" ON)
  option(ENABLE_BUILD_ANDROID "Build library for Android NDK (ARMv7)" OFF)
 else(APPLE)
   option(ENABLE_BUILD_ANDROID "Build library for Android NDK (ARMv7)" ON)
@@ -57,6 +57,8 @@ if(ENABLE_BUILD_IOS_EMULATOR OR ENABLE_BUILD_IOS)
     COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/iOS/ic_launcher_retina.png ${CMAKE_CURRENT_BINARY_DIR}/Onelab/
     COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/drawContext.cpp ${CMAKE_CURRENT_BINARY_DIR}/Onelab/Onelab/
     COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/drawContext.h ${CMAKE_CURRENT_BINARY_DIR}/Onelab/Onelab/
+    COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/drawGeom.cpp ${CMAKE_CURRENT_BINARY_DIR}/Onelab/Onelab/
+    COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/drawMesh.cpp ${CMAKE_CURRENT_BINARY_DIR}/Onelab/Onelab/
     COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/drawString.cpp ${CMAKE_CURRENT_BINARY_DIR}/Onelab/Onelab/
     COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/drawString.h ${CMAKE_CURRENT_BINARY_DIR}/Onelab/Onelab/
     COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/Trackball.cpp ${CMAKE_CURRENT_BINARY_DIR}/Onelab/Onelab/
diff --git a/contrib/mobile/drawContext.cpp b/contrib/mobile/drawContext.cpp
index 4748f935b5fc31052ec42ca545e668d79c4ed82e..e10b22d1f00fd8b5e341a61cd9cbce50a18e0a00 100644
--- a/contrib/mobile/drawContext.cpp
+++ b/contrib/mobile/drawContext.cpp
@@ -211,7 +211,7 @@ void drawContext::initView(int w, int h)
 	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 }
 
-void drawArray(VertexArray *va, GLint type, bool colorArray=false)
+void drawArray(VertexArray *va, GLint type, bool colorArray)
 {
 	if(!va) return;
 	glEnable(GL_BLEND);
@@ -465,21 +465,6 @@ void drawContext::drawScale()
 	glPopMatrix();
 }
 
-void drawContext::drawMesh()
-{
-	GModel::current()->fillVertexArrays();
-	unsigned int col = CTX::instance()->color.mesh.line;
-	glColor4ub((GLubyte)CTX::instance()->unpackRed(col),
-               (GLubyte)CTX::instance()->unpackGreen(col),
-               (GLubyte)CTX::instance()->unpackBlue(col),
-               (GLubyte)CTX::instance()->unpackAlpha(col));
-	for(GModel::fiter it = GModel::current()->firstFace(); it != GModel::current()->lastFace(); it++){
-		if(_fillMesh) drawArray((*it)->va_triangles, GL_TRIANGLES);
-		else drawArray((*it)->va_lines, GL_LINES, true);
-	}
-	CTX::instance()->mesh.changed = 0;
-}
-
 void drawContext::drawPost()
 {
 	if(PView::list.empty()) return ;
@@ -490,39 +475,6 @@ void drawContext::drawPost()
 	}
 }
 
-void drawContext::drawGeom()
-{
-	unsigned int col = CTX::instance()->color.geom.line;
-	glColor4ub((GLubyte)CTX::instance()->unpackRed(col),
-               (GLubyte)CTX::instance()->unpackGreen(col),
-               (GLubyte)CTX::instance()->unpackBlue(col),
-               (GLubyte)CTX::instance()->unpackAlpha(col));
-	//glLineWidth((GLfloat)CTX::instance()->geom.lineWidth); OpenGL Error -> GL_INVALID_VALUE​, 0x0501
-	for(GModel::eiter it = GModel::current()->firstEdge(); it != GModel::current()->lastEdge(); it++){
-		GEdge *e = *it;
-		int N = e->minimumDrawSegments() + 1; // e is sometime incorrect (e.g. 0x0000004f) when compute
-		Range<double> t_bounds = e->parBounds(0);
-		double t_min = t_bounds.low();
-		double t_max = t_bounds.high();
-        
-		// Create a VA for this edge
-		GLfloat *edge = (GLfloat *) malloc(N*3*sizeof(GLfloat));
-        
-		for(unsigned int i=0; i < N; i++) {
-			double t = t_min + (double)i / (double)(N-1) * (t_max - t_min);
-			GPoint p = e->point(t);
-			edge[i*3] = p.x(); edge[i*3+1] = p.y(); edge[i*3+2] = p.z();
-		}
-		// Then print the VA
-		glVertexPointer(3, GL_FLOAT, 0, edge);
-		glEnableClientState(GL_VERTEX_ARRAY);
-		glDrawArrays(GL_LINE_STRIP, 0, N);
-		glDisableClientState(GL_VERTEX_ARRAY);
-        free(edge);
-	}
-	glLineWidth(1);
-}
-
 void drawContext::drawAxes(float x0, float y0, float z0, float h)
 {
 	glLineWidth(1.);
diff --git a/contrib/mobile/drawGeom.cpp b/contrib/mobile/drawGeom.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f642a51d9e113c85d45bb9cc86acad49a3c7b0d1
--- /dev/null
+++ b/contrib/mobile/drawGeom.cpp
@@ -0,0 +1,92 @@
+#if !defined(BUILD_ANDROID)
+#define BUILD_IOS 1
+#endif
+
+#if defined(BUILD_IOS)
+#include <OpenGLES/ES1/gl.h>
+#include <OpenGLES/ES1/glext.h>
+
+#include <Gmsh/Gmsh.h>
+#include <Gmsh/GModel.h>
+#endif
+
+#if defined(BUILD_ANDROID)
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+
+#include <gmsh/Gmsh.h>
+#include <gmsh/GModel.h>
+#endif
+
+#include "drawContext.h"
+
+void drawGeomVertex(GVertex *v)
+{
+	if(!v->getVisibility()) return;
+	if(v->geomType() == GEntity::BoundaryLayerPoint) return;
+
+	unsigned int col = CTX::instance()->color.geom.point;
+	glColor4ub((GLubyte)CTX::instance()->unpackRed(col),
+               (GLubyte)CTX::instance()->unpackGreen(col),
+               (GLubyte)CTX::instance()->unpackBlue(col),
+               (GLubyte)CTX::instance()->unpackAlpha(col));
+	const GLfloat p[] = {(GLfloat)v->x(), (GLfloat)v->y(), (GLfloat)v->z()};
+	glPointSize((GLfloat)(CTX::instance()->geom.pointSize>0)? 3:1);
+	glVertexPointer(3, GL_FLOAT, 0, p);
+	glEnableClientState(GL_VERTEX_ARRAY);
+	glDrawArrays(GL_POINTS, 0, 1);
+	glDisableClientState(GL_VERTEX_ARRAY);
+	glPointSize(1);
+}
+void drawGeomEdge(GEdge *e)
+{
+	if(!e->getVisibility()) return;
+	if(e->geomType() == GEntity::DiscreteCurve) return;
+	if(e->geomType() == GEntity::PartitionCurve) return;
+	if(e->geomType() == GEntity::BoundaryLayerCurve) return;
+
+	unsigned int col = CTX::instance()->color.geom.line;
+	glColor4ub((GLubyte)CTX::instance()->unpackRed(col),
+               (GLubyte)CTX::instance()->unpackGreen(col),
+               (GLubyte)CTX::instance()->unpackBlue(col),
+               (GLubyte)CTX::instance()->unpackAlpha(col));
+	int N = e->minimumDrawSegments() + 1;
+	Range<double> t_bounds = e->parBounds(0);
+	double t_min = t_bounds.low();
+	double t_max = t_bounds.high();
+
+	// Create a VA for this edge
+	GLfloat *edge = (GLfloat *) malloc(N*3*sizeof(GLfloat));
+		
+	for(unsigned int i=0; i < N; i++) {
+		double t = t_min + (double)i / (double)(N-1) * (t_max - t_min);
+		GPoint p = e->point(t);
+		edge[i*3] = p.x(); edge[i*3+1] = p.y(); edge[i*3+2] = p.z();
+	}
+	// Then print the VA
+	glVertexPointer(3, GL_FLOAT, 0, edge);
+	glEnableClientState(GL_VERTEX_ARRAY);
+	glDrawArrays(GL_LINE_STRIP, 0, N);
+	glDisableClientState(GL_VERTEX_ARRAY);
+        free(edge);
+}
+void drawGeomFace(GFace *f)
+{
+	// TODO
+}
+void drawContext::drawGeom()
+{
+	for(unsigned int i=0; i<GModel::list.size(); i++) {
+		GModel *m = GModel::list[i];
+		if(!m->getVisibility()) continue;
+		if(CTX::instance()->geom.points || CTX::instance()->geom.pointsNum)
+			std::for_each(m->firstVertex(), m->lastVertex(), drawGeomVertex);
+		if(CTX::instance()->geom.lines || CTX::instance()->geom.linesNum || CTX::instance()->geom.tangents)
+			std::for_each(m->firstEdge(), m->lastEdge(), drawGeomEdge);
+		if(CTX::instance()->geom.surfaces || CTX::instance()->geom.surfacesNum || CTX::instance()->geom.normals)
+			std::for_each(m->firstFace(), m->lastFace(), drawGeomFace);
+
+	}
+}
+
+
diff --git a/contrib/mobile/drawMesh.cpp b/contrib/mobile/drawMesh.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7257981a099002c86353d04b235dbb62952ab4c7
--- /dev/null
+++ b/contrib/mobile/drawMesh.cpp
@@ -0,0 +1,120 @@
+#if !defined(BUILD_ANDROID)
+#define BUILD_IOS 1
+#endif
+
+#if defined(BUILD_IOS)
+#include <OpenGLES/ES1/gl.h>
+#include <OpenGLES/ES1/glext.h>
+
+#include <Gmsh/Gmsh.h>
+#include <Gmsh/GModel.h>
+#include <Gmsh/GEdgeCompound.h>
+#include <Gmsh/GFaceCompound.h>
+#include <Gmsh/PView.h>
+#include <Gmsh/PViewData.h>
+#endif
+
+#if defined(BUILD_ANDROID)
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+
+#include <gmsh/Gmsh.h>
+#include <gmsh/GModel.h>
+#include <gmsh/GEdgeCompound.h>
+#include <gmsh/GFaceCompound.h>
+#include <gmsh/PView.h>
+#include <gmsh/PViewData.h>
+#endif
+
+#include "drawContext.h"
+
+// from GModelVertexArrays
+extern unsigned int getColorByEntity(GEntity *e);
+
+void drawMeshVertex(GVertex *e)
+{
+    if(!CTX::instance()->mesh.points && !CTX::instance()->mesh.pointsNum) return;
+	std::vector<GLfloat> vertex;
+	std::vector<GLubyte> color;
+	for(unsigned int i = 0; i < e->mesh_vertices.size(); i++){
+		MVertex *v = e->mesh_vertices[i];
+		if(!v->getVisibility()) continue;
+        unsigned int col;
+		if(CTX::instance()->mesh.colorCarousel == 0 || CTX::instance()->mesh.volumesFaces || CTX::instance()->mesh.surfacesFaces) {
+			if(v->getPolynomialOrder() > 1)
+				col = CTX::instance()->color.mesh.vertexSup;
+			else
+				col = CTX::instance()->color.mesh.vertex;
+		}
+        else
+            col = getColorByEntity(e);
+        color.push_back((GLubyte)CTX::instance()->unpackRed(col));
+        color.push_back((GLubyte)CTX::instance()->unpackGreen(col));
+        color.push_back((GLubyte)CTX::instance()->unpackBlue(col));
+        color.push_back((GLubyte)CTX::instance()->unpackAlpha(col));
+		vertex.push_back(v->x());
+		vertex.push_back(v->y());
+		vertex.push_back(v->z());
+	}
+	glVertexPointer(3, GL_FLOAT, 0, &vertex.front());
+	glEnableClientState(GL_VERTEX_ARRAY);
+    glColorPointer(4, GL_UNSIGNED_BYTE, color.size()/4, &color.front());
+    glEnableClientState(GL_COLOR_ARRAY);
+	glDrawArrays(GL_POINTS, 0, vertex.size()/3);
+	glDisableClientState(GL_VERTEX_ARRAY);
+    glDisableClientState(GL_COLOR_ARRAY);
+}
+void drawMeshEdge(GEdge *e)
+{
+    if(!e->getVisibility()) {
+        if(e->getCompound()) {
+            if(!e->getCompound()->getVisibility()) return;
+        }
+        else
+            return;
+    }
+	drawArray(e->va_lines, GL_LINES, true);
+}
+void drawMeshFace(GFace *f)
+{
+    if(!f->getVisibility()) {
+        if(f->getCompound()) {
+            if(!f->getCompound()->getVisibility()) return;
+        }
+        else
+            return;
+    }
+	drawArray(f->va_lines, GL_LINES, true);
+}
+
+void drawContext::drawMesh()
+{
+	if(!CTX::instance()->mesh.draw) return;
+
+	if(CTX::instance()->mesh.changed)
+		for(unsigned int i = 0; i < GModel::list.size(); i++)
+			for(unsigned int j = 0; j < PView::list.size(); j++)
+				if(PView::list[j]->getData()->hasModel(GModel::list[i]))
+					PView::list[j]->setChanged(true);
+
+    unsigned int col = CTX::instance()->color.mesh.line;
+	glColor4ub((GLubyte)CTX::instance()->unpackRed(col),
+               (GLubyte)CTX::instance()->unpackGreen(col),
+               (GLubyte)CTX::instance()->unpackBlue(col),
+               (GLubyte)CTX::instance()->unpackAlpha(col));
+	for(unsigned int i = 0; i < GModel::list.size(); i++){
+		GModel *m = GModel::list[i];
+		m->fillVertexArrays();
+		if(!m->getVisibility()) continue;
+		int status = m->getMeshStatus();
+		if(status >= 0)
+            std::for_each(m->firstVertex(), m->lastVertex(), drawMeshVertex);
+		if(status >= 1)
+			std::for_each(m->firstEdge(), m->lastEdge(), drawMeshEdge);
+		if(status >= 2)
+            std::for_each(m->firstFace(), m->lastFace(), drawMeshFace);
+	}
+	CTX::instance()->mesh.changed = 0;
+}
+
+
diff --git a/contrib/mobile/iOS/Onelab/SplitViewController.mm b/contrib/mobile/iOS/Onelab/SplitViewController.mm
index 59ffd586a5186c72e8bf1fbca087563e42046252..0b51aef27f45bbddd81d36952cb33e8c0589841b 100644
--- a/contrib/mobile/iOS/Onelab/SplitViewController.mm
+++ b/contrib/mobile/iOS/Onelab/SplitViewController.mm
@@ -40,6 +40,7 @@
 	 }
 	 }*/
 	self.delegate = detailViewController;
+	[self setPresentsWithGesture:NO];
 }
 
 -(void)viewDidAppear:(BOOL)animated