/* A pointer to our parent object class */
static GObjectClass *spi_device_event_controller_parent_class;
+int (*x_default_error_handler) (Display *display, XErrorEvent *error_event);
+
typedef enum {
SPI_DEVICE_TYPE_KBD,
+ SPI_DEVICE_TYPE_MOUSE,
SPI_DEVICE_TYPE_LAST_DEFINED
} SpiDeviceTypeCategory;
return GDK_FILTER_CONTINUE;
}
+int
+_spi_controller_device_error_handler (Display *display, XErrorEvent *error)
+{
+ if (error->error_code == BadAccess)
+ {
+ g_message ("Could not complete key grab: grab already in use.\n");
+ }
+ else
+ {
+ (*x_default_error_handler) (display, error);
+ }
+}
+
static void
spi_controller_register_with_devices (SpiDEController *controller)
{
gdk_window_set_events (gdk_get_default_root_window (),
GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK);
+ x_default_error_handler = XSetErrorHandler (_spi_controller_device_error_handler);
+
XSelectInput (GDK_DISPLAY (),
DefaultRootWindow (GDK_DISPLAY ()),
KeyPressMask | KeyReleaseMask);
}
else if (grab_mask->pending_remove)
{
+#ifdef SPI_DEBUG
+ fprintf (stderr, "ungrabbing, mask=%x\n", grab_mask->mod_mask);
+#endif
XUngrabKey (GDK_DISPLAY (),
grab_mask->key_val,
grab_mask->mod_mask,
}
else if (grab_mask->pending_add || re_issue_grab)
{
+
+#ifdef SPI_DEBUG
+ fprintf (stderr, "grab with mask %x\n", grab_mask->mod_mask);
+#endif
XGrabKey (GDK_DISPLAY (),
grab_mask->key_val,
grab_mask->mod_mask,
fprintf(stderr, "spi_device_event_controller_object_finalize called\n");
#endif
/* disconnect any special listeners, get rid of outstanding keygrabs */
+ XUngrabKey (GDK_DISPLAY (), AnyKey, AnyModifier, DefaultRootWindow (GDK_DISPLAY ()));
spi_device_event_controller_parent_class->finalize (object);
}
DEControllerKeyListener *key_listener;
} RemoveKeyListenerClosure;
-static SpiReEnterantContinue
+static SpiReEntrantContinue
remove_key_listener_cb (GList * const *list,
gpointer user_data)
{
if (CORBA_Object_is_equivalent (ctx->key_listener->listener.object,
key_listener->listener.object, ctx->ev))
{
- spi_re_enterant_list_delete_link (list);
+ spi_re_entrant_list_delete_link (list);
spi_dec_key_listener_free (key_listener, ctx->ev);
}
- return SPI_RE_ENTERANT_CONTINUE;
+ return SPI_RE_ENTRANT_CONTINUE;
+}
+
+static SpiReEntrantContinue
+copy_key_listener_cb (GList * const *list,
+ gpointer user_data)
+{
+ DEControllerKeyListener *key_listener = (*list)->data;
+ RemoveKeyListenerClosure *ctx = user_data;
+
+ if (CORBA_Object_is_equivalent (ctx->key_listener->listener.object,
+ key_listener->listener.object, ctx->ev))
+ {
+ /* TODO: FIXME aggregate keys in case the listener is registered twice */
+ CORBA_free (ctx->key_listener->keys);
+ ctx->key_listener->keys = ORBit_copy_value (key_listener->keys, TC_Accessibility_KeySet);
+ }
+
+ return SPI_RE_ENTRANT_CONTINUE;
}
/*
(void *) l, (unsigned long) mask->value);
#endif
- spi_controller_deregister_global_keygrabs (controller, key_listener);
-
ctx.ev = ev;
ctx.key_listener = key_listener;
- spi_re_enterant_list_foreach (&controller->key_listeners,
+ /* special case, copy keyset from existing controller list entry */
+ if (keys->_length == 0)
+ {
+ spi_re_entrant_list_foreach (&controller->key_listeners,
+ copy_key_listener_cb, &ctx);
+ }
+
+ spi_controller_deregister_global_keygrabs (controller, key_listener);
+
+ spi_re_entrant_list_foreach (&controller->key_listeners,
remove_key_listener_cb, &ctx);
spi_dec_key_listener_free (key_listener, ev);