@Override
  public void start(InputEvent e, Observer observer) {
    assert e != null;
    assert e instanceof MouseEvent;
    assert e.getEventType() == MouseEvent.MOUSE_PRESSED;
    assert e.getTarget() instanceof Node;
    assert observer != null;

    this.observer = observer;
    this.eventTarget = (Node) e.getTarget();

    assert eventTarget.getOnDragDetected() == null;
    assert eventTarget.getOnMouseReleased() == null;
    assert eventTarget.getOnMouseExited() == null;

    eventTarget.setOnDragDetected(
        e1 -> {
          try {
            mouseDragDetected(e1);
          } finally {
            performTermination();
          }
        });
    eventTarget.setOnMouseReleased(
        e1 -> {
          try {
            mouseReleased(e1);
          } finally {
            performTermination();
          }
        });
    eventTarget.setOnMouseExited(
        e1 -> {
          try {
            mouseExited(e1);
          } finally {
            performTermination();
          }
        });

    try {
      mousePressed((MouseEvent) e);
    } catch (RuntimeException x) {
      performTermination();
      throw x;
    }
  }
  @Override
  public void start(InputEvent e, Observer observer) {
    assert e != null;
    assert e instanceof MouseEvent;
    assert e.getEventType() == MouseEvent.MOUSE_PRESSED;
    assert observer != null;
    assert mouseDidDrag == false;

    final Node glassLayer = contentPanelController.getGlassLayer();
    assert glassLayer.getOnDragDetected() == null;
    assert glassLayer.getOnMouseDragged() == null;
    assert glassLayer.getOnMouseReleased() == null;
    assert glassLayer.getOnKeyPressed() == null;
    assert glassLayer.getOnKeyReleased() == null;

    glassLayer.setOnDragDetected(
        new EventHandler<MouseEvent>() {
          @Override
          public void handle(MouseEvent e) {
            lastMouseEvent = e;
            mouseDidDrag = true;
            mouseDragStarted();
            glassLayer.setOnMouseDragged(
                new EventHandler<MouseEvent>() {
                  @Override
                  public void handle(MouseEvent e) {
                    lastMouseEvent = e;
                    mouseDragged();
                  }
                });
          }
        });
    glassLayer.setOnMouseReleased(
        new EventHandler<MouseEvent>() {
          @Override
          public void handle(MouseEvent e) {
            lastMouseEvent = e;
            try {
              if (mouseDidDrag) {
                try {
                  mouseDragEnded();
                } finally {
                  glassLayer.setOnMouseDragged(null);
                }
              }
              mouseReleased();
            } finally {
              performTermination();
            }
          }
        });
    glassLayer.setOnKeyPressed(
        new EventHandler<KeyEvent>() {
          @Override
          public void handle(KeyEvent e) {
            handleKeyPressed(e);
          }
        });
    glassLayer.setOnKeyReleased(
        new EventHandler<KeyEvent>() {
          @Override
          public void handle(KeyEvent e) {
            handleKeyReleased(e);
          }
        });

    this.mousePressedEvent = (MouseEvent) e;
    this.lastMouseEvent = mousePressedEvent;
    this.observer = observer;

    try {
      mousePressed();
    } catch (RuntimeException x) {
      performTermination();
      throw x;
    }
  }