diff --git a/clutter/x11/clutter-device-manager-xi2.c b/clutter/x11/clutter-device-manager-xi2.c
index 13c814871..bb438d56b 100644
--- a/clutter/x11/clutter-device-manager-xi2.c
+++ b/clutter/x11/clutter-device-manager-xi2.c
@@ -235,9 +235,6 @@ add_device (ClutterDeviceManagerXI2 *manager_xi2,
 
   /* we don't go through the DeviceManager::add_device() vfunc because
    * that emits the signal, and we only do it conditionally
-   *
-   * FIXME: add a boolean "emit_signal" argument to the add_device()
-   * wrapper in ClutterDeviceManager, and emit the signal only if true
    */
   g_hash_table_replace (manager_xi2->devices_by_id,
                         GINT_TO_POINTER (info->deviceid),
@@ -329,6 +326,8 @@ translate_hierarchy_event (ClutterBackendX11       *backend_x11,
           XIDeviceInfo *info;
           int n_devices;
 
+          CLUTTER_NOTE (EVENT, "Hierarchy event: device enabled");
+
           info = XIQueryDevice (backend_x11->xdpy,
                                 ev->info[i].deviceid,
                                 &n_devices);
@@ -336,6 +335,8 @@ translate_hierarchy_event (ClutterBackendX11       *backend_x11,
         }
       else if (ev->info[i].flags & XIDeviceDisabled)
         {
+          CLUTTER_NOTE (EVENT, "Hierarchy event: device disabled");
+
           remove_device (manager_xi2, ev->info[i].deviceid);
         }
       else if ((ev->info[i].flags & XISlaveAttached) ||
@@ -345,6 +346,11 @@ translate_hierarchy_event (ClutterBackendX11       *backend_x11,
           XIDeviceInfo *info;
           int n_devices;
 
+          CLUTTER_NOTE (EVENT, "Hierarchy event: slave %s",
+                        (ev->info[i].flags & XISlaveAttached)
+                          ? "attached"
+                          : "detached");
+
           slave = g_hash_table_lookup (manager_xi2->devices_by_id,
                                        GINT_TO_POINTER (ev->info[i].deviceid));
           master = clutter_input_device_get_associated_device (slave);
@@ -533,8 +539,8 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
   ClutterDeviceManagerXI2 *manager_xi2 = CLUTTER_DEVICE_MANAGER_XI2 (translator);
   ClutterTranslateReturn retval = CLUTTER_TRANSLATE_CONTINUE;
   ClutterBackendX11 *backend_x11;
-  ClutterStageX11 *stage_x11;
-  ClutterStage *stage;
+  ClutterStageX11 *stage_x11 = NULL;
+  ClutterStage *stage = NULL;
   ClutterInputDevice *device;
   XGenericEventCookie *cookie;
   XIEvent *xi_event;
@@ -558,15 +564,19 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
 
   xi_event = (XIEvent *) cookie->data;
 
-  stage = get_event_stage (translator, xi_event);
-  if (stage == NULL || CLUTTER_ACTOR_IN_DESTRUCTION (stage))
+  if (!(xi_event->evtype == XI_HierarchyChanged ||
+        xi_event->evtype == XI_DeviceChanged))
     {
-      XFreeEventData (backend_x11->xdpy, cookie);
-      return CLUTTER_TRANSLATE_CONTINUE;
+      stage = get_event_stage (translator, xi_event);
+      if (stage == NULL || CLUTTER_ACTOR_IN_DESTRUCTION (stage))
+        {
+          XFreeEventData (backend_x11->xdpy, cookie);
+          return CLUTTER_TRANSLATE_CONTINUE;
+        }
+      else
+        stage_x11 = CLUTTER_STAGE_X11 (_clutter_stage_get_window (stage));
     }
 
-  stage_x11 = CLUTTER_STAGE_X11 (_clutter_stage_get_window (stage));
-
   event->any.stage = stage;
 
   switch (xi_event->evtype)
diff --git a/tests/interactive/test-devices.c b/tests/interactive/test-devices.c
index f38e3285e..e68a26d11 100644
--- a/tests/interactive/test-devices.c
+++ b/tests/interactive/test-devices.c
@@ -4,9 +4,9 @@
 #include <clutter/x11/clutter-x11.h>
 
 typedef struct {
+  ClutterActor *stage;
 
   GHashTable *devices;
-
 } TestDevicesApp;
 
 static const gchar *
@@ -77,11 +77,10 @@ axis_type_name (ClutterInputAxis axis)
 }
 
 static gboolean
-stage_button_event_cb (ClutterActor *actor,
-                       ClutterEvent *event,
-                       gpointer userdata)
+stage_button_event_cb (ClutterActor   *actor,
+                       ClutterEvent   *event,
+                       TestDevicesApp *app)
 {
-  TestDevicesApp *app = (TestDevicesApp *)userdata;
   ClutterInputDevice *device;
   ClutterInputDevice *source_device;
   ClutterActor *hand = NULL;
@@ -128,11 +127,10 @@ stage_button_event_cb (ClutterActor *actor,
 }
 
 static gboolean
-stage_motion_event_cb (ClutterActor *actor,
-                       ClutterEvent *event,
-                       gpointer userdata)
+stage_motion_event_cb (ClutterActor   *actor,
+                       ClutterEvent   *event,
+                       TestDevicesApp *app)
 {
-  TestDevicesApp *app = (TestDevicesApp *)userdata;
   ClutterInputDevice *device;
   ClutterActor *hand = NULL;
 
@@ -152,6 +150,65 @@ stage_motion_event_cb (ClutterActor *actor,
   return FALSE;
 }
 
+static void
+manager_device_added_cb (ClutterDeviceManager *manager,
+                         ClutterInputDevice   *device,
+                         TestDevicesApp       *app)
+{
+  ClutterInputDeviceType device_type;
+  ClutterActor *hand = NULL;
+
+  g_print ("got a %s device '%s' with id %d\n",
+           device_type_name (device),
+           clutter_input_device_get_device_name (device),
+           clutter_input_device_get_device_id (device));
+
+  device_type = clutter_input_device_get_device_type (device);
+  if (device_type == CLUTTER_POINTER_DEVICE ||
+      device_type == CLUTTER_PEN_DEVICE ||
+      device_type == CLUTTER_POINTER_DEVICE)
+    {
+      g_print ("*** enabling device '%s' ***\n",
+               clutter_input_device_get_device_name (device));
+
+      clutter_input_device_set_enabled (device, TRUE);
+
+      hand = clutter_texture_new_from_file (TESTS_DATADIR
+                                            G_DIR_SEPARATOR_S
+                                            "redhand.png",
+                                            NULL);
+      g_hash_table_insert (app->devices, device, hand);
+
+      clutter_container_add_actor (CLUTTER_CONTAINER (app->stage), hand);
+    }
+}
+
+static void
+manager_device_removed_cb (ClutterDeviceManager *manager,
+                           ClutterInputDevice   *device,
+                           TestDevicesApp       *app)
+{
+  ClutterInputDeviceType device_type;
+  ClutterActor *hand = NULL;
+
+  g_print ("removed a %s device '%s' with id %d\n",
+           device_type_name (device),
+           clutter_input_device_get_device_name (device),
+           clutter_input_device_get_device_id (device));
+
+  device_type = clutter_input_device_get_device_type (device);
+  if (device_type == CLUTTER_POINTER_DEVICE ||
+      device_type == CLUTTER_PEN_DEVICE ||
+      device_type == CLUTTER_POINTER_DEVICE)
+    {
+      hand = g_hash_table_lookup (app->devices, device);
+      if (hand != NULL)
+        clutter_container_add_actor (CLUTTER_CONTAINER (app->stage), hand);
+
+      g_hash_table_remove (app->devices, device);
+    }
+}
+
 G_MODULE_EXPORT int
 test_devices_main (int argc, char **argv)
 {
@@ -181,10 +238,18 @@ test_devices_main (int argc, char **argv)
   g_signal_connect (stage,
                     "button-press-event", G_CALLBACK (stage_button_event_cb),
                     app);
+  app->stage = stage;
 
   clutter_actor_show_all (stage);
 
   manager = clutter_device_manager_get_default ();
+  g_signal_connect (manager,
+                    "device-added", G_CALLBACK (manager_device_added_cb),
+                    app);
+  g_signal_connect (manager,
+                    "device-removed", G_CALLBACK (manager_device_removed_cb),
+                    app);
+
   stage_devices = clutter_device_manager_peek_devices (manager);
 
   if (stage_devices == NULL)