changeset 1331:ab81ee8fce1f broker

- Viewport is not passed and stored as a shared_ptr instead of raw reference. - ViewportController can now be injected with an undo stack (not a ctor param anymore, as a preparation for the move of the undo stack to an interactor) - Added (temp) flag to disable emscripten events registration in the WebAssemblyViewport (because legacy client code deals with them directly) - Added emscripten_clear_timeout in ~WebGLViewportsRegistry - Removed GenericToolbox::HoldingRef whose responsibility is better served with proper callback un-registration.
author Benjamin Golinvaux <bgo@osimis.io>
date Mon, 30 Mar 2020 14:23:46 +0200
parents 8d3e669f01a2
children be614695747d
files Framework/Scene2D/Internals/FixedPointAligner.cpp Framework/Scene2D/Internals/FixedPointAligner.h Framework/Scene2D/PanSceneTracker.cpp Framework/Scene2D/PanSceneTracker.h Framework/Scene2D/RotateSceneTracker.cpp Framework/Scene2D/RotateSceneTracker.h Framework/Scene2D/ZoomSceneTracker.cpp Framework/Scene2D/ZoomSceneTracker.h Framework/Scene2DViewport/AngleMeasureTool.cpp Framework/Scene2DViewport/AngleMeasureTool.h Framework/Scene2DViewport/CreateAngleMeasureCommand.cpp Framework/Scene2DViewport/CreateAngleMeasureCommand.h Framework/Scene2DViewport/CreateAngleMeasureTracker.cpp Framework/Scene2DViewport/CreateAngleMeasureTracker.h Framework/Scene2DViewport/CreateLineMeasureCommand.cpp Framework/Scene2DViewport/CreateLineMeasureCommand.h Framework/Scene2DViewport/CreateLineMeasureTracker.cpp Framework/Scene2DViewport/CreateLineMeasureTracker.h Framework/Scene2DViewport/EditAngleMeasureCommand.cpp Framework/Scene2DViewport/EditAngleMeasureCommand.h Framework/Scene2DViewport/EditAngleMeasureTracker.cpp Framework/Scene2DViewport/EditAngleMeasureTracker.h Framework/Scene2DViewport/EditLineMeasureCommand.cpp Framework/Scene2DViewport/EditLineMeasureCommand.h Framework/Scene2DViewport/EditLineMeasureTracker.cpp Framework/Scene2DViewport/EditLineMeasureTracker.h Framework/Scene2DViewport/LayerHolder.cpp Framework/Scene2DViewport/LayerHolder.h Framework/Scene2DViewport/LineMeasureTool.cpp Framework/Scene2DViewport/LineMeasureTool.h Framework/Scene2DViewport/MeasureCommands.cpp Framework/Scene2DViewport/MeasureCommands.h Framework/Scene2DViewport/MeasureTool.cpp Framework/Scene2DViewport/MeasureTool.h Framework/Scene2DViewport/MeasureTrackers.cpp Framework/Scene2DViewport/MeasureTrackers.h Framework/Scene2DViewport/OneGesturePointerTracker.cpp Framework/Scene2DViewport/OneGesturePointerTracker.h Framework/Scene2DViewport/ViewportController.cpp Framework/Scene2DViewport/ViewportController.h Framework/Toolbox/GenericToolbox.h Framework/Viewport/SdlViewport.cpp Framework/Viewport/SdlViewport.h Framework/Viewport/WebAssemblyCairoViewport.cpp Framework/Viewport/WebAssemblyViewport.cpp Framework/Viewport/WebAssemblyViewport.h Framework/Viewport/WebGLViewport.cpp Framework/Viewport/WebGLViewport.h Framework/Viewport/WebGLViewportsRegistry.cpp Framework/Viewport/WebGLViewportsRegistry.h UnitTestsSources/GenericToolboxTests.cpp
diffstat 51 files changed, 387 insertions(+), 363 deletions(-) [+]
line wrap: on
line diff
--- a/Framework/Scene2D/Internals/FixedPointAligner.cpp	Mon Mar 30 08:47:30 2020 +0200
+++ b/Framework/Scene2D/Internals/FixedPointAligner.cpp	Mon Mar 30 14:23:46 2020 +0200
@@ -25,19 +25,19 @@
 {
   namespace Internals
   {
-    FixedPointAligner::FixedPointAligner(IViewport& viewport,
+    FixedPointAligner::FixedPointAligner(boost::shared_ptr<IViewport> viewport,
                                          const ScenePoint2D& p) 
       : viewport_(viewport)
       , canvas_(p)
     {
-      std::unique_ptr<IViewport::ILock> lock(viewport_.Lock());
+      std::unique_ptr<IViewport::ILock> lock(viewport_->Lock());
       pivot_ = canvas_.Apply(lock->GetController().GetCanvasToSceneTransform());
     }
 
     
     void FixedPointAligner::Apply()
     {
-      std::unique_ptr<IViewport::ILock> lock(viewport_.Lock());
+      std::unique_ptr<IViewport::ILock> lock(viewport_->Lock());
       ScenePoint2D p = canvas_.Apply(
         lock->GetController().GetCanvasToSceneTransform());
 
--- a/Framework/Scene2D/Internals/FixedPointAligner.h	Mon Mar 30 08:47:30 2020 +0200
+++ b/Framework/Scene2D/Internals/FixedPointAligner.h	Mon Mar 30 14:23:46 2020 +0200
@@ -35,12 +35,12 @@
     class FixedPointAligner : public boost::noncopyable
     {
     private:
-      IViewport& viewport_;
+      boost::shared_ptr<IViewport> viewport_;
       ScenePoint2D           pivot_;
       ScenePoint2D           canvas_;
 
     public:
-      FixedPointAligner(IViewport& viewport,
+      FixedPointAligner(boost::shared_ptr<IViewport> viewport,
                         const ScenePoint2D& p);
 
       void Apply();
--- a/Framework/Scene2D/PanSceneTracker.cpp	Mon Mar 30 08:47:30 2020 +0200
+++ b/Framework/Scene2D/PanSceneTracker.cpp	Mon Mar 30 14:23:46 2020 +0200
@@ -27,12 +27,12 @@
 
 namespace OrthancStone
 {
-  PanSceneTracker::PanSceneTracker(IViewport& viewport,
+  PanSceneTracker::PanSceneTracker(boost::shared_ptr<IViewport> viewport,
                                    const PointerEvent& event)
     : OneGesturePointerTracker(viewport)
   {
     
-    std::unique_ptr<IViewport::ILock> lock(viewport_.Lock());
+    std::unique_ptr<IViewport::ILock> lock(viewport_->Lock());
 
     originalSceneToCanvas_ = lock->GetController().GetSceneToCanvasTransform();
     originalCanvasToScene_ = lock->GetController().GetCanvasToSceneTransform();
@@ -45,7 +45,7 @@
   {
     ScenePoint2D p = event.GetMainPosition().Apply(originalCanvasToScene_);
 
-    std::unique_ptr<IViewport::ILock> lock(viewport_.Lock());
+    std::unique_ptr<IViewport::ILock> lock(viewport_->Lock());
 
     lock->GetController().SetSceneToCanvasTransform(
       AffineTransform2D::Combine(
@@ -57,7 +57,7 @@
 
   void PanSceneTracker::Cancel()
   {
-    std::unique_ptr<IViewport::ILock> lock(viewport_.Lock());
+    std::unique_ptr<IViewport::ILock> lock(viewport_->Lock());
     lock->GetController().SetSceneToCanvasTransform(originalSceneToCanvas_);
   }
 }
--- a/Framework/Scene2D/PanSceneTracker.h	Mon Mar 30 08:47:30 2020 +0200
+++ b/Framework/Scene2D/PanSceneTracker.h	Mon Mar 30 14:23:46 2020 +0200
@@ -28,7 +28,7 @@
   class PanSceneTracker : public OneGesturePointerTracker
   {
   public:
-    PanSceneTracker(IViewport& viewport,
+    PanSceneTracker(boost::shared_ptr<IViewport> viewport,
                     const PointerEvent& event);
 
     virtual void PointerMove(const PointerEvent& event) ORTHANC_OVERRIDE;
--- a/Framework/Scene2D/RotateSceneTracker.cpp	Mon Mar 30 08:47:30 2020 +0200
+++ b/Framework/Scene2D/RotateSceneTracker.cpp	Mon Mar 30 14:23:46 2020 +0200
@@ -23,14 +23,14 @@
 
 namespace OrthancStone
 {
-  RotateSceneTracker::RotateSceneTracker(IViewport& viewport,
+  RotateSceneTracker::RotateSceneTracker(boost::shared_ptr<IViewport> viewport,
                                          const PointerEvent& event)
     : OneGesturePointerTracker(viewport)
     , click_(event.GetMainPosition())
     , aligner_(viewport, click_)
     , isFirst_(true)
   {
-    std::unique_ptr<IViewport::ILock> lock(viewport_.Lock());
+    std::unique_ptr<IViewport::ILock> lock(viewport_->Lock());
     originalSceneToCanvas_ = lock->GetController().GetSceneToCanvasTransform();
 
   }
@@ -52,7 +52,7 @@
         isFirst_ = false;
       }
 
-      std::unique_ptr<IViewport::ILock> lock(viewport_.Lock());
+      std::unique_ptr<IViewport::ILock> lock(viewport_->Lock());
 
       lock->GetController().SetSceneToCanvasTransform(
         AffineTransform2D::Combine(
@@ -66,7 +66,7 @@
   void RotateSceneTracker::Cancel()
   {
     // See remark above
-    std::unique_ptr<IViewport::ILock> lock(viewport_.Lock());
+    std::unique_ptr<IViewport::ILock> lock(viewport_->Lock());
     lock->GetController().SetSceneToCanvasTransform(originalSceneToCanvas_);
     lock->Invalidate();
   }
--- a/Framework/Scene2D/RotateSceneTracker.h	Mon Mar 30 08:47:30 2020 +0200
+++ b/Framework/Scene2D/RotateSceneTracker.h	Mon Mar 30 14:23:46 2020 +0200
@@ -30,7 +30,7 @@
   class RotateSceneTracker : public OneGesturePointerTracker
   {
   public:
-    RotateSceneTracker(IViewport& viewport,
+    RotateSceneTracker(boost::shared_ptr<IViewport> viewport,
                        const PointerEvent& event);
 
     virtual void PointerMove(const PointerEvent& event) ORTHANC_OVERRIDE;
--- a/Framework/Scene2D/ZoomSceneTracker.cpp	Mon Mar 30 08:47:30 2020 +0200
+++ b/Framework/Scene2D/ZoomSceneTracker.cpp	Mon Mar 30 14:23:46 2020 +0200
@@ -24,7 +24,7 @@
 
 namespace OrthancStone
 {
-  ZoomSceneTracker::ZoomSceneTracker(IViewport& viewport,
+  ZoomSceneTracker::ZoomSceneTracker(boost::shared_ptr<IViewport> viewport,
                                      const PointerEvent& event,
                                      unsigned int canvasHeight)
     : OneGesturePointerTracker(viewport)
@@ -32,7 +32,7 @@
     , aligner_(viewport, event.GetMainPosition())
   {
     
-    std::unique_ptr<IViewport::ILock> lock(viewport_.Lock());
+    std::unique_ptr<IViewport::ILock> lock(viewport_->Lock());
     originalSceneToCanvas_ = lock->GetController().GetSceneToCanvasTransform();
 
     if (canvasHeight <= 3)
@@ -76,7 +76,7 @@
 
       double zoom = pow(2.0, z);
 
-      std::unique_ptr<IViewport::ILock> lock(viewport_.Lock());
+      std::unique_ptr<IViewport::ILock> lock(viewport_->Lock());
       lock->GetController().SetSceneToCanvasTransform(
         AffineTransform2D::Combine(
           AffineTransform2D::CreateScaling(zoom, zoom),
@@ -88,7 +88,7 @@
 
   void ZoomSceneTracker::Cancel()
   {
-    std::unique_ptr<IViewport::ILock> lock(viewport_.Lock());
+    std::unique_ptr<IViewport::ILock> lock(viewport_->Lock());
     lock->GetController().SetSceneToCanvasTransform(originalSceneToCanvas_);
     lock->Invalidate();
   }
--- a/Framework/Scene2D/ZoomSceneTracker.h	Mon Mar 30 08:47:30 2020 +0200
+++ b/Framework/Scene2D/ZoomSceneTracker.h	Mon Mar 30 14:23:46 2020 +0200
@@ -33,7 +33,7 @@
   class ZoomSceneTracker : public OneGesturePointerTracker
   {
   public:
-    ZoomSceneTracker(IViewport& viewport,
+    ZoomSceneTracker(boost::shared_ptr<IViewport> viewport,
                      const PointerEvent& event,
                      unsigned int canvasHeight);
 
--- a/Framework/Scene2DViewport/AngleMeasureTool.cpp	Mon Mar 30 08:47:30 2020 +0200
+++ b/Framework/Scene2DViewport/AngleMeasureTool.cpp	Mon Mar 30 14:23:46 2020 +0200
@@ -42,7 +42,7 @@
   // the params in the LayerHolder ctor specify the number of polyline and text
   // layers
   AngleMeasureTool::AngleMeasureTool(
-    IViewport& viewport)
+    boost::shared_ptr<IViewport> viewport)
     : MeasureTool(viewport)
 #if ORTHANC_STONE_ENABLE_OUTLINED_TEXT == 1
     , layerHolder_(boost::shared_ptr<LayerHolder>(new LayerHolder(viewport,1,5)))
@@ -53,7 +53,7 @@
   {
   }
 
-  boost::shared_ptr<AngleMeasureTool> AngleMeasureTool::Create(IViewport& viewport)
+  boost::shared_ptr<AngleMeasureTool> AngleMeasureTool::Create(boost::shared_ptr<IViewport> viewport)
   {
     boost::shared_ptr<AngleMeasureTool> obj(new AngleMeasureTool(viewport));
     obj->MeasureTool::PostConstructor();
@@ -141,7 +141,7 @@
 
   AngleMeasureTool::AngleHighlightArea AngleMeasureTool::AngleHitTest(ScenePoint2D p) const
   {
-    std::unique_ptr<IViewport::ILock> lock(viewport_.Lock());
+    std::unique_ptr<IViewport::ILock> lock(viewport_->Lock());
     ViewportController& controller = lock->GetController();
     Scene2D& scene = controller.GetScene();
 
@@ -201,7 +201,7 @@
 
   boost::shared_ptr<IFlexiblePointerTracker> AngleMeasureTool::CreateEditionTracker(const PointerEvent& e)
   {
-    std::unique_ptr<IViewport::ILock> lock(viewport_.Lock());
+    std::unique_ptr<IViewport::ILock> lock(viewport_->Lock());
     ViewportController& controller = lock->GetController();
     Scene2D& scene = controller.GetScene();
 
@@ -215,7 +215,7 @@
       new EditLineMeasureTracker(
         boost::shared_ptr<LineMeasureTool> measureTool;
         MessageBroker & broker,
-        IViewport&          viewport,
+        boost::shared_ptr<IViewport>          viewport,
         const PointerEvent & e);
     */
 
@@ -234,7 +234,7 @@
   {
     if (IsSceneAlive())
     {
-      std::unique_ptr<IViewport::ILock> lock(viewport_.Lock());
+      std::unique_ptr<IViewport::ILock> lock(viewport_->Lock());
       ViewportController& controller = lock->GetController();
       Scene2D& scene = controller.GetScene();
 
--- a/Framework/Scene2DViewport/AngleMeasureTool.h	Mon Mar 30 08:47:30 2020 +0200
+++ b/Framework/Scene2DViewport/AngleMeasureTool.h	Mon Mar 30 14:23:46 2020 +0200
@@ -40,7 +40,7 @@
   class AngleMeasureTool : public MeasureTool
   {
   public:
-    static boost::shared_ptr<AngleMeasureTool> Create(IViewport& viewport);
+    static boost::shared_ptr<AngleMeasureTool> Create(boost::shared_ptr<IViewport> viewport);
 
     ~AngleMeasureTool();
 
@@ -70,7 +70,7 @@
     AngleHighlightArea AngleHitTest(ScenePoint2D p) const;
 
   private:
-    AngleMeasureTool(IViewport& viewport);
+    AngleMeasureTool(boost::shared_ptr<IViewport> viewport);
 
     virtual void        RefreshScene() ORTHANC_OVERRIDE;
     void                RemoveFromScene();
--- a/Framework/Scene2DViewport/CreateAngleMeasureCommand.cpp	Mon Mar 30 08:47:30 2020 +0200
+++ b/Framework/Scene2DViewport/CreateAngleMeasureCommand.cpp	Mon Mar 30 14:23:46 2020 +0200
@@ -26,13 +26,13 @@
 namespace OrthancStone
 {
   CreateAngleMeasureCommand::CreateAngleMeasureCommand(
-    IViewport& viewport,
+    boost::shared_ptr<IViewport> viewport,
     ScenePoint2D           point)
     : CreateMeasureCommand(viewport)
     , measureTool_(AngleMeasureTool::Create(viewport))
   {
     
-    std::unique_ptr<IViewport::ILock> lock(viewport_.Lock());
+    std::unique_ptr<IViewport::ILock> lock(viewport_->Lock());
     ViewportController& controller = lock->GetController();
 
     controller.AddMeasureTool(measureTool_);
--- a/Framework/Scene2DViewport/CreateAngleMeasureCommand.h	Mon Mar 30 08:47:30 2020 +0200
+++ b/Framework/Scene2DViewport/CreateAngleMeasureCommand.h	Mon Mar 30 14:23:46 2020 +0200
@@ -28,7 +28,7 @@
   public:
     /** Ctor sets end of side 1*/
     CreateAngleMeasureCommand(
-      IViewport& viewport,
+      boost::shared_ptr<IViewport> viewport,
       ScenePoint2D           point);
 
     /** This method sets center*/
--- a/Framework/Scene2DViewport/CreateAngleMeasureTracker.cpp	Mon Mar 30 08:47:30 2020 +0200
+++ b/Framework/Scene2DViewport/CreateAngleMeasureTracker.cpp	Mon Mar 30 14:23:46 2020 +0200
@@ -26,14 +26,14 @@
 namespace OrthancStone
 {
   CreateAngleMeasureTracker::CreateAngleMeasureTracker(
-    IViewport& viewport,
+    boost::shared_ptr<IViewport> viewport,
     const PointerEvent& e)
     : CreateMeasureTracker(viewport)
     , state_(CreatingSide1)
   {
     ScenePoint2D point = e.GetMainPosition();
     {    
-      std::unique_ptr<IViewport::ILock> lock(viewport_.Lock());
+      std::unique_ptr<IViewport::ILock> lock(viewport_->Lock());
       Scene2D& scene = lock->GetController().GetScene();
       point = e.GetMainPosition().Apply(scene.GetCanvasToSceneTransform());
     }
@@ -55,7 +55,7 @@
 
     
     {
-      std::unique_ptr<IViewport::ILock> lock(viewport_.Lock());
+      std::unique_ptr<IViewport::ILock> lock(viewport_->Lock());
       ViewportController& controller = lock->GetController();
 
       ScenePoint2D scenePos = event.GetMainPosition().Apply(
--- a/Framework/Scene2DViewport/CreateAngleMeasureTracker.h	Mon Mar 30 08:47:30 2020 +0200
+++ b/Framework/Scene2DViewport/CreateAngleMeasureTracker.h	Mon Mar 30 14:23:46 2020 +0200
@@ -38,7 +38,7 @@
     must be supplied, too
     */
     CreateAngleMeasureTracker(
-      IViewport&          viewport,
+      boost::shared_ptr<IViewport>          viewport,
       const PointerEvent&             e);
 
     ~CreateAngleMeasureTracker();
--- a/Framework/Scene2DViewport/CreateLineMeasureCommand.cpp	Mon Mar 30 08:47:30 2020 +0200
+++ b/Framework/Scene2DViewport/CreateLineMeasureCommand.cpp	Mon Mar 30 14:23:46 2020 +0200
@@ -26,13 +26,13 @@
 namespace OrthancStone
 {
   CreateLineMeasureCommand::CreateLineMeasureCommand(
-    IViewport& viewport,
+    boost::shared_ptr<IViewport> viewport,
     ScenePoint2D           point)
     : CreateMeasureCommand(viewport)
     , measureTool_(LineMeasureTool::Create(viewport))
   {
     
-    std::unique_ptr<IViewport::ILock> lock(viewport_.Lock());
+    std::unique_ptr<IViewport::ILock> lock(viewport_->Lock());
     ViewportController& controller = lock->GetController();
     controller.AddMeasureTool(measureTool_);
     measureTool_->Set(point, point);
--- a/Framework/Scene2DViewport/CreateLineMeasureCommand.h	Mon Mar 30 08:47:30 2020 +0200
+++ b/Framework/Scene2DViewport/CreateLineMeasureCommand.h	Mon Mar 30 14:23:46 2020 +0200
@@ -27,7 +27,7 @@
   {
   public:
     CreateLineMeasureCommand(
-      IViewport& viewport,
+      boost::shared_ptr<IViewport> viewport,
       ScenePoint2D           point);
 
     // the starting position is set in the ctor
--- a/Framework/Scene2DViewport/CreateLineMeasureTracker.cpp	Mon Mar 30 08:47:30 2020 +0200
+++ b/Framework/Scene2DViewport/CreateLineMeasureTracker.cpp	Mon Mar 30 14:23:46 2020 +0200
@@ -26,13 +26,13 @@
 namespace OrthancStone
 {
   CreateLineMeasureTracker::CreateLineMeasureTracker(
-    IViewport&          viewport,
+    boost::shared_ptr<IViewport>          viewport,
     const PointerEvent&             e)
     : CreateMeasureTracker(viewport)
   {
     ScenePoint2D point = e.GetMainPosition();
     {
-      std::unique_ptr<IViewport::ILock> lock(viewport_.Lock());
+      std::unique_ptr<IViewport::ILock> lock(viewport_->Lock());
       ViewportController& controller = lock->GetController();
       point = e.GetMainPosition().Apply(controller.GetScene().GetCanvasToSceneTransform());
     }
@@ -53,7 +53,7 @@
         "PointerMove: active_ == false");
     }
 
-    std::unique_ptr<IViewport::ILock> lock(viewport_.Lock());
+    std::unique_ptr<IViewport::ILock> lock(viewport_->Lock());
     ViewportController& controller = lock->GetController();
 
     ScenePoint2D scenePos = event.GetMainPosition().Apply(
--- a/Framework/Scene2DViewport/CreateLineMeasureTracker.h	Mon Mar 30 08:47:30 2020 +0200
+++ b/Framework/Scene2DViewport/CreateLineMeasureTracker.h	Mon Mar 30 14:23:46 2020 +0200
@@ -38,7 +38,7 @@
     must be supplied, too
     */
     CreateLineMeasureTracker(
-      IViewport&          viewport,
+      boost::shared_ptr<IViewport>          viewport,
       const PointerEvent&             e);
 
     ~CreateLineMeasureTracker();
--- a/Framework/Scene2DViewport/EditAngleMeasureCommand.cpp	Mon Mar 30 08:47:30 2020 +0200
+++ b/Framework/Scene2DViewport/EditAngleMeasureCommand.cpp	Mon Mar 30 14:23:46 2020 +0200
@@ -24,7 +24,7 @@
 {
   EditAngleMeasureCommand::EditAngleMeasureCommand(
     boost::shared_ptr<MeasureTool>  measureTool,
-    IViewport& viewport)
+    boost::shared_ptr<IViewport> viewport)
     : EditMeasureCommand(measureTool, viewport)
     , measureTool_(measureTool)
   {
--- a/Framework/Scene2DViewport/EditAngleMeasureCommand.h	Mon Mar 30 08:47:30 2020 +0200
+++ b/Framework/Scene2DViewport/EditAngleMeasureCommand.h	Mon Mar 30 14:23:46 2020 +0200
@@ -29,7 +29,7 @@
     /** Ctor sets end of side 1*/
     EditAngleMeasureCommand(
       boost::shared_ptr<MeasureTool>  measureTool,
-      IViewport& viewport);
+      boost::shared_ptr<IViewport> viewport);
 
     /** This method sets center*/
     void SetCenter(ScenePoint2D scenePos);
--- a/Framework/Scene2DViewport/EditAngleMeasureTracker.cpp	Mon Mar 30 08:47:30 2020 +0200
+++ b/Framework/Scene2DViewport/EditAngleMeasureTracker.cpp	Mon Mar 30 14:23:46 2020 +0200
@@ -27,13 +27,13 @@
 {
   EditAngleMeasureTracker::EditAngleMeasureTracker(
     boost::shared_ptr<MeasureTool>  measureTool,
-    IViewport& viewport,
+    boost::shared_ptr<IViewport> viewport,
     const PointerEvent& e)
     : EditMeasureTracker(viewport, e)
   {
     ScenePoint2D scenePos = e.GetMainPosition();
     {
-      std::unique_ptr<IViewport::ILock> lock(viewport_.Lock());
+      std::unique_ptr<IViewport::ILock> lock(viewport_->Lock());
       ViewportController& controller = lock->GetController();
       scenePos = e.GetMainPosition().Apply(controller.GetScene().GetCanvasToSceneTransform());
     }
@@ -48,7 +48,7 @@
 
   void EditAngleMeasureTracker::PointerMove(const PointerEvent& e)
   {
-    std::unique_ptr<IViewport::ILock> lock(viewport_.Lock());
+    std::unique_ptr<IViewport::ILock> lock(viewport_->Lock());
     ViewportController& controller = lock->GetController();
     Scene2D& scene = controller.GetScene();
 
--- a/Framework/Scene2DViewport/EditAngleMeasureTracker.h	Mon Mar 30 08:47:30 2020 +0200
+++ b/Framework/Scene2DViewport/EditAngleMeasureTracker.h	Mon Mar 30 14:23:46 2020 +0200
@@ -38,7 +38,7 @@
     */
     EditAngleMeasureTracker(
       boost::shared_ptr<MeasureTool>  measureTool,
-      IViewport& viewport,
+      boost::shared_ptr<IViewport> viewport,
       const PointerEvent& e);
 
     ~EditAngleMeasureTracker();
--- a/Framework/Scene2DViewport/EditLineMeasureCommand.cpp	Mon Mar 30 08:47:30 2020 +0200
+++ b/Framework/Scene2DViewport/EditLineMeasureCommand.cpp	Mon Mar 30 14:23:46 2020 +0200
@@ -24,7 +24,7 @@
 {
   EditLineMeasureCommand::EditLineMeasureCommand(
     boost::shared_ptr<MeasureTool>  measureTool,
-    IViewport& viewport)
+    boost::shared_ptr<IViewport> viewport)
     : EditMeasureCommand(measureTool, viewport)
     , measureTool_(measureTool)
   {
--- a/Framework/Scene2DViewport/EditLineMeasureCommand.h	Mon Mar 30 08:47:30 2020 +0200
+++ b/Framework/Scene2DViewport/EditLineMeasureCommand.h	Mon Mar 30 14:23:46 2020 +0200
@@ -28,7 +28,7 @@
   public:
     EditLineMeasureCommand(
       boost::shared_ptr<MeasureTool>  measureTool,
-      IViewport& viewport);
+      boost::shared_ptr<IViewport> viewport);
 
     void SetStart(ScenePoint2D scenePos);
     void SetEnd(ScenePoint2D scenePos);
--- a/Framework/Scene2DViewport/EditLineMeasureTracker.cpp	Mon Mar 30 08:47:30 2020 +0200
+++ b/Framework/Scene2DViewport/EditLineMeasureTracker.cpp	Mon Mar 30 14:23:46 2020 +0200
@@ -28,13 +28,13 @@
 {
   EditLineMeasureTracker::EditLineMeasureTracker(
     boost::shared_ptr<MeasureTool>  measureTool,
-    IViewport& viewport,
+    boost::shared_ptr<IViewport> viewport,
     const PointerEvent& e)
     : EditMeasureTracker(viewport, e)
   {
     ScenePoint2D scenePos = e.GetMainPosition();
     {
-      std::unique_ptr<IViewport::ILock> lock(viewport_.Lock());
+      std::unique_ptr<IViewport::ILock> lock(viewport_->Lock());
       Scene2D& scene = lock->GetController().GetScene();
       scenePos = e.GetMainPosition().Apply(scene.GetCanvasToSceneTransform());
     }
@@ -49,7 +49,7 @@
 
   void EditLineMeasureTracker::PointerMove(const PointerEvent& e)
   {
-    std::unique_ptr<IViewport::ILock> lock(viewport_.Lock());
+    std::unique_ptr<IViewport::ILock> lock(viewport_->Lock());
     ViewportController& controller = lock->GetController();
     Scene2D& scene = controller.GetScene();
 
--- a/Framework/Scene2DViewport/EditLineMeasureTracker.h	Mon Mar 30 08:47:30 2020 +0200
+++ b/Framework/Scene2DViewport/EditLineMeasureTracker.h	Mon Mar 30 14:23:46 2020 +0200
@@ -38,7 +38,7 @@
     */
     EditLineMeasureTracker(
       boost::shared_ptr<MeasureTool>  measureTool,
-      IViewport& viewport,
+      boost::shared_ptr<IViewport> viewport,
       const PointerEvent&                 e);
 
     ~EditLineMeasureTracker();
--- a/Framework/Scene2DViewport/LayerHolder.cpp	Mon Mar 30 08:47:30 2020 +0200
+++ b/Framework/Scene2DViewport/LayerHolder.cpp	Mon Mar 30 14:23:46 2020 +0200
@@ -28,7 +28,7 @@
 namespace OrthancStone
 {
   LayerHolder::LayerHolder(
-    IViewport& viewport,
+    boost::shared_ptr<IViewport> viewport,
     int        polylineLayerCount,
     int        textLayerCount,
     int        infoTextCount)
@@ -43,7 +43,7 @@
 
   void LayerHolder::CreateLayers()
   {
-    std::unique_ptr<IViewport::ILock> lock(viewport_.Lock());
+    std::unique_ptr<IViewport::ILock> lock(viewport_->Lock());
     ViewportController& controller = lock->GetController();
     Scene2D& scene = controller.GetScene();
 
@@ -84,7 +84,7 @@
   
   void LayerHolder::DeleteLayers()
   {
-    std::unique_ptr<IViewport::ILock> lock(viewport_.Lock());
+    std::unique_ptr<IViewport::ILock> lock(viewport_->Lock());
     Scene2D& scene = lock->GetController().GetScene();
 
     for (int i = 0; i < textLayerCount_ + polylineLayerCount_; ++i)
@@ -98,7 +98,7 @@
   
   PolylineSceneLayer* LayerHolder::GetPolylineLayer(int index /*= 0*/)
   {
-    std::unique_ptr<IViewport::ILock> lock(viewport_.Lock());
+    std::unique_ptr<IViewport::ILock> lock(viewport_->Lock());
     Scene2D& scene = lock->GetController().GetScene();
 
     using namespace Orthanc;
@@ -115,7 +115,7 @@
 
   TextSceneLayer* LayerHolder::GetTextLayer(int index /*= 0*/)
   {
-    std::unique_ptr<IViewport::ILock> lock(viewport_.Lock());
+    std::unique_ptr<IViewport::ILock> lock(viewport_->Lock());
     Scene2D& scene = lock->GetController().GetScene();
 
     using namespace Orthanc;
--- a/Framework/Scene2DViewport/LayerHolder.h	Mon Mar 30 08:47:30 2020 +0200
+++ b/Framework/Scene2DViewport/LayerHolder.h	Mon Mar 30 14:23:46 2020 +0200
@@ -43,7 +43,7 @@
     performed at this time
     */
     LayerHolder(
-      IViewport& viewport,
+      boost::shared_ptr<IViewport> viewport,
       int polylineLayerCount, int textLayerCount, int infoTextCount = 0);
 
     /**
@@ -101,7 +101,7 @@
     int textLayerCount_;
     int polylineLayerCount_;
     int infoTextCount_;
-    IViewport& viewport_;
+    boost::shared_ptr<IViewport> viewport_;
     int baseLayerIndex_;
   };
 }
--- a/Framework/Scene2DViewport/LineMeasureTool.cpp	Mon Mar 30 08:47:30 2020 +0200
+++ b/Framework/Scene2DViewport/LineMeasureTool.cpp	Mon Mar 30 14:23:46 2020 +0200
@@ -32,7 +32,7 @@
 {
 
   LineMeasureTool::LineMeasureTool(
-    IViewport& viewport)
+    boost::shared_ptr<IViewport> viewport)
     : MeasureTool(viewport)
 #if ORTHANC_STONE_ENABLE_OUTLINED_TEXT == 1
     , layerHolder_(boost::shared_ptr<LayerHolder>(new LayerHolder(viewport,1,5)))
@@ -44,7 +44,7 @@
 
   }
 
-  boost::shared_ptr<LineMeasureTool> LineMeasureTool::Create(IViewport& viewport)
+  boost::shared_ptr<LineMeasureTool> LineMeasureTool::Create(boost::shared_ptr<IViewport> viewport)
   {
     boost::shared_ptr<LineMeasureTool> obj(new LineMeasureTool(viewport));
     obj->MeasureTool::PostConstructor();
@@ -116,7 +116,7 @@
 
   LineMeasureTool::LineHighlightArea LineMeasureTool::LineHitTest(ScenePoint2D p)
   {
-    std::unique_ptr<IViewport::ILock> lock(viewport_.Lock());
+    std::unique_ptr<IViewport::ILock> lock(viewport_->Lock());
     ViewportController& controller = lock->GetController();
     Scene2D& scene = controller.GetScene();
 
@@ -152,7 +152,7 @@
 
   boost::shared_ptr<IFlexiblePointerTracker> LineMeasureTool::CreateEditionTracker(const PointerEvent& e)
   {
-    std::unique_ptr<IViewport::ILock> lock(viewport_.Lock());
+    std::unique_ptr<IViewport::ILock> lock(viewport_->Lock());
     ViewportController& controller = lock->GetController();
     Scene2D& scene = controller.GetScene();
 
@@ -195,7 +195,7 @@
       if (IsEnabled())
       {
         
-        std::unique_ptr<IViewport::ILock> lock(viewport_.Lock());
+        std::unique_ptr<IViewport::ILock> lock(viewport_->Lock());
         ViewportController& controller = lock->GetController();
         Scene2D& scene = controller.GetScene();
 
--- a/Framework/Scene2DViewport/LineMeasureTool.h	Mon Mar 30 08:47:30 2020 +0200
+++ b/Framework/Scene2DViewport/LineMeasureTool.h	Mon Mar 30 14:23:46 2020 +0200
@@ -38,7 +38,7 @@
   class LineMeasureTool : public MeasureTool
   {
   public:
-    static boost::shared_ptr<LineMeasureTool> Create(IViewport& viewport);
+    static boost::shared_ptr<LineMeasureTool> Create(boost::shared_ptr<IViewport> viewport);
 
     ~LineMeasureTool();
 
@@ -67,7 +67,7 @@
     LineHighlightArea LineHitTest(ScenePoint2D p);
 
   private:
-    LineMeasureTool(IViewport& viewport);
+    LineMeasureTool(boost::shared_ptr<IViewport> viewport);
 
     virtual void        RefreshScene() ORTHANC_OVERRIDE;
     void                RemoveFromScene();
--- a/Framework/Scene2DViewport/MeasureCommands.cpp	Mon Mar 30 08:47:30 2020 +0200
+++ b/Framework/Scene2DViewport/MeasureCommands.cpp	Mon Mar 30 14:23:46 2020 +0200
@@ -29,7 +29,7 @@
 {
   void CreateMeasureCommand::Undo()
   {
-    std::unique_ptr<OrthancStone::IViewport::ILock> lock(viewport_.Lock());
+    std::unique_ptr<OrthancStone::IViewport::ILock> lock(viewport_->Lock());
     // simply disable the measure tool upon undo
     GetMeasureTool()->Disable();
     lock->GetController().RemoveMeasureTool(GetMeasureTool());
@@ -37,12 +37,12 @@
 
   void CreateMeasureCommand::Redo()
   {
-    std::unique_ptr<OrthancStone::IViewport::ILock> lock(viewport_.Lock());
+    std::unique_ptr<OrthancStone::IViewport::ILock> lock(viewport_->Lock());
     GetMeasureTool()->Enable();
     lock->GetController().AddMeasureTool(GetMeasureTool());
   }
 
-  CreateMeasureCommand::CreateMeasureCommand(IViewport& viewport)
+  CreateMeasureCommand::CreateMeasureCommand(boost::shared_ptr<IViewport> viewport)
     : MeasureCommand(viewport)
   {
 
@@ -56,7 +56,7 @@
 
   void DeleteMeasureCommand::Redo()
   {
-    std::unique_ptr<OrthancStone::IViewport::ILock> lock(viewport_.Lock());
+    std::unique_ptr<OrthancStone::IViewport::ILock> lock(viewport_->Lock());
     // simply disable the measure tool upon undo
     GetMeasureTool()->Disable();
     lock->GetController().RemoveMeasureTool(GetMeasureTool());
@@ -64,7 +64,7 @@
 
   void DeleteMeasureCommand::Undo()
   {
-    std::unique_ptr<OrthancStone::IViewport::ILock> lock(viewport_.Lock());
+    std::unique_ptr<OrthancStone::IViewport::ILock> lock(viewport_->Lock());
     GetMeasureTool()->Enable();
     lock->GetController().AddMeasureTool(GetMeasureTool());
   }
@@ -75,18 +75,18 @@
     // we thus leave it as is
   }
 
-  DeleteMeasureCommand::DeleteMeasureCommand(boost::shared_ptr<MeasureTool> measureTool, IViewport& viewport)
+  DeleteMeasureCommand::DeleteMeasureCommand(boost::shared_ptr<MeasureTool> measureTool, boost::shared_ptr<IViewport> viewport)
     : MeasureCommand(viewport)
     , mementoOriginal_(measureTool->GetMemento())
     , measureTool_(measureTool)
     , mementoModified_(measureTool->GetMemento())
   {
-    std::unique_ptr<OrthancStone::IViewport::ILock> lock(viewport_.Lock());
+    std::unique_ptr<OrthancStone::IViewport::ILock> lock(viewport_->Lock());
     GetMeasureTool()->Disable();
     lock->GetController().RemoveMeasureTool(GetMeasureTool());
   }
 
-  EditMeasureCommand::EditMeasureCommand(boost::shared_ptr<MeasureTool> measureTool, IViewport& viewport)
+  EditMeasureCommand::EditMeasureCommand(boost::shared_ptr<MeasureTool> measureTool, boost::shared_ptr<IViewport> viewport)
     : MeasureCommand(viewport)
     , mementoOriginal_(measureTool->GetMemento())
     , mementoModified_(measureTool->GetMemento())
--- a/Framework/Scene2DViewport/MeasureCommands.h	Mon Mar 30 08:47:30 2020 +0200
+++ b/Framework/Scene2DViewport/MeasureCommands.h	Mon Mar 30 14:23:46 2020 +0200
@@ -35,7 +35,7 @@
   class MeasureCommand : public boost::noncopyable
   {
   public:
-    MeasureCommand(IViewport& viewport) : viewport_(viewport)
+    MeasureCommand(boost::shared_ptr<IViewport> viewport) : viewport_(viewport)
     {}
     virtual void Undo() = 0;
     virtual void Redo() = 0;
@@ -43,13 +43,13 @@
     virtual ~MeasureCommand() {};
 
   protected:
-    IViewport& viewport_;
+    boost::shared_ptr<IViewport> viewport_;
   };
 
   class CreateMeasureCommand : public MeasureCommand
   {
   public:
-    CreateMeasureCommand(IViewport& viewport);
+    CreateMeasureCommand(boost::shared_ptr<IViewport> viewport);
     virtual ~CreateMeasureCommand();
     virtual void Undo() ORTHANC_OVERRIDE;
     virtual void Redo() ORTHANC_OVERRIDE;
@@ -61,7 +61,7 @@
   class EditMeasureCommand : public MeasureCommand
   {
   public:
-    EditMeasureCommand(boost::shared_ptr<MeasureTool> measureTool, IViewport& viewport);
+    EditMeasureCommand(boost::shared_ptr<MeasureTool> measureTool, boost::shared_ptr<IViewport> viewport);
     virtual ~EditMeasureCommand();
     virtual void Undo() ORTHANC_OVERRIDE;
     virtual void Redo() ORTHANC_OVERRIDE;
@@ -82,7 +82,7 @@
   class DeleteMeasureCommand : public MeasureCommand
   {
   public:
-    DeleteMeasureCommand(boost::shared_ptr<MeasureTool> measureTool, IViewport& viewport);
+    DeleteMeasureCommand(boost::shared_ptr<MeasureTool> measureTool, boost::shared_ptr<IViewport> viewport);
     virtual ~DeleteMeasureCommand();
     virtual void Undo() ORTHANC_OVERRIDE;
     virtual void Redo() ORTHANC_OVERRIDE;
--- a/Framework/Scene2DViewport/MeasureTool.cpp	Mon Mar 30 08:47:30 2020 +0200
+++ b/Framework/Scene2DViewport/MeasureTool.cpp	Mon Mar 30 14:23:46 2020 +0200
@@ -48,7 +48,7 @@
   }
 
   MeasureTool::MeasureTool(
-    IViewport& viewport)
+    boost::shared_ptr<IViewport> viewport)
     : viewport_(viewport)
     , enabled_(true)
   {
@@ -57,7 +57,7 @@
 
   void MeasureTool::PostConstructor()
   {
-    std::unique_ptr<IViewport::ILock> lock(viewport_.Lock());
+    std::unique_ptr<IViewport::ILock> lock(viewport_->Lock());
     ViewportController& controller = lock->GetController();
 
     Register<ViewportController::SceneTransformChanged>(
--- a/Framework/Scene2DViewport/MeasureTool.h	Mon Mar 30 08:47:30 2020 +0200
+++ b/Framework/Scene2DViewport/MeasureTool.h	Mon Mar 30 14:23:46 2020 +0200
@@ -113,7 +113,7 @@
     virtual std::string GetDescription() = 0;
 
   protected:
-    MeasureTool(IViewport& viewport);
+    MeasureTool(boost::shared_ptr<IViewport> viewport);
 
     void PostConstructor();
 
@@ -141,7 +141,7 @@
     Protected to allow sub-classes to use this weak pointer in factory methods
     (pass them to created objects)
     */
-    IViewport& viewport_;
+    boost::shared_ptr<IViewport> viewport_;
 
 
   private:
--- a/Framework/Scene2DViewport/MeasureTrackers.cpp	Mon Mar 30 08:47:30 2020 +0200
+++ b/Framework/Scene2DViewport/MeasureTrackers.cpp	Mon Mar 30 14:23:46 2020 +0200
@@ -24,7 +24,7 @@
 namespace OrthancStone
 {
 
-  CreateMeasureTracker::CreateMeasureTracker(IViewport& viewport)
+  CreateMeasureTracker::CreateMeasureTracker(boost::shared_ptr<IViewport> viewport)
     : viewport_(viewport)
     , alive_(true)
     , commitResult_(true)
@@ -48,7 +48,7 @@
     // to the undo stack
     // otherwise, we simply undo it
 
-    std::unique_ptr<IViewport::ILock> lock(viewport_.Lock());
+    std::unique_ptr<IViewport::ILock> lock(viewport_->Lock());
     ViewportController& controller = lock->GetController();
 
     if (commitResult_)
@@ -59,12 +59,12 @@
     lock->Invalidate();
   }
 
-  EditMeasureTracker::EditMeasureTracker(IViewport& viewport, const PointerEvent& e)
+  EditMeasureTracker::EditMeasureTracker(boost::shared_ptr<IViewport> viewport, const PointerEvent& e)
     : viewport_(viewport)
     , alive_(true)
     , commitResult_(true)
   {
-    std::unique_ptr<IViewport::ILock> lock(viewport_.Lock());
+    std::unique_ptr<IViewport::ILock> lock(viewport_->Lock());
     ViewportController& controller = lock->GetController();
 
     originalClickPosition_ = e.GetMainPosition().Apply(
@@ -88,7 +88,7 @@
     // to the undo stack
     // otherwise, we simply undo it
 
-    std::unique_ptr<IViewport::ILock> lock(viewport_.Lock());
+    std::unique_ptr<IViewport::ILock> lock(viewport_->Lock());
     ViewportController& controller = lock->GetController();
 
     if (commitResult_)
--- a/Framework/Scene2DViewport/MeasureTrackers.h	Mon Mar 30 08:47:30 2020 +0200
+++ b/Framework/Scene2DViewport/MeasureTrackers.h	Mon Mar 30 14:23:46 2020 +0200
@@ -40,13 +40,13 @@
     virtual void Cancel() ORTHANC_OVERRIDE;
     virtual bool IsAlive() const ORTHANC_OVERRIDE;
   protected:
-    CreateMeasureTracker(IViewport& viewport);
+    CreateMeasureTracker(boost::shared_ptr<IViewport> viewport);
 
     ~CreateMeasureTracker();
   
   protected:
     boost::shared_ptr<CreateMeasureCommand>         command_;
-    IViewport&          viewport_;
+    boost::shared_ptr<IViewport>          viewport_;
     bool                            alive_;
 
   private:
@@ -59,13 +59,13 @@
     virtual void Cancel() ORTHANC_OVERRIDE;
     virtual bool IsAlive() const ORTHANC_OVERRIDE;
   protected:
-    EditMeasureTracker(IViewport& viewport, const PointerEvent& e);
+    EditMeasureTracker(boost::shared_ptr<IViewport> viewport, const PointerEvent& e);
 
     ~EditMeasureTracker();
 
   protected:
     boost::shared_ptr<EditMeasureCommand> command_;
-    IViewport&   viewport_;
+    boost::shared_ptr<IViewport>   viewport_;
     bool                                  alive_;
     
     ScenePoint2D                          GetOriginalClickPosition() const
--- a/Framework/Scene2DViewport/OneGesturePointerTracker.cpp	Mon Mar 30 08:47:30 2020 +0200
+++ b/Framework/Scene2DViewport/OneGesturePointerTracker.cpp	Mon Mar 30 14:23:46 2020 +0200
@@ -28,7 +28,7 @@
 namespace OrthancStone
 {
   OneGesturePointerTracker::OneGesturePointerTracker(
-    IViewport& viewport)
+    boost::shared_ptr<IViewport> viewport)
     : viewport_(viewport)
     , alive_(true)
     , currentTouchCount_(1)
--- a/Framework/Scene2DViewport/OneGesturePointerTracker.h	Mon Mar 30 08:47:30 2020 +0200
+++ b/Framework/Scene2DViewport/OneGesturePointerTracker.h	Mon Mar 30 14:23:46 2020 +0200
@@ -44,13 +44,13 @@
   class OneGesturePointerTracker : public IFlexiblePointerTracker
   {
   public:
-    OneGesturePointerTracker(IViewport& viewport);
+    OneGesturePointerTracker(boost::shared_ptr<IViewport> viewport);
     virtual void PointerUp(const PointerEvent& event) ORTHANC_OVERRIDE;
     virtual void PointerDown(const PointerEvent& event) ORTHANC_OVERRIDE;
     virtual bool IsAlive() const ORTHANC_OVERRIDE;
   
   protected:
-    IViewport& viewport_;
+    boost::shared_ptr<IViewport> viewport_;
 
   private:
     bool                   alive_;
--- a/Framework/Scene2DViewport/ViewportController.cpp	Mon Mar 30 08:47:30 2020 +0200
+++ b/Framework/Scene2DViewport/ViewportController.cpp	Mon Mar 30 14:23:46 2020 +0200
@@ -33,7 +33,7 @@
 namespace OrthancStone
 {
   IFlexiblePointerTracker* DefaultViewportInteractor::CreateTracker(
-    IViewport&          viewport,
+    boost::shared_ptr<IViewport>          viewport,
     const PointerEvent& event,
     unsigned int        viewportWidth,
     unsigned int        viewportHeight)
@@ -63,39 +63,21 @@
     }
   }
 
-
-  ViewportController::ViewportController(IViewport& viewport) 
+  ViewportController::ViewportController(boost::shared_ptr<IViewport> viewport)
     : viewport_(viewport)
-    , undoStackW_(boost::shared_ptr<UndoStack>(new UndoStack()))
-
     , scene_(new Scene2D)
     , canvasToSceneFactor_(1)
   {
+    // undoStack_ is not default-initialized, which basically means empty.
+    // The controller must be able to cope with this.
   }
 
-  ViewportController::ViewportController(IViewport& viewport,
-                                         const Scene2D& scene)
-    : viewport_(viewport)
-    , undoStackW_(boost::shared_ptr<UndoStack>(new UndoStack()))
-    , scene_(scene.Clone())
-    , canvasToSceneFactor_(1)
-  {
-  }
-
-  ViewportController::ViewportController(IViewport& viewport, 
-                                         boost::weak_ptr<UndoStack> undoStackW)
-    : viewport_(viewport)
-    , undoStackW_(undoStackW)
-    , scene_(new Scene2D)
-    , canvasToSceneFactor_(1)
-  {
-  }
- 
   ViewportController::~ViewportController()
   {
   }
 
-  void ViewportController::PushCommand(boost::shared_ptr<MeasureCommand> command)
+  void ViewportController::PushCommand(
+    boost::shared_ptr<MeasureCommand> command)
   {
     boost::shared_ptr<UndoStack> undoStack = undoStackW_.lock();
     if (undoStack.get() != NULL)
@@ -104,7 +86,7 @@
     }
     else
     {
-      LOG(ERROR) << "Internal error: no undo stack in the viewport controller!";
+      LOG(ERROR) << "Internal error: no undo stack!";
     }
   }
 
@@ -117,7 +99,7 @@
     }
     else
     {
-      LOG(ERROR) << "Internal error: no undo stack in the viewport controller!";
+      LOG(ERROR) << "Internal error: no undo stack!";
     }
   }
 
@@ -130,7 +112,7 @@
     }
     else
     {
-      LOG(ERROR) << "Internal error: no undo stack in the viewport controller!";
+      LOG(ERROR) << "Internal error: no undo stack!";
     }
   }
 
@@ -143,7 +125,7 @@
     }
     else
     {
-      LOG(ERROR) << "Internal error: no undo stack in the viewport controller!";
+      LOG(ERROR) << "Internal error: no undo stack!";
       return false;
     }
   }
@@ -157,13 +139,13 @@
     }
     else
     {
-      LOG(ERROR) << "Internal error: no undo stack in the viewport controller!";
+      LOG(ERROR) << "Internal error: no undo stack!";
       return false;
     }
   }
   
-  std::vector<boost::shared_ptr<MeasureTool> > ViewportController::HitTestMeasureTools(
-    ScenePoint2D p)
+  std::vector<boost::shared_ptr<MeasureTool> > 
+    ViewportController::HitTestMeasureTools(ScenePoint2D p)
   {
     std::vector<boost::shared_ptr<MeasureTool> > ret;
     
@@ -174,8 +156,7 @@
     }
     return ret;
   }
-
-
+  
   void ViewportController::ResetMeasuringToolsHighlight()
   {
     for (size_t i = 0; i < measureTools_.size(); ++i)
@@ -184,17 +165,20 @@
     }
   }
 
-  OrthancStone::AffineTransform2D ViewportController::GetCanvasToSceneTransform() const
+  OrthancStone::AffineTransform2D 
+    ViewportController::GetCanvasToSceneTransform() const
   {
     return scene_->GetCanvasToSceneTransform();
   }
 
-  OrthancStone::AffineTransform2D ViewportController::GetSceneToCanvasTransform() const
+  OrthancStone::AffineTransform2D 
+    ViewportController::GetSceneToCanvasTransform() const
   {
     return scene_->GetSceneToCanvasTransform();
   }
 
-  void ViewportController::SetSceneToCanvasTransform(const AffineTransform2D& transform)
+  void ViewportController::SetSceneToCanvasTransform(
+    const AffineTransform2D& transform)
   {
     scene_->SetSceneToCanvasTransform(transform);
 
@@ -210,17 +194,23 @@
     BroadcastMessage(SceneTransformChanged(*this));
   }
 
-  void ViewportController::AddMeasureTool(boost::shared_ptr<MeasureTool> measureTool)
+  void ViewportController::AddMeasureTool(
+    boost::shared_ptr<MeasureTool> measureTool)
   {
-    ORTHANC_ASSERT(std::find(measureTools_.begin(), measureTools_.end(), measureTool)
-      == measureTools_.end(), "Duplicate measure tool");
+    ORTHANC_ASSERT(std::find(measureTools_.begin(), 
+                             measureTools_.end(), 
+                             measureTool) == measureTools_.end(), 
+                  "Duplicate measure tool");
     measureTools_.push_back(measureTool);
   }
 
-  void ViewportController::RemoveMeasureTool(boost::shared_ptr<MeasureTool> measureTool)
+  void ViewportController::RemoveMeasureTool(
+    boost::shared_ptr<MeasureTool> measureTool)
   {
-    ORTHANC_ASSERT(std::find(measureTools_.begin(), measureTools_.end(), measureTool)
-      != measureTools_.end(), "Measure tool not found");
+    ORTHANC_ASSERT(std::find(measureTools_.begin(), 
+                             measureTools_.end(), 
+                             measureTool) != measureTools_.end(), 
+                  "Measure tool not found");
     measureTools_.erase(
       std::remove(measureTools_.begin(), measureTools_.end(), measureTool), 
       measureTools_.end());
@@ -252,14 +242,16 @@
   }
 
 
-  void ViewportController::HandleMousePress(OrthancStone::IViewportInteractor& interactor,
-                                            const PointerEvent& event,
-                                            unsigned int viewportWidth,
-                                            unsigned int viewportHeight)
+  void ViewportController::HandleMousePress(
+    OrthancStone::IViewportInteractor&  interactor,
+    const PointerEvent&                 event,
+    unsigned int                        viewportWidth,
+    unsigned int                        viewportHeight)
   {
     if (activeTracker_)
     {
-      // We are dealing with a multi-stage tracker (that is made of several interactions)
+      // We are dealing with a multi-stage tracker (that is made of several 
+      // interactions)
       activeTracker_->PointerDown(event);
 
       if (!activeTracker_->IsAlive())
@@ -280,7 +272,10 @@
       }
 
       // No measure tool, create new tracker from the interactor
-      activeTracker_.reset(interactor.CreateTracker(viewport_, event, viewportWidth, viewportHeight));
+      activeTracker_.reset(interactor.CreateTracker(viewport_, 
+                                                    event, 
+                                                    viewportWidth, 
+                                                    viewportHeight));
     }
   }
 
--- a/Framework/Scene2DViewport/ViewportController.h	Mon Mar 30 08:47:30 2020 +0200
+++ b/Framework/Scene2DViewport/ViewportController.h	Mon Mar 30 14:23:46 2020 +0200
@@ -41,7 +41,7 @@
     {
     }
 
-    virtual IFlexiblePointerTracker* CreateTracker(IViewport& viewport,
+    virtual IFlexiblePointerTracker* CreateTracker(boost::shared_ptr<IViewport> viewport,
                                                    const PointerEvent& event,
                                                    unsigned int viewportWidth,
                                                    unsigned int viewportHeight) = 0;
@@ -52,7 +52,7 @@
   class DefaultViewportInteractor : public IViewportInteractor
   {
   public:
-    virtual IFlexiblePointerTracker* CreateTracker(IViewport& viewport,
+    virtual IFlexiblePointerTracker* CreateTracker(boost::shared_ptr<IViewport> viewport,
                                                    const PointerEvent& event,
                                                    unsigned int viewportWidth,
                                                    unsigned int viewportHeight) ORTHANC_OVERRIDE;
@@ -109,13 +109,10 @@
   {
   public:
     ORTHANC_STONE_DEFINE_ORIGIN_MESSAGE(__FILE__, __LINE__, \
-                                        SceneTransformChanged, ViewportController);
-
-    ViewportController(IViewport& viewport);
+                                        SceneTransformChanged, \
+                                        ViewportController);
 
-    ViewportController(IViewport& viewport, const Scene2D& scene /* will be cloned */);
-
-    ViewportController(IViewport& viewport, boost::weak_ptr<UndoStack> undoStackW);
+    ViewportController(boost::shared_ptr<IViewport> viewport);
 
     ~ViewportController();
 
@@ -124,7 +121,8 @@
     (in scene coords). A tracker can then be requested from the chosen 
     measure tool, if needed
     */
-    std::vector<boost::shared_ptr<MeasureTool> > HitTestMeasureTools(ScenePoint2D p);
+    std::vector<boost::shared_ptr<MeasureTool> > HitTestMeasureTools(
+      ScenePoint2D p);
 
     /**
     This function will traverse the measuring tools and will clear their 
@@ -223,6 +221,34 @@
       return *scene_;
     }
 
+    /**
+    This method is used in a move pattern: when the ownership of the scene 
+    managed by this viewport controller must be transferred to another 
+    controller.
+    */
+    Scene2D* ReleaseScene()
+    {
+      return scene_.release();
+    }
+
+    /**
+    This method is used when one wishes to replace the scene that is currently
+    managed by the controller. The previous scene is deleted and the controller
+    now has ownership of the new one.
+    */
+    void AcquireScene(Scene2D* scene)
+    {
+      scene_.reset(scene);
+    }
+
+    /**
+    Sets the undo stack that is used by PushCommand, Undo...
+    */
+    void SetUndoStack(boost::weak_ptr<UndoStack> undoStackW)
+    {
+      undoStackW_ = undoStackW;
+    }
+    
     bool HasActiveTracker() const
     {
       return activeTracker_.get() != NULL;
@@ -231,7 +257,7 @@
   private:
     double GetCanvasToSceneFactor() const;
 
-    IViewport&                                    viewport_;
+    boost::shared_ptr<IViewport>                  viewport_;
     boost::weak_ptr<UndoStack>                    undoStackW_;  // Global stack, possibly shared by all viewports
     std::vector<boost::shared_ptr<MeasureTool> >  measureTools_;
     boost::shared_ptr<IFlexiblePointerTracker>    activeTracker_;  // TODO - Couldn't this be a "std::unique_ptr"?
--- a/Framework/Toolbox/GenericToolbox.h	Mon Mar 30 08:47:30 2020 +0200
+++ b/Framework/Toolbox/GenericToolbox.h	Mon Mar 30 14:23:46 2020 +0200
@@ -21,6 +21,7 @@
 #pragma once
 
 #include <Core/Compatibility.h>
+#include <Core/OrthancException.h>
 
 #include <boost/shared_ptr.hpp>
 
@@ -303,35 +304,5 @@
     {
       return GetRgbaValuesFromString(red, green, blue, alpha, text.c_str());
     }
-
-
-    template<typename Wrappee> 
-    struct HoldingRef
-    {
-      HoldingRef(Wrappee* object)
-      {
-        // a crash here means that the object is not stored in a shared_ptr
-        // using shared_ptr is mandatory for this
-        object_ = object->shared_from_this();
-      }
-      boost::shared_ptr<Wrappee> object_;
-
-      static void* Wrap(Wrappee* object)
-      {
-        std::unique_ptr<HoldingRef<Wrappee > > up(new HoldingRef<Wrappee>(object));
-        void* userData = reinterpret_cast<void*>(up.release());
-        return userData;
-      }
-
-      static boost::shared_ptr<Wrappee> Unwrap(void* userData)
-      {
-        // the stored shared_ptr will be deleted because of wrapping
-        // the data in a RAII
-        std::unique_ptr<HoldingRef<Wrappee > >
-          up(reinterpret_cast<HoldingRef<Wrappee>*>(userData));
-        boost::shared_ptr<Wrappee> object = up->object_;
-        return object;
-      }
-    };
   }
 }
--- a/Framework/Viewport/SdlViewport.cpp	Mon Mar 30 08:47:30 2020 +0200
+++ b/Framework/Viewport/SdlViewport.cpp	Mon Mar 30 14:23:46 2020 +0200
@@ -22,6 +22,8 @@
 
 #include <Core/OrthancException.h>
 
+#include <boost/make_shared.hpp>
+
 namespace OrthancStone
 {
   ICompositor& SdlViewport::SdlLock::GetCompositor()
@@ -48,8 +50,7 @@
     compositor_.reset(compositor);
   }
 
-  SdlViewport::SdlViewport() :
-    controller_(new ViewportController(*this))
+  SdlViewport::SdlViewport()
   {
     refreshEvent_ = SDL_RegisterEvents(1);
 
@@ -58,18 +59,12 @@
       throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
     }
   }
-
-  SdlViewport::SdlViewport(boost::weak_ptr<UndoStack> undoStackW) :
-    controller_(new ViewportController(*this,undoStackW))
+  
+  void SdlViewport::PostConstructor()
   {
-    refreshEvent_ = SDL_RegisterEvents(1);
-
-    if (refreshEvent_ == static_cast<uint32_t>(-1))
-    {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
-    }
+    controller_ = boost::make_shared<ViewportController>(shared_from_this());
   }
-
+    
   void SdlViewport::SendRefreshEvent()
   {
     SDL_Event event;
@@ -88,15 +83,15 @@
     AcquireCompositor(new OpenGLCompositor(context_));  // (*)
   }
 
-  SdlOpenGLViewport::SdlOpenGLViewport(const char* title,
-                                       boost::weak_ptr<UndoStack> undoStackW,
-                                       unsigned int width,
-                                       unsigned int height,
-                                       bool allowDpiScaling) :
-    SdlViewport(undoStackW),
-    context_(title, width, height, allowDpiScaling)
+  boost::shared_ptr<SdlOpenGLViewport> SdlOpenGLViewport::Create(const char* title,
+                                                                 unsigned int width,
+                                                                 unsigned int height,
+                                                                 bool allowDpiScaling)
   {
-    AcquireCompositor(new OpenGLCompositor(context_));  // (*)
+    boost::shared_ptr<SdlOpenGLViewport> that =
+      boost::shared_ptr<SdlOpenGLViewport>(new SdlOpenGLViewport(title, width, height, allowDpiScaling));
+    that->SdlViewport::PostConstructor();
+    return that;
   }
 
   SdlOpenGLViewport::~SdlOpenGLViewport()
--- a/Framework/Viewport/SdlViewport.h	Mon Mar 30 08:47:30 2020 +0200
+++ b/Framework/Viewport/SdlViewport.h	Mon Mar 30 14:23:46 2020 +0200
@@ -53,13 +53,14 @@
 {
   class UndoStack;
 
-  class SdlViewport : public IViewport
+  class SdlViewport : public IViewport,
+                      public boost::enable_shared_from_this<SdlViewport>
   {
   private:
     boost::recursive_mutex                 mutex_;
     uint32_t                               refreshEvent_;
     boost::shared_ptr<ViewportController>  controller_;
-    std::unique_ptr<ICompositor>             compositor_;
+    std::unique_ptr<ICompositor>           compositor_;
 
     void SendRefreshEvent();
 
@@ -102,9 +103,11 @@
 
     void AcquireCompositor(ICompositor* compositor /* takes ownership */);
 
-  public:
+  protected:
     SdlViewport();
-    SdlViewport(boost::weak_ptr<UndoStack> undoStackW);
+    void PostConstructor();
+
+  public:
 
     bool IsRefreshEvent(const SDL_Event& event) const
     {
@@ -131,17 +134,17 @@
   private:
     SdlOpenGLContext  context_;
 
-  public:
+  private:
     SdlOpenGLViewport(const char* title,
                       unsigned int width,
                       unsigned int height,
                       bool allowDpiScaling = true);
+  public:
+    static boost::shared_ptr<SdlOpenGLViewport> Create(const char* title,
+                                                       unsigned int width,
+                                                       unsigned int height,
+                                                       bool allowDpiScaling = true);
 
-    SdlOpenGLViewport(const char* title,
-                      boost::weak_ptr<UndoStack> undoStackW,
-                      unsigned int width,
-                      unsigned int height,
-                      bool allowDpiScaling = true);
 
     virtual ~SdlOpenGLViewport();
 
@@ -162,11 +165,17 @@
 
     void CreateSdlSurfaceFromCompositor(CairoCompositor& compositor);
 
-  public:
+  private:
     SdlCairoViewport(const char* title,
                      unsigned int width,
                      unsigned int height,
                      bool allowDpiScaling = true);
+  public:
+    static boost::shared_ptr<SdlCairoViewport> Create(const char* title,
+                     unsigned int width,
+                     unsigned int height,
+                     bool allowDpiScaling = true);
+
 
     virtual ~SdlCairoViewport();
 
--- a/Framework/Viewport/WebAssemblyCairoViewport.cpp	Mon Mar 30 08:47:30 2020 +0200
+++ b/Framework/Viewport/WebAssemblyCairoViewport.cpp	Mon Mar 30 14:23:46 2020 +0200
@@ -122,12 +122,16 @@
   }
 
 
-  WebAssemblyCairoViewport::WebAssemblyCairoViewport(const std::string& canvasId) :
-    WebAssemblyViewport(canvasId, NULL, boost::weak_ptr<UndoStack>())
+  WebAssemblyCairoViewport::WebAssemblyCairoViewport(
+    const std::string& canvasId) :
+    WebAssemblyViewport(canvasId)
   {
     unsigned int width, height;
     GetCanvasSize(width, height);
-    emscripten_set_canvas_element_size(GetFullCanvasId().c_str(), width, height);
+    emscripten_set_canvas_element_size(GetFullCanvasId().c_str(), 
+                                       width, 
+                                       height);
+
     AcquireCompositor(new CairoCompositor(width, height));
   }
 }
--- a/Framework/Viewport/WebAssemblyViewport.cpp	Mon Mar 30 08:47:30 2020 +0200
+++ b/Framework/Viewport/WebAssemblyViewport.cpp	Mon Mar 30 14:23:46 2020 +0200
@@ -106,7 +106,8 @@
 
   EM_BOOL WebAssemblyViewport::OnRequestAnimationFrame(double time, void *userData)
   {
-    boost::shared_ptr<WebAssemblyViewport> that = GenericToolbox::HoldingRef<WebAssemblyViewport>::Unwrap(userData);
+    LOG(TRACE) << __func__;
+    WebAssemblyViewport* that = reinterpret_cast<WebAssemblyViewport*>(userData);
 
     if (that->compositor_.get() != NULL &&
         that->controller_ /* should always be true */)
@@ -114,12 +115,14 @@
       that->Paint(*that->compositor_, *that->controller_);
     }
       
+    LOG(TRACE) << "Exiting: " << __func__;
     return true;
   }
 
   EM_BOOL WebAssemblyViewport::OnResize(int eventType, const EmscriptenUiEvent *uiEvent, void *userData)
   {
-    boost::shared_ptr<WebAssemblyViewport> that = GenericToolbox::HoldingRef<WebAssemblyViewport>::Unwrap(userData);
+    LOG(TRACE) << __func__;
+    WebAssemblyViewport* that = reinterpret_cast<WebAssemblyViewport*>(userData);
 
     if (that->compositor_.get() != NULL)
     {
@@ -127,15 +130,16 @@
       that->Invalidate();
     }
       
+    LOG(TRACE) << "Exiting: " << __func__;
     return true;
   }
 
 
   EM_BOOL WebAssemblyViewport::OnMouseDown(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData)
   {
-    boost::shared_ptr<WebAssemblyViewport> that = GenericToolbox::HoldingRef<WebAssemblyViewport>::Unwrap(userData);
+    WebAssemblyViewport* that = reinterpret_cast<WebAssemblyViewport*>(userData);
 
-    LOG(INFO) << "mouse down: " << that->GetFullCanvasId();      
+    LOG(TRACE) << "mouse down: " << that->GetFullCanvasId();      
 
     if (that->compositor_.get() != NULL &&
         that->interactor_.get() != NULL)
@@ -149,31 +153,41 @@
       that->Invalidate();
     }
 
+    LOG(TRACE) << "Exiting: " << __func__;
     return true;
   }
 
     
   EM_BOOL WebAssemblyViewport::OnMouseMove(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData)
   {
-    boost::shared_ptr<WebAssemblyViewport> that = GenericToolbox::HoldingRef<WebAssemblyViewport>::Unwrap(userData);
+    LOG(TRACE) << "WebAssemblyViewport::OnMouseMove CP1. userData = " << userData;
+    
+    WebAssemblyViewport* that = reinterpret_cast<WebAssemblyViewport*>(userData);
+    LOG(TRACE) << "WebAssemblyViewport::OnMouseMove CP2";
 
     if (that->compositor_.get() != NULL &&
         that->controller_->HasActiveTracker())
     {
+      LOG(TRACE) << "WebAssemblyViewport::OnMouseMove CP3";
       PointerEvent pointer;
       ConvertMouseEvent(pointer, *mouseEvent, *that->compositor_);
+      LOG(TRACE) << "WebAssemblyViewport::OnMouseMove CP4";
       if (that->controller_->HandleMouseMove(pointer))
       {
+        LOG(TRACE) << "WebAssemblyViewport::OnMouseMove CP5";
         that->Invalidate();
+        LOG(TRACE) << "WebAssemblyViewport::OnMouseMove CP6";
       }
     }
 
+    LOG(TRACE) << "Exiting: " << __func__;
     return true;
   }
     
   EM_BOOL WebAssemblyViewport::OnMouseUp(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData)
   {
-    boost::shared_ptr<WebAssemblyViewport> that = GenericToolbox::HoldingRef<WebAssemblyViewport>::Unwrap(userData);
+    LOG(TRACE) << __func__;
+    WebAssemblyViewport* that = reinterpret_cast<WebAssemblyViewport*>(userData);
 
     if (that->compositor_.get() != NULL)
     {
@@ -183,12 +197,13 @@
       that->Invalidate();
     }
 
+    LOG(TRACE) << "Exiting: " << __func__;
     return true;
   }
 
   void WebAssemblyViewport::Invalidate()
   {
-    emscripten_request_animation_frame(OnRequestAnimationFrame, GenericToolbox::HoldingRef<WebAssemblyViewport>::Wrap(this));
+    emscripten_request_animation_frame(OnRequestAnimationFrame, reinterpret_cast<void*>(this));
   }
 
   void WebAssemblyViewport::AcquireCompositor(ICompositor* compositor /* takes ownership */)
@@ -204,66 +219,96 @@
   }
 
   WebAssemblyViewport::WebAssemblyViewport(
-    const std::string& canvasId,
-    const Scene2D* scene,
-    boost::weak_ptr<UndoStack> undoStackW) :
+    const std::string& canvasId, bool enableEmscriptenEvents) :
     shortCanvasId_(canvasId),
     fullCanvasId_(canvasId),
-    interactor_(new DefaultViewportInteractor)
+    interactor_(new DefaultViewportInteractor),
+    enableEmscriptenEvents_(enableEmscriptenEvents)
+  {
+  }
+
+  void WebAssemblyViewport::PostConstructor()
   {
-    if(undoStackW.lock() != NULL)
-    {
-      controller_ = boost::make_shared<ViewportController>(*this,undoStackW);
-    }
-    else if (scene == NULL)
-    {
-      controller_ = boost::make_shared<ViewportController>(*this);
-    }
-    else
-    {
-      controller_ = boost::make_shared<ViewportController>(*this,*scene);
-    }
+    boost::shared_ptr<IViewport> viewport = shared_from_this();
+    controller_.reset(new ViewportController(viewport));
 
-    LOG(INFO) << "Initializing Stone viewport on HTML canvas: " << canvasId;
+    LOG(INFO) << "Initializing Stone viewport on HTML canvas: " 
+      << shortCanvasId_;
 
-    if (canvasId.empty() ||
-        canvasId[0] == '#')
+    if (shortCanvasId_.empty() ||
+        shortCanvasId_[0] == '#')
     {
       throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange,
-                                      "The canvas identifier must not start with '#'");
+        "The canvas identifier must not start with '#'");
     }
 
     // Disable right-click on the canvas (i.e. context menu)
     EM_ASM({
-        document.getElementById(UTF8ToString($0)).oncontextmenu = function(event) {
+        document.getElementById(UTF8ToString($0)).oncontextmenu = 
+        function(event)
+        {
           event.preventDefault();
         }
       },
-      canvasId.c_str()   // $0
+      shortCanvasId_.c_str()   // $0
       );
 
-    LOG(TRACE) << "2020-03-16-16h23 About to call emscripten_set_XXXX_callback on \"" 
-      << fullCanvasId_.c_str() << "\" from WebAssemblyViewport::WebAssemblyViewport";
+    if (enableEmscriptenEvents_)
+    {
+      // It is not possible to monitor the resizing of individual
+      // canvas, so we track the full window of the browser
+      emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW,
+                                     reinterpret_cast<void*>(this),
+                                     false,
+                                     OnResize);
 
-#if 1
-    // It is not possible to monitor the resizing of individual
-    // canvas, so we track the full window of the browser
-    emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, this, false, OnResize);
+      emscripten_set_mousedown_callback(fullCanvasId_.c_str(),
+                                        reinterpret_cast<void*>(this),
+                                        false,
+                                        OnMouseDown);
 
-    emscripten_set_mousedown_callback(fullCanvasId_.c_str(), this, false, OnMouseDown);
-    emscripten_set_mousemove_callback(fullCanvasId_.c_str(), this, false, OnMouseMove);
-    emscripten_set_mouseup_callback(fullCanvasId_.c_str(), this, false, OnMouseUp);
-#endif
-    LOG(TRACE) << "2020-03-16-16h23 DONE calling emscripten_set_XXXX_callback on \"" 
-      << fullCanvasId_.c_str() << "\" from WebAssemblyViewport::WebAssemblyViewport";
+      emscripten_set_mousemove_callback(fullCanvasId_.c_str(),
+                                        reinterpret_cast<void*>(this),
+                                        false,
+                                        OnMouseMove);
+
+      emscripten_set_mouseup_callback(fullCanvasId_.c_str(),
+                                      reinterpret_cast<void*>(this),
+                                      false,
+                                      OnMouseUp);
+    }
   }
 
+  WebAssemblyViewport::~WebAssemblyViewport()
+  {
+    if (enableEmscriptenEvents_)
+    {
+      emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW,
+                                     reinterpret_cast<void*>(this),
+                                     false,
+                                     NULL);
+
+      emscripten_set_mousedown_callback(fullCanvasId_.c_str(),
+                                        reinterpret_cast<void*>(this),
+                                        false,
+                                        OnMouseDown);
+
+      emscripten_set_mousemove_callback(fullCanvasId_.c_str(),
+                                        reinterpret_cast<void*>(this),
+                                        false,
+                                        OnMouseMove);
+
+      emscripten_set_mouseup_callback(fullCanvasId_.c_str(),
+                                      reinterpret_cast<void*>(this),
+                                      false,
+                                      OnMouseUp);
+    }
+  }
   
   IViewport::ILock* WebAssemblyViewport::Lock()
   {
     return new WasmLock(*this);
   }
-
   
   void WebAssemblyViewport::AcquireInteractor(IViewportInteractor* interactor)
   {
--- a/Framework/Viewport/WebAssemblyViewport.h	Mon Mar 30 08:47:30 2020 +0200
+++ b/Framework/Viewport/WebAssemblyViewport.h	Mon Mar 30 14:23:46 2020 +0200
@@ -43,11 +43,12 @@
   private:
     class WasmLock;
     
-    std::string                            shortCanvasId_;
-    std::string                            fullCanvasId_;
-    std::unique_ptr<ICompositor>             compositor_;
-    boost::shared_ptr<ViewportController>  controller_;
-    std::unique_ptr<IViewportInteractor>     interactor_;
+    std::string                           shortCanvasId_;
+    std::string                           fullCanvasId_;
+    std::unique_ptr<ICompositor>          compositor_;
+    std::unique_ptr<ViewportController>   controller_;
+    std::unique_ptr<IViewportInteractor>  interactor_;
+    bool                                  enableEmscriptenEvents_;
 
     static EM_BOOL OnRequestAnimationFrame(double time, void *userData);
     
@@ -79,12 +80,20 @@
 
     virtual void UpdateSize(ICompositor& compositor) = 0;
 
+    /**
+    The second argument is temporary and should be deleted once the migration 
+    to interactors is finished.
+    */
+    WebAssemblyViewport(const std::string& canvasId, 
+                        bool enableEmscriptenEvents = true);
+
+    void PostConstructor();
+
   public:
-    WebAssemblyViewport(const std::string& canvasId,
-                        const Scene2D* scene,
-                        boost::weak_ptr<UndoStack> undoStackW);
+    virtual ILock* Lock() ORTHANC_OVERRIDE;
 
-    virtual ILock* Lock() ORTHANC_OVERRIDE;
+    ~WebAssemblyViewport();
+
 
     /**
     This method takes ownership
--- a/Framework/Viewport/WebGLViewport.cpp	Mon Mar 30 08:47:30 2020 +0200
+++ b/Framework/Viewport/WebGLViewport.cpp	Mon Mar 30 14:23:46 2020 +0200
@@ -79,32 +79,26 @@
     }
   }
 
-  WebGLViewport::WebGLViewport(const std::string& canvasId,
-                               boost::weak_ptr<UndoStack> undoStackW) :
-    WebAssemblyViewport(canvasId, NULL, undoStackW),
-    context_(GetFullCanvasId())
-  {
-    AcquireCompositor(new OpenGLCompositor(context_));
-  }
-
   WebGLViewport::WebGLViewport(const std::string& canvasId) :
-    WebAssemblyViewport(canvasId, NULL, boost::weak_ptr<UndoStack>()),
+    WebAssemblyViewport(canvasId),
     context_(GetFullCanvasId())
   {
     AcquireCompositor(new OpenGLCompositor(context_));
   }
 
-  WebGLViewport::WebGLViewport(const std::string& canvasId,
-                               const Scene2D& scene) :
-    WebAssemblyViewport(canvasId, &scene, boost::weak_ptr<UndoStack>()),
-    context_(GetFullCanvasId())
+  boost::shared_ptr<WebGLViewport> WebGLViewport::Create(
+    const std::string& canvasId)
   {
-    AcquireCompositor(new OpenGLCompositor(context_));
+    boost::shared_ptr<WebGLViewport> that = 
+      boost::shared_ptr<WebGLViewport>(new WebGLViewport(canvasId));
+    that->WebAssemblyViewport::PostConstructor();
+    return that;
   }
 
   WebGLViewport::~WebGLViewport()
   {
-    // Make sure to delete the compositor before its parent "context_" gets deleted
+    // Make sure to delete the compositor before its parent "context_" gets
+    // deleted
     ClearCompositor();
   }
 }
--- a/Framework/Viewport/WebGLViewport.h	Mon Mar 30 08:47:30 2020 +0200
+++ b/Framework/Viewport/WebGLViewport.h	Mon Mar 30 14:23:46 2020 +0200
@@ -31,6 +31,8 @@
   private:
     OpenGL::WebAssemblyOpenGLContext  context_;
 
+    WebGLViewport(const std::string& canvasId);
+
   protected:
     virtual void Paint(ICompositor& compositor,
                        ViewportController& controller) ORTHANC_OVERRIDE;
@@ -38,13 +40,7 @@
     virtual void UpdateSize(ICompositor& compositor) ORTHANC_OVERRIDE;
 
   public:
-    WebGLViewport(const std::string& canvasId);
-
-    WebGLViewport(const std::string& canvasId,
-                  boost::weak_ptr<UndoStack> undoStackW);
-
-    WebGLViewport(const std::string& canvasId,
-                  const Scene2D& scene);
+    static boost::shared_ptr<WebGLViewport> Create(const std::string& canvasId);
 
     virtual ~WebGLViewport();
 
--- a/Framework/Viewport/WebGLViewportsRegistry.cpp	Mon Mar 30 08:47:30 2020 +0200
+++ b/Framework/Viewport/WebGLViewportsRegistry.cpp	Mon Mar 30 14:23:46 2020 +0200
@@ -21,6 +21,8 @@
 
 #include "WebGLViewportsRegistry.h"
 
+#include "../Toolbox/GenericToolbox.h"
+
 #include <Core/OrthancException.h>
 
 #include <boost/make_shared.hpp>
@@ -29,13 +31,17 @@
 {
   void WebGLViewportsRegistry::LaunchTimer()
   {
-    emscripten_set_timeout(OnTimeoutCallback, timeoutMS_, this);
+    timeOutID_ = emscripten_set_timeout(
+      OnTimeoutCallback, 
+      timeoutMS_, 
+      reinterpret_cast<void*>(this));
   }
-
   
   void WebGLViewportsRegistry::OnTimeout()
   {
-    for (Viewports::iterator it = viewports_.begin(); it != viewports_.end(); ++it)
+    for (Viewports::iterator it = viewports_.begin();
+         it != viewports_.end(); 
+         ++it)
     {
       if (it->second == NULL ||
           it->second->IsContextLost())
@@ -61,10 +67,20 @@
         // replaced by a fresh one with the same ID: Recreate the
         // WebGL context on the new canvas
         boost::shared_ptr<WebGLViewport> viewport;
-          
+
+        // we need to steal the properties from the old viewport
+        // and set them to the new viewport
         {
           std::unique_ptr<IViewport::ILock> lock(it->second->Lock());
-          viewport = boost::make_shared<WebGLViewport>(it->first, lock->GetController().GetScene());
+
+          // TODO: remove ViewportController
+          Scene2D* scene = lock->GetController().ReleaseScene();
+          viewport = WebGLViewport::Create(it->first);
+
+          {
+            std::unique_ptr<IViewport::ILock> newLock(viewport->Lock());
+            newLock->GetController().AcquireScene(scene);
+          }
         }
 
         // Replace the old WebGL viewport by the new one
@@ -81,16 +97,17 @@
     LaunchTimer();
   }
 
-    
   void WebGLViewportsRegistry::OnTimeoutCallback(void *userData)
   {
-    WebGLViewportsRegistry& that = *reinterpret_cast<WebGLViewportsRegistry*>(userData);
-    that.OnTimeout();
+    // This object dies with the process or tab. 
+    WebGLViewportsRegistry* that = 
+      reinterpret_cast<WebGLViewportsRegistry*>(userData);
+    that->OnTimeout();
   }
 
-    
   WebGLViewportsRegistry::WebGLViewportsRegistry(double timeoutMS) :
-    timeoutMS_(timeoutMS)
+    timeoutMS_(timeoutMS),
+    timeOutID_(0)
   {
     if (timeoutMS <= 0)
     {
@@ -100,8 +117,14 @@
     LaunchTimer();
   }
 
+  WebGLViewportsRegistry::~WebGLViewportsRegistry()
+  {
+    emscripten_clear_timeout(timeOutID_);
+    Clear();
+  }
 
-  boost::shared_ptr<WebGLViewport> WebGLViewportsRegistry::Add(const std::string& canvasId)
+  boost::shared_ptr<WebGLViewport> WebGLViewportsRegistry::Add(
+    const std::string& canvasId)
   {
     if (viewports_.find(canvasId) != viewports_.end())
     {
@@ -110,13 +133,13 @@
     }
     else
     {
-      boost::shared_ptr<WebGLViewport> viewport(new WebGLViewport(canvasId));
+      boost::shared_ptr<WebGLViewport> viewport = 
+        WebGLViewport::Create(canvasId);
       viewports_[canvasId] = viewport;
       return viewport;
     }
   }
-
-    
+      
   void WebGLViewportsRegistry::Remove(const std::string& canvasId)
   {
     Viewports::iterator found = viewports_.find(canvasId);
@@ -130,14 +153,12 @@
       viewports_.erase(found);
     }
   }
-
-    
+  
   void WebGLViewportsRegistry::Clear()
   {
     viewports_.clear();
   }
 
-
   WebGLViewportsRegistry::Accessor::Accessor(WebGLViewportsRegistry& that,
                                              const std::string& canvasId) :
     that_(that)
@@ -150,7 +171,6 @@
     }
   }
 
-
   IViewport::ILock& WebGLViewportsRegistry::Accessor::GetViewport() const
   {
     if (IsValid())
--- a/Framework/Viewport/WebGLViewportsRegistry.h	Mon Mar 30 08:47:30 2020 +0200
+++ b/Framework/Viewport/WebGLViewportsRegistry.h	Mon Mar 30 14:23:46 2020 +0200
@@ -23,6 +23,8 @@
 
 #include "WebGLViewport.h"
 
+#include <boost/enable_shared_from_this.hpp>
+
 namespace OrthancStone
 {
   /**
@@ -33,13 +35,15 @@
    * lost). If some WebGL context is lost, it is automatically
    * reinitialized by created a fresh HTML5 canvas.
    **/  
-  class WebGLViewportsRegistry : public boost::noncopyable
+  class WebGLViewportsRegistry : public boost::noncopyable,
+    public boost::enable_shared_from_this<WebGLViewportsRegistry>
   {
   private:
     typedef std::map<std::string, boost::shared_ptr<WebGLViewport> >  Viewports;
 
     double     timeoutMS_;
     Viewports  viewports_;
+    long       timeOutID_;
 
     void LaunchTimer();
 
@@ -50,10 +54,7 @@
   public:
     WebGLViewportsRegistry(double timeoutMS /* in milliseconds */);
     
-    ~WebGLViewportsRegistry()
-    {
-      Clear();
-    }
+    ~WebGLViewportsRegistry();
 
     boost::shared_ptr<WebGLViewport> Add(const std::string& canvasId);
 
@@ -64,7 +65,7 @@
     class Accessor : public boost::noncopyable
     {
     private:
-      WebGLViewportsRegistry&          that_;
+      WebGLViewportsRegistry&            that_;
       std::unique_ptr<IViewport::ILock>  lock_;
 
     public:
--- a/UnitTestsSources/GenericToolboxTests.cpp	Mon Mar 30 08:47:30 2020 +0200
+++ b/UnitTestsSources/GenericToolboxTests.cpp	Mon Mar 30 14:23:46 2020 +0200
@@ -4245,50 +4245,9 @@
   EXPECT_EQ(0, blue);
 }
 
-static int Test_GenericToolbox_HoldingRef_ctor_trace = 100;
-static int Test_GenericToolbox_HoldingRef_dtor_trace = 1000;
-
-class Test_GenericToolbox_HoldingRef : public boost::enable_shared_from_this<Test_GenericToolbox_HoldingRef>
-{
-public:
-  Test_GenericToolbox_HoldingRef() : answer_(42) { Test_GenericToolbox_HoldingRef_ctor_trace++; }
-  unsigned int answer_;
-
-  ~Test_GenericToolbox_HoldingRef()
-  {
-    Test_GenericToolbox_HoldingRef_dtor_trace--;
-  }
-};
-
-TEST(GenericToolbox, HoldingRef)
-{
-  using namespace OrthancStone::GenericToolbox;
-
-  void* userData = NULL;
-
-  {
-    boost::shared_ptr<Test_GenericToolbox_HoldingRef> test(new Test_GenericToolbox_HoldingRef() );
-    Test_GenericToolbox_HoldingRef* This = test.get();
-    userData = HoldingRef<Test_GenericToolbox_HoldingRef>::Wrap(This);
-    EXPECT_EQ(42u,This->answer_);
-    This->answer_ = 0xdeadbeef;
-    EXPECT_EQ(0xdeadbeef,This->answer_);
-  }
-  
-  EXPECT_EQ(101,Test_GenericToolbox_HoldingRef_ctor_trace);
-  EXPECT_EQ(1000,Test_GenericToolbox_HoldingRef_dtor_trace);
-  
-  {
-    boost::shared_ptr<Test_GenericToolbox_HoldingRef> test2 = HoldingRef<Test_GenericToolbox_HoldingRef>::Unwrap(userData);
-    EXPECT_EQ(0xdeadbeef,test2->answer_);
-  }
-  
-  EXPECT_EQ(999,Test_GenericToolbox_HoldingRef_dtor_trace); // make sure wrapper was deleted once
-}
-
-
-
-
-
-
-
+
+
+
+
+
+