+static DBusMessage *
+impl_deregister_device_listener (DBusConnection *bus,
+ DBusMessage *message,
+ void *user_data)
+{
+ SpiDEController *controller = SPI_REGISTRY(user_data)->de_controller;
+ DEControllerListener *listener;
+ DBusError error;
+ const char *path;
+ dbus_int32_t event_types;
+ DBusMessage *reply;
+
+ dbus_error_init(&error);
+ if (!dbus_message_get_args(message, &error, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_UINT32, &event_types, DBUS_TYPE_INVALID))
+ {
+ return spi_dbus_general_error (message);
+ }
+ listener = spi_dec_listener_new (dbus_message_get_sender(message), path, event_types);
+ spi_controller_deregister_device_listener (
+ controller, listener);
+ reply = dbus_message_new_method_return (message);
+ return reply;
+}
+
+static unsigned int dec_xkb_get_slowkeys_delay (SpiDEController *controller)
+{
+ unsigned int retval = 0;
+ DEControllerPrivateData *priv = (DEControllerPrivateData *)
+ g_object_get_qdata (G_OBJECT (controller), spi_dec_private_quark);
+#ifdef HAVE_XKB
+#ifdef XKB_HAS_GET_SLOW_KEYS_DELAY
+ retval = XkbGetSlowKeysDelay (spi_get_display (),
+ XkbUseCoreKbd, &bounce_delay);
+#else
+ if (!(priv->xkb_desc == (XkbDescPtr) BadAlloc || priv->xkb_desc == NULL))
+ {
+ Status s = XkbGetControls (spi_get_display (),
+ XkbAllControlsMask, priv->xkb_desc);
+ if (s == Success)
+ {
+ if (priv->xkb_desc->ctrls->enabled_ctrls & XkbSlowKeysMask)
+ retval = priv->xkb_desc->ctrls->slow_keys_delay;
+ }
+ }
+#endif
+#endif
+#ifdef SPI_XKB_DEBUG
+ fprintf (stderr, "SlowKeys delay: %d\n", (int) retval);
+#endif
+ return retval;
+}
+
+static unsigned int dec_xkb_get_bouncekeys_delay (SpiDEController *controller)
+{
+ unsigned int retval = 0;
+ DEControllerPrivateData *priv = (DEControllerPrivateData *)
+ g_object_get_qdata (G_OBJECT (controller), spi_dec_private_quark);
+#ifdef HAVE_XKB
+#ifdef XKB_HAS_GET_BOUNCE_KEYS_DELAY
+ retval = XkbGetBounceKeysDelay (spi_get_display (),
+ XkbUseCoreKbd, &bounce_delay);
+#else
+ if (!(priv->xkb_desc == (XkbDescPtr) BadAlloc || priv->xkb_desc == NULL))
+ {
+ Status s = XkbGetControls (spi_get_display (),
+ XkbAllControlsMask, priv->xkb_desc);
+ if (s == Success)
+ {
+ if (priv->xkb_desc->ctrls->enabled_ctrls & XkbBounceKeysMask)
+ retval = priv->xkb_desc->ctrls->debounce_delay;
+ }
+ }
+#endif
+#endif
+#ifdef SPI_XKB_DEBUG
+ fprintf (stderr, "BounceKeys delay: %d\n", (int) retval);
+#endif
+ return retval;
+}
+
+static gboolean
+dec_synth_keycode_press (SpiDEController *controller,
+ unsigned int keycode)
+{
+ unsigned int time = CurrentTime;
+ unsigned int bounce_delay;
+ unsigned int elapsed_msec;
+ struct timeval tv;
+ DEControllerPrivateData *priv =
+ (DEControllerPrivateData *) g_object_get_qdata (G_OBJECT (controller),
+ spi_dec_private_quark);
+ if (keycode == priv->last_release_keycode)
+ {
+ bounce_delay = dec_xkb_get_bouncekeys_delay (controller);
+ if (bounce_delay)
+ {
+ gettimeofday (&tv, NULL);
+ elapsed_msec =
+ (tv.tv_sec - priv->last_release_time.tv_sec) * 1000
+ + (tv.tv_usec - priv->last_release_time.tv_usec) / 1000;
+#ifdef SPI_XKB_DEBUG
+ fprintf (stderr, "%d ms elapsed (%ld usec)\n", elapsed_msec,
+ (long) (tv.tv_usec - priv->last_release_time.tv_usec));
+#endif
+#ifdef THIS_IS_BROKEN
+ if (elapsed_msec < bounce_delay)
+ time = bounce_delay - elapsed_msec + 1;
+#else
+ time = bounce_delay + 10;
+ /* fudge for broken XTest */
+#endif
+#ifdef SPI_XKB_DEBUG
+ fprintf (stderr, "waiting %d ms\n", time);
+#endif
+ }
+ }
+ XTestFakeKeyEvent (spi_get_display (), keycode, True, time);
+ priv->last_press_keycode = keycode;
+ XFlush (spi_get_display ());
+ XSync (spi_get_display (), False);
+ gettimeofday (&priv->last_press_time, NULL);
+ return TRUE;
+}
+
+static gboolean
+dec_synth_keycode_release (SpiDEController *controller,
+ unsigned int keycode)
+{
+ unsigned int time = CurrentTime;
+ unsigned int slow_delay;
+ unsigned int elapsed_msec;
+ struct timeval tv;
+ DEControllerPrivateData *priv =
+ (DEControllerPrivateData *) g_object_get_qdata (G_OBJECT (controller),
+ spi_dec_private_quark);
+ if (keycode == priv->last_press_keycode)
+ {
+ slow_delay = dec_xkb_get_slowkeys_delay (controller);
+ if (slow_delay)
+ {
+ gettimeofday (&tv, NULL);
+ elapsed_msec =
+ (tv.tv_sec - priv->last_press_time.tv_sec) * 1000
+ + (tv.tv_usec - priv->last_press_time.tv_usec) / 1000;
+#ifdef SPI_XKB_DEBUG
+ fprintf (stderr, "%d ms elapsed (%ld usec)\n", elapsed_msec,
+ (long) (tv.tv_usec - priv->last_press_time.tv_usec));
+#endif
+#ifdef THIS_IS_BROKEN_DUNNO_WHY
+ if (elapsed_msec < slow_delay)
+ time = slow_delay - elapsed_msec + 1;
+#else
+ time = slow_delay + 10;
+ /* our XTest seems broken, we have to add slop as above */
+#endif
+#ifdef SPI_XKB_DEBUG
+ fprintf (stderr, "waiting %d ms\n", time);
+#endif
+ }
+ }
+ XTestFakeKeyEvent (spi_get_display (), keycode, False, time);
+ priv->last_release_keycode = keycode;
+ XSync (spi_get_display (), False);
+ gettimeofday (&priv->last_release_time, NULL);
+ return TRUE;
+}
+
+static unsigned
+dec_get_modifier_state (SpiDEController *controller)
+{
+ return mouse_mask_state;
+}
+
+static gboolean
+dec_lock_modifiers (SpiDEController *controller, unsigned modifiers)
+{
+ DEControllerPrivateData *priv = (DEControllerPrivateData *)
+ g_object_get_qdata (G_OBJECT (controller), spi_dec_private_quark);
+
+ if (priv->have_xkb) {
+ return XkbLockModifiers (spi_get_display (), XkbUseCoreKbd,
+ modifiers, modifiers);
+ } else {
+ int mod_index;
+ for (mod_index=0;mod_index<8;mod_index++)
+ if (modifiers & (1<<mod_index))
+ dec_synth_keycode_press(controller, xmkeymap->modifiermap[mod_index]);
+ return TRUE;
+ }
+}
+
+static gboolean
+dec_unlock_modifiers (SpiDEController *controller, unsigned modifiers)
+{
+ DEControllerPrivateData *priv = (DEControllerPrivateData *)
+ g_object_get_qdata (G_OBJECT (controller), spi_dec_private_quark);
+
+ if (priv->have_xkb) {
+ return XkbLockModifiers (spi_get_display (), XkbUseCoreKbd,
+ modifiers, 0);
+ } else {
+ int mod_index;
+ for (mod_index=0;mod_index<8;mod_index++)
+ if (modifiers & (1<<mod_index))
+ dec_synth_keycode_release(controller, xmkeymap->modifiermap[mod_index]);
+ return TRUE;
+ }
+}
+
+static KeySym
+dec_keysym_for_unichar (SpiDEController *controller, gunichar unichar)
+{
+ return ucs2keysym ((long) unichar);
+}
+
+static gboolean
+dec_synth_keysym (SpiDEController *controller, KeySym keysym)