diff --git a/examples/api/CMakeLists.txt b/examples/api/CMakeLists.txt
index 35e49024157ffa64172ef708549e1225065d815f..6ec8855830f564abc7eb1f7791ebf16365f10d8b 100644
--- a/examples/api/CMakeLists.txt
+++ b/examples/api/CMakeLists.txt
@@ -73,13 +73,13 @@ foreach(EXAMPLE ${EXAMPLES})
             </plist>")
       set_target_properties(${EXAMPLENAME} PROPERTIES MACOSX_BUNDLE_INFO_PLIST
                             ${CMAKE_CURRENT_BINARY_DIR}/${EXAMPLENAME}.plist)
-      add_test(${EXAMPLENAME} ${EXAMPLENAME}.app/Contents/MacOS/${EXAMPLENAME})
+      add_test(${EXAMPLENAME}_cpp ${EXAMPLENAME}.app/Contents/MacOS/${EXAMPLENAME} -nopopup)
     else()
-      add_test(${EXAMPLENAME} ${EXAMPLENAME})
+      add_test(${EXAMPLENAME}_cpp ${EXAMPLENAME} -nopopup)
     endif()
   else()
     add_executable(${EXAMPLENAME} ${EXAMPLE})
-    add_test(${EXAMPLENAME}_cpp ${EXAMPLENAME})
+    add_test(${EXAMPLENAME}_cpp ${EXAMPLENAME} -nopopup)
   endif()
   target_link_libraries(${EXAMPLENAME} ${GMSH_LIB} ${EXTRA_LIBS})
 endforeach()
@@ -89,10 +89,10 @@ foreach(EXAMPLE ${EXAMPLES})
   get_filename_component(EXAMPLENAME ${EXAMPLE} NAME_WE)
   add_executable(${EXAMPLENAME}c ${EXAMPLE})
   target_link_libraries(${EXAMPLENAME}c ${GMSH_LIB} ${EXTRA_LIBS})
-  add_test(${EXAMPLENAME}_c ${EXAMPLENAME}c)
+  add_test(${EXAMPLENAME}_c ${EXAMPLENAME}c -nopopup)
 endforeach()
 
-find_program(PYTHON python)
+find_program(PYTHON python3)
 if(PYTHON)
   file(GLOB EXAMPLES *.py)
   foreach(EXAMPLE ${EXAMPLES})
@@ -106,6 +106,6 @@ if(JULIA)
   file(GLOB EXAMPLES *.jl)
   foreach(EXAMPLE ${EXAMPLES})
     get_filename_component(EXAMPLENAME ${EXAMPLE} NAME_WE)
-    add_test(${EXAMPLENAME}_jl ${JULIA} ${EXAMPLE})
+    add_test(${EXAMPLENAME}_jl ${JULIA} ${EXAMPLE} -nopopup)
   endforeach()
 endif()
diff --git a/examples/api/adapt_mesh.cpp b/examples/api/adapt_mesh.cpp
index 2c1d18f1417b488b05cc7899585ef4280349505f..2d337c99c4c36ab21f6635e03a457b028cab88d1 100644
--- a/examples/api/adapt_mesh.cpp
+++ b/examples/api/adapt_mesh.cpp
@@ -1,6 +1,7 @@
 #include <gmsh.h>
 #include <cmath>
 #include <map>
+#include <set>
 #include <complex>
 
 class myVertex {
@@ -217,6 +218,10 @@ int main(int argc, char **argv)
   double lc = 0.02;
   int N = 10000;
   bool dumpfiles = false;
+
+  std::set<std::string> args(argv, argv + argc);
+  if(args.count("-nopopup")) argc--;
+
   if(argc > 1) lc = atof(argv[1]);
   if(argc > 2) N = atoi(argv[2]);
   if(argc > 3) dumpfiles = atoi(argv[3]);
@@ -287,7 +292,7 @@ int main(int argc, char **argv)
   if(dumpfiles) gmsh::view::write(err2_view, "err2.pos");
 
   // show everything in the gui
-  gmsh::fltk::run();
+  if(!args.count("-nopopup")) gmsh::fltk::run();
 
   gmsh::finalize();
   return 0;
diff --git a/examples/api/aneurysm.py b/examples/api/aneurysm.py
index 56de81ecf769f45f20ec0543eac0a3135f317e6a..5ad2a9cd9f04f71979970f7ef314d9b1d038b809 100644
--- a/examples/api/aneurysm.py
+++ b/examples/api/aneurysm.py
@@ -1,12 +1,14 @@
 import gmsh
 import sys
+import os
 import math
 
 gmsh.initialize(sys.argv)
 
 # merge STL, create surface patches that are reparametrizable (so we can remesh
 # them) and compute the parametrizations
-gmsh.merge('aneurysm_data.stl')
+path = os.path.dirname(os.path.abspath(__file__))
+gmsh.merge(os.path.join(path, 'aneurysm_data.stl'))
 gmsh.model.mesh.classifySurfaces(math.pi, True, True)
 gmsh.model.mesh.createGeometry()
 
diff --git a/examples/api/closest_point.py b/examples/api/closest_point.py
index 94c3fe559a96f13545738a9b94636ce703fb1190..acbcbcb2983d4576d6e2d385af897051f147463f 100644
--- a/examples/api/closest_point.py
+++ b/examples/api/closest_point.py
@@ -18,6 +18,7 @@ gmsh.model.occ.fragment([(0, pp)], [(1, c)])
 
 gmsh.model.occ.synchronize()
 
-gmsh.fltk.run()
+if '-nopopup' not in sys.argv:
+    gmsh.fltk.run()
 
 gmsh.finalize()
diff --git a/examples/api/copy_mesh.py b/examples/api/copy_mesh.py
index aff7bef167298be62163c1a724564a4bebfc6e1a..b3fde5d1f667382e3a7e39f5f8882a37afbb4d4b 100644
--- a/examples/api/copy_mesh.py
+++ b/examples/api/copy_mesh.py
@@ -1,4 +1,5 @@
 import gmsh
+import sys
 
 gmsh.initialize()
 
@@ -52,5 +53,7 @@ gmsh.option.setNumber("Mesh.Algorithm3D", 10)
 gmsh.model.mesh.clear()
 gmsh.model.mesh.generate(3)
 
-gmsh.fltk.run()
+if '-nopopup' not in sys.argv:
+    gmsh.fltk.run()
+
 gmsh.finalize()
diff --git a/examples/api/edges.cpp b/examples/api/edges.cpp
index af29210e47067bb2b62e5b87395c70aecc5a663f..7b8accc3f65b94ff37b477b49df565bca195fcee 100644
--- a/examples/api/edges.cpp
+++ b/examples/api/edges.cpp
@@ -1,5 +1,6 @@
 #include <cstdio>
 #include <gmsh.h>
+#include <set>
 
 int main(int argc, char **argv)
 {
@@ -97,7 +98,8 @@ int main(int argc, char **argv)
     gmsh::model::mesh::getJacobians(eleType1D, uvw, jac, det, pts, c);
   }
 
-  gmsh::fltk::run();
+  std::set<std::string> args(argv, argv + argc);
+  if(!args.count("-nopopup")) gmsh::fltk::run();
 
   gmsh::finalize();
   return 0;
diff --git a/examples/api/faces.cpp b/examples/api/faces.cpp
index ef21c8f6e113a234c1fd23eeb1e5c2ecb79a46ab..15130031b2a41f235134ec7f4d9bac1bb9dbc7f9 100644
--- a/examples/api/faces.cpp
+++ b/examples/api/faces.cpp
@@ -1,5 +1,6 @@
 #include <cstdio>
 #include <gmsh.h>
+#include <set>
 
 int main(int argc, char **argv)
 {
@@ -97,7 +98,8 @@ int main(int argc, char **argv)
     gmsh::model::mesh::getJacobians(eleType2D, uvw, jac, det, pts, s);
   }
 
-  gmsh::fltk::run();
+  std::set<std::string> args(argv, argv + argc);
+  if(!args.count("-nopopup")) gmsh::fltk::run();
 
   gmsh::finalize();
   return 0;
diff --git a/examples/api/fragment_surfaces.cpp b/examples/api/fragment_surfaces.cpp
index af1dc83df68ab1a2f82ead08f47f2e1b0d8e376f..bfb7ab0b56f828934d960e961ae1cd6e59074684 100644
--- a/examples/api/fragment_surfaces.cpp
+++ b/examples/api/fragment_surfaces.cpp
@@ -1,6 +1,7 @@
 #include <gmsh.h>
+#include <set>
 
-int main()
+int main(int argc, char **argv)
 {
   gmsh::initialize();
   int s1 = gmsh::model::occ::addRectangle(0, 0, 0, 1, 1);
@@ -10,5 +11,7 @@ int main()
   std::vector<std::vector<std::pair<int, int> > > outmap;
   gmsh::model::occ::fragment({{2, s1}}, {{2, s2}}, out, outmap);
   gmsh::model::occ::synchronize();
-  gmsh::fltk::run();
+
+  std::set<std::string> args(argv, argv + argc);
+  if(!args.count("-nopopup")) gmsh::fltk::run();
 }
diff --git a/examples/api/gui.cpp b/examples/api/gui.cpp
index e8420779255f339693eaf08e2eab497fc17ba28a..8e450b052aacbc5d0a295aedf167cab2956c6127 100644
--- a/examples/api/gui.cpp
+++ b/examples/api/gui.cpp
@@ -1,8 +1,12 @@
 #include <cstdio>
 #include <gmsh.h>
+#include <set>
 
 int main(int argc, char **argv)
 {
+  std::set<std::string> args(argv, argv + argc);
+  if(args.count("-nopopup")) exit(0);
+
   gmsh::initialize(argc, argv);
 
   // creates the FLTK user interface; this could also be called after the
diff --git a/examples/api/gui.jl b/examples/api/gui.jl
index 8cba16c0cb944573f38acd2b606956817c70a8ad..a7b5b7aa1d6f2ea1dd3653069f5bc3be3b2549f8 100644
--- a/examples/api/gui.jl
+++ b/examples/api/gui.jl
@@ -1,5 +1,9 @@
 import gmsh
 
+if "-nopopup" in ARGS
+    exit(0)
+end
+
 gmsh.initialize(append!(["gmsh"], ARGS))
 
 # creates the FLTK user interface; this could also be called after the geometry
diff --git a/examples/api/gui.py b/examples/api/gui.py
index e3fb0353b4c3a0843d0345f769e82b15e18f8d4b..14d6d4e842a0efb8fb8d81932c143ede6099f4fb 100644
--- a/examples/api/gui.py
+++ b/examples/api/gui.py
@@ -1,12 +1,14 @@
 import gmsh
 import sys
 
+if '-nopopup' in sys.argv:
+    exit(0)
+
 gmsh.initialize(sys.argv)
 
 # creates the FLTK user interface; this could also be called after the geometry
 # is created (or not at all - fltk.run() will do it automatically)
-if '-nopopup' not in sys.argv:
-    gmsh.fltk.initialize()
+gmsh.fltk.initialize()
 
 # Copied from boolean.py...
 gmsh.model.add("boolean")
@@ -39,7 +41,6 @@ gmsh.model.setColor(gmsh.model.getEntities(2), 249, 166, 2)
 #     gmsh.fltk.wait()
 #     print("just treated an event in the interface")
 
-if '-nopopup' not in sys.argv:
-    gmsh.fltk.run()
+gmsh.fltk.run()
 
 gmsh.finalize()
diff --git a/examples/api/mirror_mesh.py b/examples/api/mirror_mesh.py
index 1331472ccafd3fbd5c00b6a9c929c9f125c754fd..16beaee62180bdc58cb309311a57c14233222619 100644
--- a/examples/api/mirror_mesh.py
+++ b/examples/api/mirror_mesh.py
@@ -3,6 +3,7 @@
 # overall conforming mesh
 
 import gmsh
+import sys
 
 gmsh.initialize()
 
@@ -50,4 +51,5 @@ transform(m, 3000, 3000000, 3000000, -1, -1, 1)
 # boundaries
 gmsh.model.mesh.removeDuplicateNodes()
 
-gmsh.fltk.run()
+if '-nopopup' not in sys.argv:
+    gmsh.fltk.run()
diff --git a/examples/api/naca_boundary_layer_2d.py b/examples/api/naca_boundary_layer_2d.py
index 0623f8092a8502e4c44becc4d2bed44bdfa17a16..e1eeffd472b17e645398266f149bc90e29d0f8b8 100644
--- a/examples/api/naca_boundary_layer_2d.py
+++ b/examples/api/naca_boundary_layer_2d.py
@@ -70,7 +70,8 @@ if by_extrusion:
     gmsh.model.occ.synchronize()
     # a boundary layer can be created through extrusion using the built-in CAD
     # kernel: this creates topological entities that will be filled with a
-    # discrete geometry (a mesh) during mesh generation
+    # discrete geometry (a mesh extruded along the boundary normals) during mesh
+    # generation
     n = np.linspace(1, 1, 7)
     d = np.logspace(-4, -2, 7)
     extbl = gmsh.model.geo.extrudeBoundaryLayer(gmsh.model.getEntities(1),
diff --git a/examples/api/naca_boundary_layer_3d.py b/examples/api/naca_boundary_layer_3d.py
index 52bca883f89be4fd6b5db062dda1a7ca1ca09303..290bed28729788ac2999ca6d0353940c399e8205 100644
--- a/examples/api/naca_boundary_layer_3d.py
+++ b/examples/api/naca_boundary_layer_3d.py
@@ -85,9 +85,10 @@ gmsh.model.occ.synchronize()
 
 # create a boundary layer for all the surfaces through extrusion using the
 # built-in CAD kernel: this creates topological entities that will be filled
-# with a discrete geometry (a mesh) during mesh generation; more general
-# boundary layer meshing constraints are currently only available in 2D, through
-# the BoundaryLayer Field - see 'naca_boundary_layer_2d.py'.
+# with a discrete geometry (a mesh extruded along the boundary normals) during
+# mesh generation; more general boundary layer meshing constraints are also
+# available in 2D through the BoundaryLayer Field - see
+# 'naca_boundary_layer_2d.py'.
 n = np.linspace(1, 1, 7)
 d = np.logspace(-4, -2, 7)
 extbl = gmsh.model.geo.extrudeBoundaryLayer(gmsh.model.getEntities(2),
diff --git a/examples/api/onelab_test.jl b/examples/api/onelab_test.jl
index 6803f698d6d92c08d855104c4fff78fab047c2bd..7ba2baf672721693715ff4bd0e445d4fbe1812b2 100644
--- a/examples/api/onelab_test.jl
+++ b/examples/api/onelab_test.jl
@@ -41,6 +41,8 @@ gmsh.onelab.setString("string 1", ["goodbye"])
 # remove a parameter
 gmsh.onelab.clear("string 2")
 
-gmsh.fltk.run()
+if !("-nopopup" in ARGS)
+    gmsh.fltk.run()
+end
 
 gmsh.finalize()
diff --git a/examples/api/onelab_test.py b/examples/api/onelab_test.py
index b4f4be129aa5886c91f1a9010a201dd10f053c45..3f394ec8df937254dad55a91e1b57b33f573cdd4 100644
--- a/examples/api/onelab_test.py
+++ b/examples/api/onelab_test.py
@@ -2,7 +2,6 @@ import gmsh
 import sys
 import json
 import math
-import thread
 
 gmsh.initialize()
 
diff --git a/examples/api/partition.cpp b/examples/api/partition.cpp
index 39c7090f75c5bc2edc0eda4d24ee26723d70a8e2..f4ef6a13fa8b05857e3002ae88404824ff90e5e8 100644
--- a/examples/api/partition.cpp
+++ b/examples/api/partition.cpp
@@ -1,5 +1,6 @@
 #include <gmsh.h>
 #include <iostream>
+#include <set>
 
 int main(int argc, char **argv)
 {
@@ -68,7 +69,9 @@ int main(int argc, char **argv)
       std::cout << "\n";
     }
   }
-  gmsh::fltk::run();
+
+  std::set<std::string> args(argv, argv + argc);
+  if(!args.count("-nopopup")) gmsh::fltk::run();
 
   gmsh::finalize();
 
diff --git a/examples/api/raw_tetrahedralization.py b/examples/api/raw_tetrahedralization.py
index 913af7c29e3edb4fac8e8c8201ad5d29552624f3..d9dcfd147d0733ea22a31e072045e0f5f032ad38 100644
--- a/examples/api/raw_tetrahedralization.py
+++ b/examples/api/raw_tetrahedralization.py
@@ -1,11 +1,12 @@
 import numpy as np
 import gmsh
+import sys
 
 # number of points to tetrahedralize
 N = 100
 
 # visualize the mesh?
-visu = True
+visu = ("-nopopup" not in sys.argv)
 
 gmsh.initialize()
 
diff --git a/examples/api/raw_triangulation.py b/examples/api/raw_triangulation.py
index d5c8f0f54b3d7094352a9d04b78f6b1296a81218..f3df634376f7cc87354383ba1215917244078c01 100644
--- a/examples/api/raw_triangulation.py
+++ b/examples/api/raw_triangulation.py
@@ -1,11 +1,12 @@
 import numpy as np
 import gmsh
+import sys
 
 # number of points to trianguate
 N = 100
 
 # visualize the mesh?
-visu = True
+visu = ("-nopopup" not in sys.argv)
 
 gmsh.initialize()
 
diff --git a/examples/api/spherical_surf.jl b/examples/api/spherical_surf.jl
index b80c7b65db369e6430345761f77a9c1eda82a033..6125c70a43e5414a20b8908e055abe3e10f3ffbb 100644
--- a/examples/api/spherical_surf.jl
+++ b/examples/api/spherical_surf.jl
@@ -13,5 +13,9 @@ gmsh.model.occ.synchronize()
 
 gmsh.model.removeEntities([(3,sph)])
 gmsh.model.removeEntities([(2,2), (2,4), (2,6)], true)
-gmsh.fltk.run()
+
+if !("-nopopup" in ARGS)
+    gmsh.fltk.run()
+end
+
 gmsh.finalize()
diff --git a/examples/api/spline.cpp b/examples/api/spline.cpp
index 0e37b3b93fbd1b082b69450c67ff06ed87a20141..5d7b73bf60568383cfdbad29bc7b7ee99955c66a 100644
--- a/examples/api/spline.cpp
+++ b/examples/api/spline.cpp
@@ -1,4 +1,5 @@
 #include <gmsh.h>
+#include <set>
 
 int main(int argc, char **argv)
 {
@@ -35,7 +36,10 @@ int main(int argc, char **argv)
                                {3, 1, 3});
 
   gmsh::model::occ::synchronize();
-  gmsh::fltk::run();
+
+  std::set<std::string> args(argv, argv + argc);
+  if(!args.count("-nopopup")) gmsh::fltk::run();
+
   gmsh::finalize();
   return 0;
 }
diff --git a/examples/api/split_window.py b/examples/api/split_window.py
index 8137c964c4cc116d1c1821bfe96df742ec2fbed5..a043c83ef4ef7e09646ab864a3db0fbb84249055 100644
--- a/examples/api/split_window.py
+++ b/examples/api/split_window.py
@@ -1,6 +1,9 @@
 import gmsh
 import sys
 
+if '-nopopup' in sys.argv:
+    exit(0)
+
 gmsh.initialize(sys.argv)
 
 # create simple geometry
diff --git a/examples/api/square.cpp b/examples/api/square.cpp
index 18714c149a5ef457418b9b244d68a335db82fc93..c7e6fce6cff04e345227d460504dbf5c2a8048c4 100644
--- a/examples/api/square.cpp
+++ b/examples/api/square.cpp
@@ -1,5 +1,7 @@
 #include <gmsh.h>
-int main()
+#include <set>
+
+int main(int argc, char **argv)
 {
   gmsh::initialize();
   gmsh::model::occ::addRectangle(0, 0, 0, 1, 1, 1);
@@ -8,6 +10,9 @@ int main()
   gmsh::option::setNumber("Mesh.MeshSizeMin", 1);
   gmsh::option::setNumber("Mesh.MeshSizeMax", 1);
   gmsh::model::mesh::generate();
-  gmsh::fltk::run();
+
+  std::set<std::string> args(argv, argv + argc);
+  if(!args.count("-nopopup")) gmsh::fltk::run();
+
   gmsh::finalize();
 }
diff --git a/examples/api/surface_filling.py b/examples/api/surface_filling.py
index 1518baedeef2f554f3d181450152190da8aa3006..d0f9d7f3696af8f0f092a7e9d5599c1344af1bec 100644
--- a/examples/api/surface_filling.py
+++ b/examples/api/surface_filling.py
@@ -1,4 +1,5 @@
 import gmsh
+import sys
 
 gmsh.initialize()
 gmsh.option.setNumber('Mesh.MeshSizeMin', 0.02)
@@ -29,4 +30,8 @@ gmsh.model.occ.addPoint(-0.67, 0.1, -0.2, 8)
 gmsh.model.occ.addSurfaceFilling(1, 4, [7, 8])
 
 gmsh.model.occ.synchronize()
-gmsh.fltk.run()
+
+if '-nopopup' not in sys.argv:
+    gmsh.fltk.run()
+
+gmsh.finalize()
diff --git a/examples/api/view_renumbering.py b/examples/api/view_renumbering.py
index 7700833ad42fe91f57bdd903caf22b83a12f5974..c1a26c6cf3a66d9788da0a4a28890f4a64c31b0c 100644
--- a/examples/api/view_renumbering.py
+++ b/examples/api/view_renumbering.py
@@ -31,6 +31,7 @@ gmsh.view.addHomogeneousModelData(
 gmsh.model.mesh.renumberNodes()
 gmsh.model.mesh.renumberElements()
 
-gmsh.fltk.run()
+if '-nopopup' not in sys.argv:
+    gmsh.fltk.run()
 
 gmsh.finalize()