diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9cf2b11784299f00f84be061bd92347bb97fd01c..698385645ad3a54f3b951e2881699810696872f7 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -90,6 +90,7 @@ IF(NOT CLIENT_ONLY)
     ${CMAKE_SOURCE_DIR}/include/gepetto/gui/pick-handler.hh
     ${CMAKE_SOURCE_DIR}/include/gepetto/gui/shortcut-factory.hh
     ${CMAKE_SOURCE_DIR}/include/gepetto/gui/selection-handler.hh
+    ${CMAKE_SOURCE_DIR}/include/gepetto/gui/selection-event.hh
     ${CMAKE_SOURCE_DIR}/include/gepetto/gui/windows-manager.hh
     )
   SET (${PROJECT_NAME}_HEADERS_NO_MOC
diff --git a/include/gepetto/gui/bodytreewidget.hh b/include/gepetto/gui/bodytreewidget.hh
index d6a7445621e11924353a11809ed06f0b4445c9b2..2c3dc6f22d0df7b4998fb6ad7369418048562476 100644
--- a/include/gepetto/gui/bodytreewidget.hh
+++ b/include/gepetto/gui/bodytreewidget.hh
@@ -59,6 +59,12 @@ namespace gepetto {
         return model_;
       }
 
+      /// Handle a selection event
+      ///
+      /// Does not re-emit a selection event when the body tree selection
+      /// is updated.
+      void handleSelectionEvent (const SelectionEvent* event);
+
     public slots:
       /// \addtogroup available_in_python Python API
       /// \{
@@ -101,6 +107,9 @@ namespace gepetto {
       /// \param pos position of the item
       void customContextMenu (const QPoint& pos);
 
+      void currentChanged (const QModelIndex &current,
+                           const QModelIndex &previous);
+
     private:
       QTreeView* view_;
       QStandardItemModel* model_;
diff --git a/include/gepetto/gui/fwd.hh b/include/gepetto/gui/fwd.hh
index 6013b3abf2a8727a0a7aaf83ab265b0fabd438b7..2821edb6a7548ee6da713e55c26534bedf61ea18 100644
--- a/include/gepetto/gui/fwd.hh
+++ b/include/gepetto/gui/fwd.hh
@@ -13,6 +13,7 @@ namespace gepetto {
     class BodyTreeItem;
     class ShortcutFactory;
     class SelectionHandler;
+    class SelectionEvent;
 
     class ViewerCorbaServer;
 
diff --git a/include/gepetto/gui/mainwindow.hh b/include/gepetto/gui/mainwindow.hh
index b30b58a2b89ed3866561a8064b435c3497f59c21..4091fc7bd6b06cb63e53e20f73e1d39e1b112c55 100644
--- a/include/gepetto/gui/mainwindow.hh
+++ b/include/gepetto/gui/mainwindow.hh
@@ -62,6 +62,11 @@ namespace gepetto {
         /// Get
         WindowsManagerPtr_t osg () const;
 
+        SelectionHandler* selectionHandler()
+        {
+          return selectionHandler_;
+        }
+
         /// Get the central widget.
         OSGWidget* centralWidget() const;
 
diff --git a/include/gepetto/gui/osgwidget.hh b/include/gepetto/gui/osgwidget.hh
index 6815254f969fbdf86ae9e196a361a916438cc4a8..83e750a08d861e6d6c6bc4af7f03514259711c7d 100644
--- a/include/gepetto/gui/osgwidget.hh
+++ b/include/gepetto/gui/osgwidget.hh
@@ -58,7 +58,7 @@ namespace gepetto {
         WindowsManager::WindowID windowID () const;
 
 signals:
-      void clicked (QString name, QVector3D positionInWorldFrame, QKeyEvent* event);
+      void clicked (SelectionEvent* event);
 
         public slots:
         /// Load an urdf file in the viewer.
@@ -76,13 +76,13 @@ signals:
         void cameraManipulationMode ();
         void addFloor();
         void attachToWindow (const std::string nodeName);
+        void emitClicked (SelectionEvent* event);
 
       protected:
 
         virtual void paintEvent( QPaintEvent* paintEvent );
 
       private:
-      void emitClicked (QString name, QVector3D positionInWorldFrame, QKeyEvent* event);
         osgGA::EventQueue* getEventQueue() const;
 
         osg::ref_ptr<osgQt::GraphicsWindowQt> graphicsWindow_;
diff --git a/include/gepetto/gui/pick-handler.hh b/include/gepetto/gui/pick-handler.hh
index 5821a92d79e7070bf826257966d78164835ef6df..429f5635db0c19605a3bb741e3cb8c5ed03d2df0 100644
--- a/include/gepetto/gui/pick-handler.hh
+++ b/include/gepetto/gui/pick-handler.hh
@@ -24,14 +24,8 @@ namespace gepetto {
       virtual bool handle( const osgGA::GUIEventAdapter&  ea,
                                  osgGA::GUIActionAdapter& aa );
 
-      void select (graphics::NodePtr_t node);
-
       void getUsage (osg::ApplicationUsage &usage);
 
-    private slots:
-      void bodyTreeCurrentChanged (const QModelIndex &current,
-          const QModelIndex &previous);
-
     private:
       std::list <graphics::NodePtr_t> computeIntersection (osgGA::GUIActionAdapter& aa,
                                                            const float& x, const float& y,
@@ -42,7 +36,6 @@ namespace gepetto {
       QtOsgKeyboard mapper_;
       WindowsManagerPtr_t wsm_;
       OSGWidget* parent_;
-      graphics::NodePtr_t last_;
       bool pushed_;
       float lastX_, lastY_;
     };
diff --git a/include/gepetto/gui/qt-osg-keyboard.hh b/include/gepetto/gui/qt-osg-keyboard.hh
index 29d5b99a17d364db24bbec4a073a972b16d8f5aa..73c6c323e0e900d2fcbafca9608f6bf6ff543935 100644
--- a/include/gepetto/gui/qt-osg-keyboard.hh
+++ b/include/gepetto/gui/qt-osg-keyboard.hh
@@ -72,7 +72,7 @@ namespace gepetto {
         mKeyMap[Qt::Key_Insert        ] = osgGA::GUIEventAdapter::KEY_KP_Insert;
         //mKeyMap[Qt::Key_Delete        ] = osgGA::GUIEventAdapter::KEY_KP_Delete;
 
-	modKeyMap[osgGA::GUIEventAdapter::MODKEY_CTRL ] = Qt::Key_Control;
+	modKeyMap[osgGA::GUIEventAdapter::MODKEY_CTRL ] = Qt::ControlModifier;
       }
 
       ~QtOsgKeyboard()
@@ -81,7 +81,7 @@ namespace gepetto {
 
       int remapKey(QKeyEvent* event)
       {
-        KeyMap::iterator itr = mKeyMap.find(event->key());
+        KeyMap::iterator itr = mKeyMap.find((Qt::Key)event->key());
         if (itr == mKeyMap.end())
 	  {
             return int(*(event->text().toLatin1().data()));
@@ -104,19 +104,26 @@ namespace gepetto {
       QKeyEvent* remapModKey(int modMask)
       {
 	if (modMask == 0)
-	  return NULL;
-	for (ModKeyMap::iterator itr = modKeyMap.begin(); itr != modKeyMap.end(); ++itr) {
-	  if (itr->first == modMask)
-	    return new QKeyEvent(QEvent::KeyPress, itr->second, 0);
-	}	
+          return NULL;
+        ModKeyMap::const_iterator it = modKeyMap.find(modMask);
+        if (it != modKeyMap.end())
+          return new QKeyEvent(QEvent::KeyPress, it->second, 0);
 	return NULL;
       }
 
+      Qt::KeyboardModifiers getQtModKey(int modMask)
+      {
+        ModKeyMap::const_iterator it = modKeyMap.find(modMask);
+        if (it != modKeyMap.end())
+          return it->second;
+	return Qt::NoModifier;
+      }
+
     private:
-      typedef std::map<unsigned int, int> KeyMap;
+      typedef std::map<Qt::Key, int> KeyMap;
       KeyMap mKeyMap;
 
-      typedef std::map<int, unsigned int> ModKeyMap;
+      typedef std::map<int, Qt::KeyboardModifiers> ModKeyMap;
       ModKeyMap modKeyMap;
     };
   }
diff --git a/include/gepetto/gui/selection-event.hh b/include/gepetto/gui/selection-event.hh
new file mode 100644
index 0000000000000000000000000000000000000000..5dce391e50bb02553fb9161ff202876210479fe0
--- /dev/null
+++ b/include/gepetto/gui/selection-event.hh
@@ -0,0 +1,64 @@
+#ifndef GEPETTO_GUI_SELECTION_EVENT_HH
+#define GEPETTO_GUI_SELECTION_EVENT_HH
+
+#include <QString>
+#include <QVector3D>
+#include <QObject>
+
+#include <gepetto/viewer/node.h>
+
+namespace gepetto {
+  namespace gui {
+    class SelectionEvent : public QObject {
+      Q_OBJECT
+
+      public:
+        enum Type {
+          FromOsgWindow,
+          FromBodyTree
+        };
+
+        SelectionEvent (const Type& t, graphics::NodePtr_t node = graphics::NodePtr_t(), Qt::KeyboardModifiers modKey = Qt::NoModifier)
+          : type_ (t)
+          , node_ (node)
+          , modKey_ (modKey)
+          , hasIntersection_ (false)
+        {
+          if (node)
+            nodeName_ = QString::fromStdString(node->getID());
+        }
+
+        SelectionEvent (const Type& t, Qt::KeyboardModifiers modKey)
+          : type_ (t)
+          , modKey_ (modKey)
+          , hasIntersection_ (false)
+        {}
+
+        void setupIntersection(const osgUtil::LineSegmentIntersector::Intersection& it);
+
+        const graphics::NodePtr_t& node () const { return node_; }
+
+        void modKey (const Qt::KeyboardModifiers& m) { modKey_ = m; }
+
+      public slots:
+        Type                  type    () const { return type_; }
+        QString               nodeName() const { return nodeName_; }
+        Qt::KeyboardModifiers modKey  () const { return modKey_; }
+
+        bool hasIntersection () { return hasIntersection_; }
+        QVector3D normal(bool local) const { return (local ? localNormal_ : worldNormal_); }
+        QVector3D point (bool local) const { return (local ? localPoint_  : worldPoint_ ); }
+
+    private:
+        Type type_;
+        QString nodeName_;
+        graphics::NodePtr_t node_;
+        Qt::KeyboardModifiers modKey_;
+
+        bool hasIntersection_;
+        QVector3D localPoint_, localNormal_, worldPoint_, worldNormal_;
+    };
+  } // namespace gui
+} // namespace gepetto
+
+#endif // GEPETTO_GUI_SELECTION_EVENT_HH
diff --git a/include/gepetto/gui/selection-handler.hh b/include/gepetto/gui/selection-handler.hh
index 0f1b8d4cbfcc9ec003f0a3f78a87092837b9fb25..89f97c7a744f7ad4891ec3e41833ae2885d693f2 100644
--- a/include/gepetto/gui/selection-handler.hh
+++ b/include/gepetto/gui/selection-handler.hh
@@ -23,6 +23,8 @@ namespace gepetto {
 
       virtual void reset() { currentSelected_ = ""; }
 
+      QString currentBody () { return currentSelected_; }
+
     signals:
       void selectedBodies(QStringList selectedBodies);
 
@@ -30,11 +32,7 @@ namespace gepetto {
       /// Slot called when a body is selected.
       /// \param name body's name
       /// \param position click position
-      virtual void onSelect(QString name, QVector3D /*position*/,
-			    QKeyEvent* /*event*/)
-      {
-	Q_UNUSED(name) emit selectedBodies(QStringList());
-      }
+      virtual void onSelect(SelectionEvent* event) = 0;
 
       virtual QString getName() { return "None"; }
 
@@ -52,7 +50,7 @@ namespace gepetto {
       ~UniqueSelection();
 
     public slots:
-      virtual void onSelect(QString name, QVector3D position, QKeyEvent* event);
+      virtual void onSelect(SelectionEvent* event);
       virtual QString getName() { return "Unique"; }
     };
 
@@ -66,7 +64,7 @@ namespace gepetto {
       virtual void reset();
 
     public slots:
-      virtual void onSelect(QString name, QVector3D position, QKeyEvent* event);
+      virtual void onSelect(SelectionEvent* event);
       virtual QString getName() { return "Multi"; }
 
     protected:
@@ -82,6 +80,8 @@ namespace gepetto {
 
       void setParentOSG(OSGWidget* parent);
 
+      SelectionMode* mode ();
+
     public slots:
       /// Add a mode to the list of available mode.
       /// \param mode mode to add
diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt
index 5b1aa5be0103e1737c260a2464575cc6f015b897..f29b79734c6cff8469acd74133015da1067cf1c3 100644
--- a/src/gui/CMakeLists.txt
+++ b/src/gui/CMakeLists.txt
@@ -38,6 +38,7 @@ SET (${PROJECT_NAME}_SOURCES
   dialog/pluginmanagerdialog.cc
   shortcut-factory.cc
   selection-handler.cc
+  selection-event.cc
   )
 
 IF(GEPETTO_GUI_HAS_PYTHONQT)
diff --git a/src/gui/bodytreewidget.cc b/src/gui/bodytreewidget.cc
index 5774ce3b398620f583e4356cd5a80f168b0320d9..05ceefe73c3be542104375ccfe6dee52f3568d6b 100644
--- a/src/gui/bodytreewidget.cc
+++ b/src/gui/bodytreewidget.cc
@@ -5,6 +5,7 @@
 #include <gepetto/gui/windows-manager.hh>
 #include <gepetto/gui/osgwidget.hh>
 #include <gepetto/gui/meta.hh>
+#include <gepetto/gui/selection-event.hh>
 
 #include <QSignalMapper>
 #include <QColorDialog>
@@ -73,6 +74,9 @@ namespace gepetto {
       view_->setSelectionMode(QAbstractItemView::ExtendedSelection);
 
       connect (view_, SIGNAL (customContextMenuRequested(QPoint)), SLOT(customContextMenu(QPoint)));
+      connect (view_->selectionModel(),
+          SIGNAL (currentChanged(QModelIndex,QModelIndex)),
+          SLOT (currentChanged(QModelIndex,QModelIndex)));
 
       toolBox_->removeItem(0);
       addSlider(toolBox_, "Transparency", this, SLOT(setTransparency(int)));
@@ -115,6 +119,51 @@ namespace gepetto {
       return selectBodyByName (QString::fromStdString (bodyName));
     }
 
+    void BodyTreeWidget::handleSelectionEvent (const SelectionEvent* event)
+    {
+      disconnect (view_->selectionModel(),
+          SIGNAL (currentChanged(QModelIndex,QModelIndex)),
+          this, SLOT (currentChanged(QModelIndex,QModelIndex)));
+      if (event->node()) {
+        QList<QStandardItem*> matches;
+        matches = model_->findItems(event->nodeName(), Qt::MatchFixedString
+                                      | Qt::MatchCaseSensitive
+                                      | Qt::MatchRecursive);
+        if (matches.empty())
+          view_->clearSelection();
+        else {
+          qDebug() << event->modKey();
+          if (event->modKey() == Qt::ControlModifier)
+            view_->selectionModel()->setCurrentIndex
+                (matches.first()->index(),
+                 QItemSelectionModel::Toggle);
+          else
+            view_->selectionModel()->select(matches.first()->index(), QItemSelectionModel::ClearAndSelect);
+        }
+      } else
+        view_->clearSelection();
+      connect (view_->selectionModel(),
+          SIGNAL (currentChanged(QModelIndex,QModelIndex)),
+          SLOT (currentChanged(QModelIndex,QModelIndex)));
+    }
+
+    void BodyTreeWidget::currentChanged (const QModelIndex &current,
+        const QModelIndex &/*previous*/)
+    {
+      // TODO
+      // if (!current.isValid()) {
+      // deselect
+      // }
+      BodyTreeItem *item = dynamic_cast <BodyTreeItem*> (
+          qobject_cast <const QStandardItemModel*>
+          (view_->model())->itemFromIndex(current)
+         );
+      if (item) {
+        SelectionEvent *event = new SelectionEvent(SelectionEvent::FromBodyTree, item->node(), QApplication::keyboardModifiers());
+        MainWindow::instance()->centralWidget()->emitClicked(event);
+      }
+    }
+
     QList<BodyTreeItem*> BodyTreeWidget::selectedBodies() const
     {
       QList<BodyTreeItem*> list;
diff --git a/src/gui/mainwindow.cc b/src/gui/mainwindow.cc
index 79944ed0bf5f87d437012d4fefc3524a4f5fd2cb..3b7fd438f1b1054c4f99ed0c5def51f64f46d4bf 100644
--- a/src/gui/mainwindow.cc
+++ b/src/gui/mainwindow.cc
@@ -71,8 +71,8 @@ namespace gepetto {
       connect(ui_->actionChange_shortcut, SIGNAL(triggered()), shortcutFactory_, SLOT(open()));
 
       selectionHandler_ = new SelectionHandler(osgViewerManagers_);
-      selectionHandler_->addMode(new UniqueSelection(osgViewerManagers_));
       selectionHandler_->addMode(new MultiSelection(osgViewerManagers_));
+      selectionHandler_->addMode(new UniqueSelection(osgViewerManagers_));
 
       ui_->osgToolBar->addWidget(selectionHandler_);
     }
diff --git a/src/gui/osgwidget.cc b/src/gui/osgwidget.cc
index c24e3fd99fb6ec135e79fd755d509afa9e0763ee..c67eaf021e33f608d1f4ffd114ff3fc5d8d48413 100644
--- a/src/gui/osgwidget.cc
+++ b/src/gui/osgwidget.cc
@@ -37,6 +37,7 @@
 
 #include <gepetto/gui/windows-manager.hh>
 #include <gepetto/gui/bodytreewidget.hh>
+#include <gepetto/gui/selection-event.hh>
 
 namespace gepetto {
   namespace gui {
@@ -145,11 +146,6 @@ namespace gepetto {
       render_.wsm_ = wsm_;
       render_.refreshRate = parent->settings_->refreshRate;
       render_.start ();
-
-      parent->bodyTree()->connect(this,
-          SIGNAL (clicked(QString,QVector3D,QKeyEvent*)), SLOT (selectBodyByName(QString)));
-      parent->connect(this, SIGNAL (clicked(QString,QVector3D,QKeyEvent*)),
-		      SLOT (requestSelectJointFromBodyName(QString)));
     }
 
     OSGWidget::~OSGWidget()
@@ -184,9 +180,14 @@ namespace gepetto {
       //        wsm_->lock().unlock();
     }
 
-    void OSGWidget::emitClicked(QString name, QVector3D positionInWorldFrame, QKeyEvent* event)
+    void OSGWidget::emitClicked(SelectionEvent* event)
     {
-      emit clicked (name, positionInWorldFrame, event);
+      emit clicked (event);
+      if (event->type() != SelectionEvent::FromBodyTree) {
+        MainWindow* main = MainWindow::instance();
+        main->bodyTree()->handleSelectionEvent(event);
+        main->requestSelectJointFromBodyName(event->nodeName());
+      }
     }
 
     void OSGWidget::onHome()
diff --git a/src/gui/pick-handler.cc b/src/gui/pick-handler.cc
index 2a631bfd37f18ff006d9d294b8b405a500687754..0abc0ec5df46661b37c99576bfcd695d806723a4 100644
--- a/src/gui/pick-handler.cc
+++ b/src/gui/pick-handler.cc
@@ -12,11 +12,13 @@
 #include <iostream>
 #include <boost/regex.hpp>
 
+#include <gepetto/gui/selection-event.hh>
 #include <gepetto/gui/windows-manager.hh>
 #include <gepetto/gui/osgwidget.hh>
 #include <gepetto/gui/mainwindow.hh>
 #include <gepetto/gui/bodytreewidget.hh>
 #include <gepetto/gui/tree-item.hh>
+#include <gepetto/gui/selection-handler.hh>
 
 namespace gepetto {
   namespace gui {
@@ -24,16 +26,10 @@ namespace gepetto {
       : QObject (parent)
       , wsm_ (wsm)
       , parent_ (parent)
-      , last_ ()
       , pushed_ (false)
       , lastX_ (0)
       , lastY_ (0)
-    {
-      MainWindow* main = MainWindow::instance ();
-      connect (main->bodyTree ()->view ()->selectionModel(),
-          SIGNAL (currentChanged(QModelIndex,QModelIndex)),
-          SLOT (bodyTreeCurrentChanged(QModelIndex,QModelIndex)));
-    }
+    {}
 
     PickHandler::~PickHandler()
     {
@@ -80,14 +76,6 @@ namespace gepetto {
       return false;
     }
 
-    void PickHandler::select (graphics::NodePtr_t node)
-    {
-      if (last_ == node) return;
-      if (last_) last_->setHighlightState (0);
-      last_ = node;
-      if (last_) last_->setHighlightState (8);
-    }
-
     void PickHandler::getUsage (osg::ApplicationUsage& usage)
     {
       usage.addKeyboardMouseBinding ("Right click", "Select node");
@@ -119,7 +107,7 @@ namespace gepetto {
           camera->accept( iv );
 
           if( !intersector->containsIntersections() ) {
-            select (graphics::NodePtr_t());
+            parent_->emitClicked(new SelectionEvent(SelectionEvent::FromOsgWindow, QApplication::keyboardModifiers()));
             return nodes;
           }
 
@@ -132,30 +120,34 @@ namespace gepetto {
                   if (n) {
                       if (boost::regex_match (n->getID(), boost::regex ("^.*_[0-9]+$")))
                         continue;
-                      osg::Vec3d p = it->getWorldIntersectPoint();
-                      QVector3D pWF (p[0],p[1],p[2]);
-                      parent_->emitClicked(QString::fromStdString(n->getID ()), pWF,
-					   mapper_.remapModKey(modKeyMask));
+                      SelectionEvent *event = new SelectionEvent(SelectionEvent::FromOsgWindow,
+                                                                 n,
+                                                                 mapper_.getQtModKey(modKeyMask));
+                      event->setupIntersection(*it);
+                      parent_->emitClicked(event);
                       return nodes;
                       // nodes.push_back(n);
                       // break;
                     }
                 }
             }
-          // emit parent_->selected (nodes.front()->getID ());
         }
-      select (graphics::NodePtr_t());
+      parent_->emitClicked(new SelectionEvent(SelectionEvent::FromOsgWindow, QApplication::keyboardModifiers()));
       return nodes;
     }
 
     void PickHandler::setCameraToSelected (osgGA::GUIActionAdapter &aa,
         bool zoom)
     {
-      if (!last_) return;
+      MainWindow* main = MainWindow::instance();
+      graphics::NodePtr_t last = main->osg()->getNode(
+            main->selectionHandler()->mode()->currentBody().toStdString()
+            );
+      if (!last) return;
       osgViewer::View* viewer = dynamic_cast<osgViewer::View*>( &aa );
       if(!viewer) return;
 
-      const osg::BoundingSphere& bs = last_->asGroup()->getBound ();
+      const osg::BoundingSphere& bs = last->asGroup()->getBound ();
       osg::Vec3f eye, center, up;
       viewer->getCameraManipulator()->getInverseMatrix ()
         .getLookAt (eye, center, up);
@@ -167,23 +159,5 @@ namespace gepetto {
           osg::Matrixd::lookAt (eye, bs.center(), up)
           );
     }
-
-    void PickHandler::bodyTreeCurrentChanged (const QModelIndex &current,
-        const QModelIndex &/*previous*/)
-    {
-      if (!current.isValid()) {
-        select (graphics::NodePtr_t());
-        return;
-      }
-      BodyTreeItem *item = dynamic_cast <BodyTreeItem*> (
-          qobject_cast <const QStandardItemModel*>
-          (current.model())->itemFromIndex(current)
-         );
-      if (item) {
-        wsm_->lock ().lock();
-        select (item->node ());
-        wsm_->lock ().unlock();
-      }
-    }
   }
 }
diff --git a/src/gui/pythonwidget.cc b/src/gui/pythonwidget.cc
index dfe3a72a1744ef3e1becf9d8f21af57824d26b39..d3711d457dfe3f11eb268dc834e9b3962f8ce254 100644
--- a/src/gui/pythonwidget.cc
+++ b/src/gui/pythonwidget.cc
@@ -38,7 +38,11 @@ namespace gepetto {
             PythonQtObjectPtr sys = PythonQt::self()->importModule ("sys");
             sys.evalScript ("argv = ['gepetto-gui']");
             console_ = new PythonQtScriptingConsole(NULL, mainContext_);
-            PythonQt::self()->registerQObjectClassNames(QStringList() << "BodyTreeWidget" << "BodyTreeItem" << "WindowsManager");
+            PythonQt::self()->registerQObjectClassNames(QStringList()
+                << "BodyTreeWidget"
+                << "BodyTreeItem"
+                << "SelectionEvent"
+                << "WindowsManager");
             mainContext_.addObject("mainWindow", MainWindow::instance());
             mainContext_.addObject("windowsManager", MainWindow::instance()->osg().get());
             console_->QTextEdit::clear();
diff --git a/src/gui/selection-event.cc b/src/gui/selection-event.cc
new file mode 100644
index 0000000000000000000000000000000000000000..0a32546106f99a64d995887ba9767a237ad4b03a
--- /dev/null
+++ b/src/gui/selection-event.cc
@@ -0,0 +1,48 @@
+// Copyright (c) 2017, Joseph Mirabel
+// Authors: Joseph Mirabel (joseph.mirabel@laas.fr)
+//
+// This file is part of gepetto-viewer-corba.
+// gepetto-viewer-corba is free software: you can redistribute it
+// and/or modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation, either version
+// 3 of the License, or (at your option) any later version.
+//
+// gepetto-viewer-corba is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Lesser Public License for more details.  You should have
+// received a copy of the GNU Lesser General Public License along with
+// gepetto-viewer-corba. If not, see <http://www.gnu.org/licenses/>.
+
+#include "gepetto/gui/selection-event.hh"
+
+#include <QDebug>
+
+#include <osgUtil/LineSegmentIntersector>
+
+
+namespace gepetto {
+  namespace gui {
+    namespace {
+      void toQVector3(const osg::Vec3f& in, QVector3D& out) {
+        out.setX(in[0]);
+        out.setY(in[1]);
+        out.setZ(in[2]);
+      }
+      void toQVector3(const osg::Vec3d& in, QVector3D& out) {
+        out.setX(in[0]);
+        out.setY(in[1]);
+        out.setZ(in[2]);
+      }
+    }
+
+    void SelectionEvent::setupIntersection(const osgUtil::LineSegmentIntersector::Intersection& it)
+    {
+      hasIntersection_ = true;
+      toQVector3(it.getLocalIntersectPoint(),  localPoint_);
+      toQVector3(it.getWorldIntersectPoint(),  worldPoint_);
+      toQVector3(it.getLocalIntersectNormal(), localNormal_);
+      toQVector3(it.getWorldIntersectNormal(), worldNormal_);
+    }
+  }
+}
diff --git a/src/gui/selection-handler.cc b/src/gui/selection-handler.cc
index 7aaa8e555bbb57bae90e1367047c3a95ebec8f27..b7ec358871be2a6e6e8db7e9daa38593444feeaf 100644
--- a/src/gui/selection-handler.cc
+++ b/src/gui/selection-handler.cc
@@ -2,7 +2,9 @@
 #include <QLabel>
 #include <QVector3D>
 #include <QAction>
+#include <QDebug>
 
+#include <gepetto/gui/selection-event.hh>
 #include <gepetto/gui/windows-manager.hh>
 #include "gepetto/gui/osgwidget.hh"
 #include "gepetto/gui/selection-handler.hh"
@@ -28,6 +30,12 @@ namespace gepetto {
       changeMode(currentIndex());
     }
 
+    SelectionMode* SelectionHandler::mode ()
+    {
+      assert(index_ >= 0 && index_ < (int)modes_.size());
+      return modes_[index_];
+    }
+
     void SelectionHandler::changeMode(int index)
     {
       if (osg_ != NULL) {
@@ -36,14 +44,14 @@ namespace gepetto {
 	}
 	if (index_ != -1) {
 	  modes_[index_]->reset();
-	  disconnect(osg_, SIGNAL(clicked(QString, QVector3D, QKeyEvent*)),
-		     modes_[index_], SLOT(onSelect(QString, QVector3D, QKeyEvent*)));
+	  disconnect(osg_, SIGNAL(clicked(SelectionEvent*)),
+		     modes_[index_], SLOT(onSelect(SelectionEvent*)));
 	  disconnect(modes_[index_], SIGNAL(selectedBodies(QStringList)),
 		     this, SLOT(getBodies(QStringList)));
 	}
 	index_ = index;
-	connect(osg_, SIGNAL(clicked(QString, QVector3D, QKeyEvent*)),
-		modes_[index], SLOT(onSelect(QString, QVector3D, QKeyEvent*)));
+	connect(osg_, SIGNAL(clicked(SelectionEvent*)),
+		modes_[index], SLOT(onSelect(SelectionEvent*)));
 	connect(modes_[index], SIGNAL(selectedBodies(QStringList)),
 		SLOT(getBodies(QStringList)));
       }
@@ -69,14 +77,14 @@ namespace gepetto {
     {
     }
 
-    void UniqueSelection::onSelect(QString name, QVector3D /*position*/,
-				   QKeyEvent* /*event*/)
+    void UniqueSelection::onSelect(SelectionEvent* event)
     {
-      if (currentSelected_ == name) return;
+      if (!event) return;
+      if (currentSelected_ == event->nodeName()) return;
       if (currentSelected_ != "") wsm_->setHighlight(currentSelected_.toStdString(), 0);
-      currentSelected_ = name;
-      wsm_->setHighlight(name.toStdString(), 8);
-      emit selectedBodies(QStringList() << name);
+      currentSelected_ = event->nodeName();
+      wsm_->setHighlight(event->node()->getID(), 8);
+      emit selectedBodies(QStringList() << currentSelected_);
     }
 
     MultiSelection::MultiSelection(WindowsManagerPtr_t wsm)
@@ -94,22 +102,36 @@ namespace gepetto {
       selectedBodies_ = QStringList();
     }
 
-    void MultiSelection::onSelect(QString name, QVector3D /*position*/,
-				  QKeyEvent* event)
+    void MultiSelection::onSelect(SelectionEvent* event)
     {
-      if (currentSelected_ == name) return;
-      if (!event || event->key() != Qt::Key_Control) {
-	foreach (QString n, selectedBodies_) {
-	  wsm_->setHighlight(n.toStdString(), 0);
-	}
-	selectedBodies_.clear();
-      }
-      else if (currentSelected_ != "") {
-	wsm_->setHighlight(currentSelected_.toStdString(), 7);
+      if (!event) return;
+      int i = selectedBodies_.indexOf(event->nodeName());
+      if (event->modKey() != Qt::ControlModifier) { // CTRL not pressed
+        foreach (QString n, selectedBodies_) {
+          wsm_->setHighlight(n.toStdString(), 0);
+        }
+        selectedBodies_.clear();
+        currentSelected_ = event->nodeName();
+        if (event->node()) {
+          wsm_->setHighlight(event->node()->getID(), 8);
+          selectedBodies_ << currentSelected_;
+        }
+      } else {                                    // CTRL pressed
+        if (!currentSelected_.isEmpty())
+          wsm_->setHighlight(currentSelected_.toStdString(), 7);
+        if (i >= 0) {                             // Already selected.
+          wsm_->setHighlight(event->node()->getID(), 0);
+          currentSelected_ = "";
+          selectedBodies_.removeAt(i);
+        } else {
+          currentSelected_ = event->nodeName();
+          if (event->node()){   // Add to the list if not empty
+            wsm_->setHighlight(event->node()->getID(), 8);
+            selectedBodies_ << currentSelected_;
+          }
+        }
       }
-      currentSelected_ = name;
-      wsm_->setHighlight(name.toStdString(), 8);
-      selectedBodies_ << name;
+      qDebug() << selectedBodies_;
       emit selectedBodies(selectedBodies_);
     }
   }