+static gboolean
+check_release (gpointer data)
+{
+ gboolean released;
+ Accessibility_DeviceEvent *event = (Accessibility_DeviceEvent *)data;
+ KeyCode code = event->hw_code;
+
+ released = is_key_released (code);
+
+ if (released)
+ {
+ check_release_handler = 0;
+ event->type = Accessibility_KEY_RELEASED_EVENT;
+ spi_controller_notify_keylisteners (saved_controller, event, TRUE);
+ }
+ return (released == 0);
+}
+
+static void wait_for_release_event (XEvent *event,
+ SpiDEController *controller)
+{
+ pressed_event = spi_keystroke_from_x_key_event ((XKeyEvent *) event);
+ saved_controller = controller;
+ check_release_handler = g_timeout_add (CHECK_RELEASE_DELAY, check_release, &pressed_event);
+}
+
+static DRouteMethod dev_methods[] =
+{
+ { impl_register_keystroke_listener, "registerKeystrokeListener" },
+ { impl_register_device_event_listener, "registerDeviceEventListener" },
+ { impl_deregister_keystroke_listener, "deregisterKeystrokeListener" },
+ { impl_deregister_device_event_listener, "deregisterDeviceEventListener" },
+ { impl_generate_keyboard_event, "generateKeyboardEvent" },
+ { impl_generate_mouse_event, "generateMouseEvent" },
+ { impl_notify_listeners_sync, "notifyListenersSync" },
+ { impl_notify_listeners_async, "notifyListenersAsync" },
+ { NULL, NULL }
+};
+
+SpiDEController *
+spi_registry_dec_new (SpiRegistry *reg, DBusConnection *bus, DRouteContext *droute)
+{
+ SpiDEController *dec = g_object_new (SPI_DEVICE_EVENT_CONTROLLER_TYPE, NULL);
+ DRoutePath *path;
+
+ dec->registry = g_object_ref (reg);
+ dec->bus = bus;
+
+ path = droute_add_one (droute,
+ SPI_DBUS_PATH_DEC,
+ dec);
+
+ droute_path_add_interface (path,
+ SPI_DBUS_INTERFACE_DEC,
+ dev_methods,
+ NULL);
+
+ spi_dec_init_mouse_listener (dec);
+ /* TODO: kill mouse listener on finalize */
+
+ return dec;
+}