X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=registryd%2Fdeviceeventcontroller.c;h=8e0b85620afc09024116f6c9f49027b5ba841fad;hb=82b0abd3d64f6bbe407068bfc9a42dcc18629f0a;hp=f5d6fb64dc965bf9381b0c4df6306c0a2d8b218c;hpb=f6ca06461319b20463f96a5b37544a540aee11ca;p=platform%2Fupstream%2Fat-spi2-core.git diff --git a/registryd/deviceeventcontroller.c b/registryd/deviceeventcontroller.c index f5d6fb6..8e0b856 100644 --- a/registryd/deviceeventcontroller.c +++ b/registryd/deviceeventcontroller.c @@ -48,20 +48,17 @@ #endif /* HAVE_XEVIE */ #include -#include -#include /* TODO: hide dependency (wrap in single porting file) */ -#include -#include -#include -#include -#include -#include -#include +#include + +#include "paths.h" +#include "keymasks.h" +#include "de-types.h" +#include "de-marshaller.h" +#include "display.h" #include "deviceeventcontroller.h" #include "reentrant-list.h" -#include "libspi/keymasks.h" KeySym ucs2keysym (long ucs); long keysym2ucs(KeySym keysym); @@ -78,8 +75,13 @@ static void wait_for_release_event (XEvent *event, SpiDEController *controller); /* A pointer to our parent object class */ static int spi_error_code = 0; -static GdkPoint last_mouse_pos_static = {0, 0}; -static GdkPoint *last_mouse_pos = &last_mouse_pos_static; +struct _SpiPoint { + gint x; + gint y; +}; +typedef struct _SpiPoint SpiPoint; +static SpiPoint last_mouse_pos_static = {0, 0}; +static SpiPoint *last_mouse_pos = &last_mouse_pos_static; static unsigned int mouse_mask_state = 0; static unsigned int mouse_button_mask = Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask; @@ -90,6 +92,9 @@ static unsigned int _numlock_physical_mask = Mod2Mask; /* a guess, will be reset static GQuark spi_dec_private_quark = 0; static XModifierKeymap* xmkeymap = NULL; +static gboolean have_mouse_listener = FALSE; +static gboolean have_mouse_event_listener = FALSE; + static int (*x_default_error_handler) (Display *display, XErrorEvent *error_event); typedef enum { @@ -108,7 +113,7 @@ typedef struct { } DEControllerGrabMask; typedef struct { - char *app_path; + char *bus_name; char *path; SpiDeviceTypeCategory type; gulong types; @@ -160,11 +165,56 @@ static gboolean spi_dec_poll_mouse_moved (gpointer data); static gboolean spi_dec_poll_mouse_moving (gpointer data); static gboolean spi_dec_poll_mouse_idle (gpointer data); -#define spi_get_display() GDK_DISPLAY() - G_DEFINE_TYPE(SpiDEController, spi_device_event_controller, G_TYPE_OBJECT) +DBusMessage * +invalid_arguments_error (DBusMessage *message) +{ + DBusMessage *reply; + gchar *errmsg; + + errmsg= g_strdup_printf ( + "Method \"%s\" with signature \"%s\" on interface \"%s\" was supplied with invalid arguments\n", + dbus_message_get_member (message), + dbus_message_get_signature (message), + dbus_message_get_interface (message)); + reply = dbus_message_new_error (message, + DBUS_ERROR_INVALID_ARGS, + errmsg); + g_free (errmsg); + return reply; +} + /* Private methods */ +static dbus_bool_t +spi_dbus_add_disconnect_match (DBusConnection *bus, const char *name) +{ + char *match = g_strdup_printf ("interface=%s,member=NameOwnerChanged,arg0=%s", DBUS_INTERFACE_DBUS, name); + if (match) + { + DBusError error; + dbus_error_init (&error); + dbus_bus_add_match (bus, match, &error); + g_free (match); + return !dbus_error_is_set (&error); + } + else return FALSE; +} + +static dbus_bool_t +spi_dbus_remove_disconnect_match (DBusConnection *bus, const char *name) +{ + char *match = g_strdup_printf ("interface=%s,member=NameOwnerChanged,arg0=%s", DBUS_INTERFACE_DBUS, name); + if (match) + { + DBusError error; + dbus_error_init (&error); + dbus_bus_remove_match (bus, match, &error); + g_free (match); + return !dbus_error_is_set (&error); + } + else return FALSE; +} static unsigned int keysym_mod_mask (KeySym keysym, KeyCode keycode) @@ -340,24 +390,43 @@ spi_dec_clear_unlatch_pending (SpiDEController *controller) { DEControllerPrivateData *priv = g_object_get_qdata (G_OBJECT (controller), spi_dec_private_quark); - priv->xkb_latch_mask = 0; + priv->xkb_latch_mask = 0; } - -static void emit(SpiDEController *controller, const char *name, int first_type, ...) + +static void emit(SpiDEController *controller, const char *interface, const char *name, const char *minor, int a1, int a2) { - va_list arg; + DBusMessage *signal = NULL; + DBusMessageIter iter, iter_struct, iter_variant; + int nil = 0; + const char *path = SPI_DBUS_PATH_ROOT; + const char *bus_name = dbus_bus_get_unique_name (controller->bus); + + signal = dbus_message_new_signal (path, interface, name); - va_start(arg, first_type); - spi_dbus_emit_valist(controller->registry->droute.bus, SPI_DBUS_PATH_DEC, SPI_DBUS_INTERFACE_DEC, name, first_type, arg); - va_end(arg); + dbus_message_iter_init_append (signal, &iter); + + dbus_message_iter_open_container (&iter, DBUS_TYPE_STRUCT, NULL, + &iter_struct); + dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &bus_name); + dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_OBJECT_PATH, &path); + dbus_message_iter_close_container (&iter, &iter_struct); + + dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &minor); + dbus_message_iter_append_basic (&iter, DBUS_TYPE_UINT32, &a1); + dbus_message_iter_append_basic (&iter, DBUS_TYPE_UINT32, &a2); + dbus_message_iter_open_container (&iter, DBUS_TYPE_VARIANT, "i", &iter_variant); + dbus_message_iter_append_basic (&iter_variant, DBUS_TYPE_INT32, &nil); + dbus_message_iter_close_container (&iter, &iter_variant); + + dbus_connection_send (controller->bus, signal, NULL); } static gboolean -spi_dec_button_update_and_emit (SpiDEController *controller, +spi_dec_button_update_and_emit (SpiDEController *controller, guint mask_return) { Accessibility_DeviceEvent mouse_e; - gchar event_name[24]; + gchar event_detail[3]; gboolean is_consumed = FALSE; if ((mask_return & mouse_button_mask) != @@ -436,7 +505,7 @@ spi_dec_button_update_and_emit (SpiDEController *controller, fprintf (stderr, "Button %d %s\n", button_number, (is_down) ? "Pressed" : "Released"); #endif - snprintf (event_name, 22, "mouse:button:%d%c", button_number, + snprintf (event_detail, 3, "%d%c", button_number, (is_down) ? 'p' : 'r'); /* TODO: FIXME distinguish between physical and * logical buttons @@ -456,7 +525,7 @@ spi_dec_button_update_and_emit (SpiDEController *controller, if (!is_consumed) { dbus_uint32_t x = last_mouse_pos->x, y = last_mouse_pos->y; - emit(controller, event_name, DBUS_TYPE_UINT32, &x, DBUS_TYPE_UINT32, &y, DBUS_TYPE_INVALID); + emit(controller, SPI_DBUS_INTERFACE_EVENT_MOUSE, "Button", event_detail, x, y); } else spi_dec_set_unlatch_pending (controller, mask_return); @@ -500,10 +569,10 @@ spi_dec_mouse_check (SpiDEController *controller, { // TODO: combine these two signals? dbus_uint32_t ix = *x, iy = *y; - emit(controller, "mouse_abs", DBUS_TYPE_UINT32, &ix, DBUS_TYPE_UINT32, &iy, DBUS_TYPE_INVALID); + emit(controller, SPI_DBUS_INTERFACE_EVENT_MOUSE, "Abs", "", ix, iy); ix -= last_mouse_pos->x; iy -= last_mouse_pos->y; - emit(controller, "mouse_rel", DBUS_TYPE_UINT32, &ix, DBUS_TYPE_UINT32, &iy, DBUS_TYPE_INVALID); + emit(controller, SPI_DBUS_INTERFACE_EVENT_MOUSE, "Rel", "", ix, iy); last_mouse_pos->x = *x; last_mouse_pos->y = *y; *moved = True; @@ -535,20 +604,19 @@ spi_dec_emit_modifier_event (SpiDEController *controller, guint prev_mask, d1 = prev_mask & key_modifier_mask; d2 = current_mask & key_modifier_mask; - emit(controller, "keyboard_modifiers", DBUS_TYPE_UINT32, &d1, DBUS_TYPE_UINT32, &d2, DBUS_TYPE_INVALID); + emit(controller, SPI_DBUS_INTERFACE_EVENT_KEYBOARD, "Modifiers", "", d1, d2); } static gboolean spi_dec_poll_mouse_moved (gpointer data) { - SpiRegistry *registry = SPI_REGISTRY (data); - SpiDEController *controller = registry->de_controller; - int x, y; + SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(data); + int x, y; gboolean moved; guint mask_return; mask_return = spi_dec_mouse_check (controller, &x, &y, &moved); - + if ((mask_return & key_modifier_mask) != (mouse_mask_state & key_modifier_mask)) { @@ -562,7 +630,9 @@ spi_dec_poll_mouse_moved (gpointer data) static gboolean spi_dec_poll_mouse_idle (gpointer data) { - if (! spi_dec_poll_mouse_moved (data)) + if (!have_mouse_event_listener && !have_mouse_listener) + return FALSE; + else if (!spi_dec_poll_mouse_moved (data)) return TRUE; else { @@ -574,7 +644,9 @@ spi_dec_poll_mouse_idle (gpointer data) static gboolean spi_dec_poll_mouse_moving (gpointer data) { - if (spi_dec_poll_mouse_moved (data)) + if (!have_mouse_event_listener && !have_mouse_listener) + return FALSE; + else if (spi_dec_poll_mouse_moved (data)) return TRUE; else { @@ -598,18 +670,15 @@ spi_dec_ungrab_mouse (gpointer data) #endif static void -spi_dec_init_mouse_listener (SpiRegistry *registry) +spi_dec_init_mouse_listener (SpiDEController *dec) { #ifdef GRAB_BUTTON Display *display = spi_get_display (); -#endif - g_timeout_add (100, spi_dec_poll_mouse_idle, registry); -#ifdef GRAB_BUTTON if (display) { if (XGrabButton (display, AnyButton, AnyModifier, - gdk_x11_get_default_root_xwindow (), + spi_get_root_window (), True, ButtonPressMask | ButtonReleaseMask, GrabModeSync, GrabModeAsync, None, None) != Success) { #ifdef SPI_DEBUG @@ -650,7 +719,7 @@ spi_dec_translate_mask (Accessibility_ControllerEventMask mask) } static DEControllerKeyListener * -spi_dec_key_listener_new (const char *app_path, +spi_dec_key_listener_new (const char *bus_name, const char *path, GSList *keys, const Accessibility_ControllerEventMask mask, @@ -658,7 +727,7 @@ spi_dec_key_listener_new (const char *app_path, const Accessibility_EventListenerMode *mode) { DEControllerKeyListener *key_listener = g_new0 (DEControllerKeyListener, 1); - key_listener->listener.app_path = g_strdup(app_path); + key_listener->listener.bus_name = g_strdup(bus_name); key_listener->listener.path = g_strdup(path); key_listener->listener.type = SPI_DEVICE_TYPE_KBD; key_listener->keys = keys; @@ -684,12 +753,12 @@ spi_dec_key_listener_new (const char *app_path, } static DEControllerListener * -spi_dec_listener_new (const char *app_path, +spi_dec_listener_new (const char *bus_name, const char *path, dbus_uint32_t types) { DEControllerListener *listener = g_new0 (DEControllerListener, 1); - listener->app_path = g_strdup(app_path); + listener->bus_name = g_strdup(bus_name); listener->path = g_strdup(path); listener->type = SPI_DEVICE_TYPE_MOUSE; listener->types = types; @@ -700,7 +769,7 @@ static DEControllerListener * spi_listener_clone (DEControllerListener *listener) { DEControllerListener *clone = g_new0 (DEControllerListener, 1); - clone->app_path = g_strdup (listener->app_path); + clone->bus_name = g_strdup (listener->bus_name); clone->path = g_strdup (listener->path); clone->type = listener->type; clone->types = listener->types; @@ -731,7 +800,7 @@ static DEControllerKeyListener * spi_key_listener_clone (DEControllerKeyListener *key_listener) { DEControllerKeyListener *clone = g_new0 (DEControllerKeyListener, 1); - clone->listener.app_path = g_strdup (key_listener->listener.app_path); + clone->listener.bus_name = g_strdup (key_listener->listener.bus_name); clone->listener.path = g_strdup (key_listener->listener.path); clone->listener.type = SPI_DEVICE_TYPE_KBD; clone->keys = keylist_clone (key_listener->keys); @@ -778,14 +847,14 @@ static void spi_listener_clone_free (DEControllerListener *clone) { g_free (clone->path); - g_free (clone->app_path); + g_free (clone->bus_name); g_free (clone); } static void spi_dec_listener_free (DEControllerListener *listener) { - g_free (listener->app_path); + g_free (listener->bus_name); g_free (listener->path); if (listener->type == SPI_DEVICE_TYPE_KBD) spi_key_listener_data_free ((DEControllerKeyListener *) listener); @@ -836,10 +905,6 @@ _deregister_keygrab (SpiDEController *controller, cur_mask->pending_remove = TRUE; } } - else - { - DBG (1, g_warning ("De-registering non-existant grab")); - } } static void @@ -918,6 +983,7 @@ spi_controller_register_device_listener (SpiDEController *controller, controller->key_listeners = g_list_prepend (controller->key_listeners, key_listener); + spi_dbus_add_disconnect_match (controller->bus, key_listener->listener.bus_name); if (key_listener->mode->global) { return spi_controller_register_global_keygrabs (controller, key_listener); @@ -927,26 +993,39 @@ spi_controller_register_device_listener (SpiDEController *controller, break; case SPI_DEVICE_TYPE_MOUSE: controller->mouse_listeners = g_list_prepend (controller->mouse_listeners, listener); + if (!have_mouse_listener) + { + have_mouse_listener = TRUE; + if (!have_mouse_event_listener) + g_timeout_add (100, spi_dec_poll_mouse_idle, controller->registry); + } + spi_dbus_add_disconnect_match (controller->bus, listener->bus_name); break; default: - DBG (1, g_warning ("listener registration for unknown device type.\n")); break; } - return FALSE; + return FALSE; } -static gboolean Accessibility_DeviceEventListener_notifyEvent(SpiRegistry *registry, DEControllerListener *listener, const Accessibility_DeviceEvent *key_event) -{ - DBusMessage *message = dbus_message_new_method_call(listener->app_path, listener->path, "org.freedesktop.atspi.Registry", "notifyEvent"); +static gboolean +Accessibility_DeviceEventListener_NotifyEvent(SpiDEController *controller, + SpiRegistry *registry, + DEControllerListener *listener, + const Accessibility_DeviceEvent *key_event) +{ + DBusMessage *message = dbus_message_new_method_call(listener->bus_name, + listener->path, + SPI_DBUS_INTERFACE_DEVICE_EVENT_LISTENER, + "NotifyEvent"); DBusError error; dbus_bool_t consumed = FALSE; dbus_error_init(&error); - if (spi_dbus_marshall_deviceEvent(message, key_event)) + if (spi_dbus_marshal_deviceEvent(message, key_event)) { // TODO: Evaluate performance: perhaps rework this whole architecture // to avoid blocking calls - DBusMessage *reply = dbus_connection_send_with_reply_and_block(registry->droute.bus, message, 1000, &error); + DBusMessage *reply = dbus_connection_send_with_reply_and_block(controller->bus, message, 1000, &error); if (reply) { DBusError error; @@ -1000,16 +1079,16 @@ spi_controller_notify_mouselisteners (SpiDEController *controlle is_consumed = FALSE; for (l2 = notify; l2 && !is_consumed; l2 = l2->next) { - DEControllerListener *listener = l2->data; + DEControllerListener *listener = l2->data; + + is_consumed = Accessibility_DeviceEventListener_NotifyEvent (controller, controller->registry, listener, event); - is_consumed = Accessibility_DeviceEventListener_notifyEvent (controller->registry, listener, event); - spi_listener_clone_free ((DEControllerListener *) l2->data); } for (; l2; l2 = l2->next) { - DEControllerListener *listener = l2->data; + DEControllerListener *listener = l2->data; spi_listener_clone_free (listener); /* clone doesn't have its own ref, so don't use spi_device_listener_free */ } @@ -1027,7 +1106,7 @@ spi_device_event_controller_forward_mouse_event (SpiDEController *controller, XEvent *xevent) { Accessibility_DeviceEvent mouse_e; - gchar event_name[24]; + gchar event_detail[3]; gboolean is_consumed = FALSE; gboolean xkb_mod_unlatch_occurred; XButtonEvent *xbutton_event = (XButtonEvent *) xevent; @@ -1065,7 +1144,7 @@ spi_device_event_controller_forward_mouse_event (SpiDEController *controller, (xevent->type == ButtonPress) ? "Press" : "Release", mouse_button_state); #endif - snprintf (event_name, 22, "mouse:button_%d%c", button, + snprintf (event_detail, 3, "%d%c", button, (xevent->type == ButtonPress) ? 'p' : 'r'); /* TODO: FIXME distinguish between physical and logical buttons */ @@ -1090,7 +1169,7 @@ spi_device_event_controller_forward_mouse_event (SpiDEController *controller, spi_controller_notify_mouselisteners (controller, &mouse_e); ix = last_mouse_pos->x; iy = last_mouse_pos->y; - emit(controller, event_name, DBUS_TYPE_UINT32, &ix, DBUS_TYPE_UINT32, &iy, DBUS_TYPE_INVALID); + emit(controller, SPI_DBUS_INTERFACE_EVENT_MOUSE, "Button", event_detail, ix, iy); } xkb_mod_unlatch_occurred = (xevent->type == ButtonPress || @@ -1107,10 +1186,9 @@ spi_device_event_controller_forward_mouse_event (SpiDEController *controller, CurrentTime); } -static GdkFilterReturn -global_filter_fn (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data) +static void +global_filter_fn (XEvent *xevent, void *data) { - XEvent *xevent = gdk_xevent; SpiDEController *controller; DEControllerPrivateData *priv; Display *display = spi_get_display (); @@ -1160,7 +1238,7 @@ global_filter_fn (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data) } } - return GDK_FILTER_CONTINUE; + return; } if (xevent->type == ButtonPress || xevent->type == ButtonRelease) { @@ -1230,12 +1308,10 @@ global_filter_fn (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data) priv->xkb_latch_mask = xkb_snev->latched_mods; } } - else - DBG (2, g_warning ("XKB event %d\n", xkb_ev->xkb_type)); XSynchronize (display, FALSE); } - return GDK_FILTER_CONTINUE; + return; } static int @@ -1256,10 +1332,14 @@ _spi_controller_device_error_handler (Display *display, XErrorEvent *error) static void spi_controller_register_with_devices (SpiDEController *controller) { - DEControllerPrivateData *priv = (DEControllerPrivateData *) - g_object_get_qdata (G_OBJECT (controller), spi_dec_private_quark); - /* FIXME: should check for extension first! */ - XTestGrabControl (spi_get_display (), True); + DEControllerPrivateData *priv; + int event_base, error_base, major_version, minor_version; + + priv = (DEControllerPrivateData *) g_object_get_qdata (G_OBJECT (controller), spi_dec_private_quark); + if (XTestQueryExtension (spi_get_display(), &event_base, &error_base, &major_version, &minor_version)) + { + XTestGrabControl (spi_get_display (), True); + } /* calls to device-specific implementations and routines go here */ /* register with: keyboard hardware code handler */ @@ -1286,15 +1366,24 @@ spi_controller_register_with_devices (SpiDEController *controller) if (XKeycodeToKeysym (spi_get_display (), i, 0) != 0) { /* don't use this one if there's a grab client! */ - gdk_error_trap_push (); + + /* Runtime errors are generated from these functions, + * that are then quashed. Equivalent to: + * try + * {Blah} + * except + * {;} + */ + + spi_x_error_trap (); XGrabKey (spi_get_display (), i, 0, - gdk_x11_get_default_root_xwindow (), + spi_get_root_window (), TRUE, GrabModeSync, GrabModeSync); XSync (spi_get_display (), TRUE); XUngrabKey (spi_get_display (), i, 0, - gdk_x11_get_default_root_xwindow ()); - if (!gdk_error_trap_pop ()) + spi_get_root_window ()); + if (!spi_x_error_release ()) { reserved = i; break; @@ -1323,10 +1412,8 @@ spi_controller_register_with_devices (SpiDEController *controller) #endif } - gdk_window_add_filter (NULL, global_filter_fn, controller); - - gdk_window_set_events (gdk_get_default_root_window (), - GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK); + spi_set_filter (global_filter_fn, controller); + spi_set_events (KeyPressMask | KeyReleaseMask); x_default_error_handler = XSetErrorHandler (_spi_controller_device_error_handler); } @@ -1341,7 +1428,9 @@ spi_key_set_contains_key (GSList *key_set, if (!key_set) { - g_print ("null key set!"); +#ifdef SPI_DEBUG + g_print ("null key set!\n"); +#endif return TRUE; } @@ -1458,7 +1547,7 @@ spi_controller_notify_keylisteners (SpiDEController *controller, { DEControllerKeyListener *key_listener = l2->data; - is_consumed = Accessibility_DeviceEventListener_notifyEvent (controller->registry, &key_listener->listener, key_event) && + is_consumed = Accessibility_DeviceEventListener_NotifyEvent (controller, controller->registry, &key_listener->listener, key_event) && key_listener->mode->preemptive; spi_key_listener_clone_free (key_listener); @@ -1694,7 +1783,7 @@ spi_controller_update_key_grabs (SpiDEController *controller, XUngrabKey (spi_get_display (), grab_mask->key_val, grab_mask->mod_mask, - gdk_x11_get_default_root_xwindow ()); + spi_get_root_window ()); do_remove = TRUE; } @@ -1707,7 +1796,7 @@ spi_controller_update_key_grabs (SpiDEController *controller, XGrabKey (spi_get_display (), grab_mask->key_val, grab_mask->mod_mask, - gdk_x11_get_default_root_xwindow (), + spi_get_root_window (), True, GrabModeSync, GrabModeSync); @@ -1771,7 +1860,7 @@ spi_device_event_controller_object_finalize (GObject *object) } /* - * DBus Accessibility::DEController::registerKeystrokeListener + * DBus Accessibility::DEController::RegisterKeystrokeListener * method implementation */ static DBusMessage * @@ -1779,7 +1868,7 @@ impl_register_keystroke_listener (DBusConnection *bus, DBusMessage *message, void *user_data) { - SpiDEController *controller = SPI_REGISTRY(user_data)->de_controller; + SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(user_data); DEControllerKeyListener *dec_listener; DBusMessageIter iter, iter_array; const char *path; @@ -1787,7 +1876,7 @@ impl_register_keystroke_listener (DBusConnection *bus, dbus_int32_t mask, type; Accessibility_EventListenerMode *mode; dbus_bool_t ret; - DBusMessage *reply; + DBusMessage *reply = NULL; char *keystring; dbus_message_iter_init(message, &iter); @@ -1808,7 +1897,20 @@ impl_register_keystroke_listener (DBusConnection *bus, dbus_message_iter_next(&iter); dbus_message_iter_get_basic(&iter, &mask); dbus_message_iter_next(&iter); - dbus_message_iter_get_basic(&iter, &type); + if (!strcmp (dbus_message_iter_get_signature (&iter), "u")) + dbus_message_iter_get_basic(&iter, &type); + else + { + dbus_message_iter_recurse(&iter, &iter_array); + while (dbus_message_iter_get_arg_type(&iter_array) != DBUS_TYPE_INVALID) + { + dbus_uint32_t t; + dbus_message_iter_get_basic (&iter_array, &t); + type |= (1 << t); + dbus_message_iter_next (&iter_array); + } + dbus_message_iter_next (&iter_array); + } dbus_message_iter_next(&iter); mode = (Accessibility_EventListenerMode *)g_malloc(sizeof(Accessibility_EventListenerMode)); if (mode) @@ -1831,26 +1933,26 @@ impl_register_keystroke_listener (DBusConnection *bus, } /* - * DBus Accessibility::DEController::registerDeviceEventListener + * DBus Accessibility::DEController::RegisterDeviceEventListener * method implementation */ static DBusMessage * -impl_register_device_listener (DBusConnection *bus, +impl_register_device_event_listener (DBusConnection *bus, DBusMessage *message, void *user_data) { - SpiDEController *controller = SPI_REGISTRY(user_data)->de_controller; + SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(user_data); DEControllerListener *dec_listener; DBusError error; const char *path; dbus_int32_t event_types; dbus_bool_t ret; - DBusMessage *reply; + DBusMessage *reply = NULL; 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); + return invalid_arguments_error (message); } dec_listener = spi_dec_listener_new (dbus_message_get_sender(message), path, event_types); ret = spi_controller_register_device_listener ( @@ -1875,10 +1977,11 @@ remove_listener_cb (GList * const *list, DEControllerListener *listener = (*list)->data; RemoveListenerClosure *ctx = user_data; - if (!strcmp(ctx->listener->app_path, listener->app_path) && + if (!strcmp(ctx->listener->bus_name, listener->bus_name) && !strcmp(ctx->listener->path, listener->path)) { spi_re_entrant_list_delete_link (list); + spi_dbus_remove_disconnect_match (ctx->bus, listener->bus_name); spi_dec_listener_free (listener); } @@ -1892,7 +1995,7 @@ copy_key_listener_cb (GList * const *list, DEControllerKeyListener *key_listener = (*list)->data; RemoveListenerClosure *ctx = user_data; - if (!strcmp(ctx->listener->app_path, key_listener->listener.app_path) && + if (!strcmp(ctx->listener->bus_name, key_listener->listener.bus_name) && !strcmp(ctx->listener->path, key_listener->listener.path)) { /* TODO: FIXME aggregate keys in case the listener is registered twice */ @@ -1911,11 +2014,13 @@ spi_controller_deregister_device_listener (SpiDEController *controlle { RemoveListenerClosure ctx; - ctx.bus = controller->registry->droute.bus; + ctx.bus = controller->bus; ctx.listener = listener; spi_re_entrant_list_foreach (&controller->mouse_listeners, remove_listener_cb, &ctx); + if (!controller->mouse_listeners) + have_mouse_listener = FALSE; } static void @@ -1924,7 +2029,7 @@ spi_deregister_controller_key_listener (SpiDEController *controller, { RemoveListenerClosure ctx; - ctx.bus = controller->registry->droute.bus; + ctx.bus = controller->bus; ctx.listener = (DEControllerListener *) key_listener; /* special case, copy keyset from existing controller list entry */ @@ -1933,7 +2038,7 @@ spi_deregister_controller_key_listener (SpiDEController *controller, 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, @@ -1941,8 +2046,33 @@ spi_deregister_controller_key_listener (SpiDEController *controller, } +void +spi_remove_device_listeners (SpiDEController *controller, const char *bus_name) +{ + GList *l, *tmp; + + for (l = controller->mouse_listeners; l; l = tmp) + { + DEControllerListener *listener = l->data; + tmp = l->next; + if (!strcmp (listener->bus_name, bus_name)) + { + spi_controller_deregister_device_listener (controller, listener); + } + } + for (l = controller->key_listeners; l; l = tmp) + { + DEControllerKeyListener *key_listener = l->data; + tmp = l->next; + if (!strcmp (key_listener->listener.bus_name, bus_name)) + { + spi_deregister_controller_key_listener (controller, key_listener); + } + } +} + /* - * DBus Accessibility::DEController::deregisterKeystrokeListener + * DBus Accessibility::DEController::DeregisterKeystrokeListener * method implementation */ static DBusMessage * @@ -1950,13 +2080,13 @@ impl_deregister_keystroke_listener (DBusConnection *bus, DBusMessage *message, void *user_data) { - SpiDEController *controller = SPI_REGISTRY(user_data)->de_controller; + SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(user_data); DEControllerKeyListener *key_listener; DBusMessageIter iter, iter_array; const char *path; GSList *keys = NULL; dbus_int32_t mask, type; - DBusMessage *reply; + DBusMessage *reply = NULL; dbus_message_iter_init(message, &iter); // TODO: verify type signature @@ -1994,25 +2124,25 @@ impl_deregister_keystroke_listener (DBusConnection *bus, } /* - * DBus Accessibility::DEController::deregisterDeviceEventListener + * DBus Accessibility::DEController::DeregisterDeviceEventListener * method implementation */ static DBusMessage * -impl_deregister_device_listener (DBusConnection *bus, +impl_deregister_device_event_listener (DBusConnection *bus, DBusMessage *message, void *user_data) { - SpiDEController *controller = SPI_REGISTRY(user_data)->de_controller; + SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(user_data); DEControllerListener *listener; DBusError error; const char *path; dbus_int32_t event_types; - DBusMessage *reply; + DBusMessage *reply = NULL; 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); + return invalid_arguments_error (message); } listener = spi_dec_listener_new (dbus_message_get_sender(message), path, event_types); spi_controller_deregister_device_listener ( @@ -2254,7 +2384,7 @@ dec_synth_keystring (SpiDEController *controller, const char *keystring) gboolean retval = TRUE; const gchar *c; - maxlen = strlen (keystring); + maxlen = strlen (keystring) + 1; keysyms = g_new0 (KeySym, maxlen); if (!(keystring && *keystring && g_utf8_validate (keystring, -1, &c))) { retval = FALSE; @@ -2305,12 +2435,12 @@ dec_synth_keystring (SpiDEController *controller, const char *keystring) /* - * DBus Accessibility::DEController::registerKeystrokeListener + * DBus Accessibility::DEController::RegisterKeystrokeListener * method implementation */ static DBusMessage * impl_generate_keyboard_event (DBusConnection *bus, DBusMessage *message, void *user_data) { - SpiDEController *controller = SPI_REGISTRY(user_data)->de_controller; + SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(user_data); DBusError error; dbus_int32_t keycode; char *keystring; @@ -2318,12 +2448,12 @@ static DBusMessage * impl_generate_keyboard_event (DBusConnection *bus, DBusMess gint err; KeySym keysym; DEControllerPrivateData *priv; - DBusMessage *reply; + DBusMessage *reply = NULL; dbus_error_init(&error); if (!dbus_message_get_args(message, &error, DBUS_TYPE_INT32, &keycode, DBUS_TYPE_STRING, &keystring, DBUS_TYPE_UINT32, &synth_type, DBUS_TYPE_INVALID)) { - return spi_dbus_general_error (message); + return invalid_arguments_error (message); } #ifdef SPI_DEBUG @@ -2337,7 +2467,7 @@ static DBusMessage * impl_generate_keyboard_event (DBusConnection *bus, DBusMess * and fall back to XSendEvent() if XTest is not available. */ - gdk_error_trap_push (); + spi_x_error_trap (); priv = (DEControllerPrivateData *) g_object_get_qdata (G_OBJECT (controller), spi_dec_private_quark); @@ -2373,10 +2503,6 @@ static DBusMessage * impl_generate_keyboard_event (DBusConnection *bus, DBusMess keystring); break; } - if ((err = gdk_error_trap_pop ())) - { - DBG (-1, g_warning ("Error [%d] emitting keystroke", err)); - } if (synth_type == Accessibility_KEY_SYM) { keysym = keycode; } @@ -2391,21 +2517,22 @@ static DBusMessage * impl_generate_keyboard_event (DBusConnection *bus, DBusMess return reply; } -/* Accessibility::DEController::generateMouseEvent */ +/* Accessibility::DEController::GenerateMouseEvent */ static DBusMessage * impl_generate_mouse_event (DBusConnection *bus, DBusMessage *message, void *user_data) { DBusError error; dbus_int32_t x; dbus_int32_t y; char *eventName; - DBusMessage *reply; + DBusMessage *reply = NULL; int button = 0; gboolean err = FALSE; Display *display = spi_get_display (); + dbus_error_init (&error); if (!dbus_message_get_args(message, &error, DBUS_TYPE_INT32, &x, DBUS_TYPE_INT32, &y, DBUS_TYPE_STRING, &eventName, DBUS_TYPE_INVALID)) { - return spi_dbus_general_error (message); + return invalid_arguments_error (message); } #ifdef SPI_DEBUG @@ -2466,18 +2593,18 @@ static DBusMessage * impl_generate_mouse_event (DBusConnection *bus, DBusMessage return reply; } -/* Accessibility::DEController::notifyListenersSync */ +/* Accessibility::DEController::NotifyListenersSync */ static DBusMessage * impl_notify_listeners_sync (DBusConnection *bus, DBusMessage *message, void *user_data) { - SpiDEController *controller = SPI_REGISTRY(user_data)->de_controller; + SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(user_data); Accessibility_DeviceEvent event; dbus_bool_t ret; - DBusMessage *reply; + DBusMessage *reply = NULL; - if (!spi_dbus_demarshall_deviceEvent(message, &event)) + if (!spi_dbus_demarshal_deviceEvent(message, &event)) { - return spi_dbus_general_error (message); + return invalid_arguments_error (message); } #ifdef SPI_DEBUG g_print ("notifylistening listeners synchronously: controller %p, event id %d\n", @@ -2498,13 +2625,13 @@ impl_notify_listeners_sync (DBusConnection *bus, DBusMessage *message, void *use static DBusMessage * impl_notify_listeners_async (DBusConnection *bus, DBusMessage *message, void *user_data) { - SpiDEController *controller = SPI_REGISTRY(user_data)->de_controller; + SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(user_data); Accessibility_DeviceEvent event; - DBusMessage *reply; + DBusMessage *reply = NULL; - if (!spi_dbus_demarshall_deviceEvent(message, &event)) + if (!spi_dbus_demarshal_deviceEvent(message, &event)) { - return spi_dbus_general_error (message); + return invalid_arguments_error (message); } #ifdef SPI_DEBUG g_print ("notifylistening listeners asynchronously: controller %p, event id %d\n", @@ -2522,7 +2649,7 @@ spi_device_event_controller_class_init (SpiDEControllerClass *klass) GObjectClass * object_class = (GObjectClass *) klass; spi_device_event_controller_parent_class = g_type_class_peek_parent (klass); - + object_class->finalize = spi_device_event_controller_object_finalize; if (!spi_dec_private_quark) @@ -2560,6 +2687,7 @@ handle_io (GIOChannel *source, static void spi_device_event_controller_init (SpiDEController *device_event_controller) { + spi_events_init (spi_get_display()); #ifdef HAVE_XEVIE GIOChannel *ioc; int fd; @@ -2624,18 +2752,6 @@ spi_device_event_controller_forward_key_event (SpiDEController *controller, return ret; } -SpiDEController * -spi_device_event_controller_new (SpiRegistry *registry) -{ - SpiDEController *retval = g_object_new ( - SPI_DEVICE_EVENT_CONTROLLER_TYPE, NULL); - - retval->registry = g_object_ref (registry); - - spi_dec_init_mouse_listener (registry); - /* TODO: kill mouse listener on finalize */ - return retval; -} static gboolean is_key_released (KeyCode code) @@ -2674,22 +2790,88 @@ static void wait_for_release_event (XEvent *event, check_release_handler = g_timeout_add (CHECK_RELEASE_DELAY, check_release, &pressed_event); } -static DRouteMethod methods[] = +static DBusHandlerResult +handle_dec_method (DBusConnection *bus, DBusMessage *message, void *user_data) +{ + const gchar *iface = dbus_message_get_interface (message); + const gchar *member = dbus_message_get_member (message); + const gint type = dbus_message_get_type (message); + + DBusMessage *reply = NULL; + + /* Check for basic reasons not to handle */ + if (type != DBUS_MESSAGE_TYPE_METHOD_CALL || + member == NULL || + iface == NULL) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + if (strcmp (iface, SPI_DBUS_INTERFACE_DEC)) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + if (!strcmp (member, "RegisterKeystrokeListener")) + reply = impl_register_keystroke_listener (bus, message, user_data); + else if (!strcmp (member, "RegisterDeviceEventListener")) + reply = impl_register_device_event_listener (bus, message, user_data); + else if (!strcmp (member, "DeregisterKeystrokeListener")) + reply = impl_deregister_keystroke_listener (bus, message, user_data); + else if (!strcmp (member, "DeregisterDeviceEventListener")) + reply = impl_deregister_device_event_listener (bus, message, user_data); + else if (!strcmp (member, "GenerateKeyboardEvent")) + reply = impl_generate_keyboard_event (bus, message, user_data); + else if (!strcmp (member, "GenerateMouseEvent")) + reply = impl_generate_mouse_event (bus, message, user_data); + else if (!strcmp (member, "NotifyListenersSync")) + reply = impl_notify_listeners_sync (bus, message, user_data); + else if (!strcmp (member, "NotifyListenersAsync")) + reply = impl_notify_listeners_async (bus, message, user_data); + else + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + if (!reply) + { + reply = dbus_message_new_method_return (message); + } + dbus_connection_send (bus, reply, NULL); + dbus_message_unref (reply); + + return DBUS_HANDLER_RESULT_HANDLED; +} + +static DBusObjectPathVTable dec_vtable = { - { impl_register_keystroke_listener, "registerKeystrokeListener" }, - { impl_register_device_listener, "registerDeviceListener" }, - { impl_deregister_keystroke_listener, "deregisterKeystrokeListener" }, - { impl_deregister_device_listener, "deregisterDeviceListener" }, - { impl_generate_keyboard_event, "generateKeyboardEvent" }, - { impl_generate_mouse_event, "generateMouseEvent" }, - { impl_notify_listeners_sync, "notifyListenersSync" }, - { impl_notify_listeners_async, "notifyListenersAsync" }, - { NULL, NULL } + NULL, + &handle_dec_method, + NULL, NULL, NULL, NULL }; +SpiDEController * +spi_registry_dec_new (SpiRegistry *reg, DBusConnection *bus) +{ + SpiDEController *dec = g_object_new (SPI_DEVICE_EVENT_CONTROLLER_TYPE, NULL); + + dec->registry = g_object_ref (reg); + dec->bus = bus; + + dbus_connection_register_object_path (bus, SPI_DBUS_PATH_DEC, &dec_vtable, dec); + + spi_dec_init_mouse_listener (dec); + + return dec; +} + void -spi_registry_initialize_dec_interface (DRouteData * data) +spi_device_event_controller_start_poll_mouse (SpiRegistry *registry) { - droute_add_interface (data, "org.freedesktop.atspi.DeviceEventController", methods, - NULL, NULL, NULL); -}; + if (!have_mouse_event_listener) + { + have_mouse_event_listener = TRUE; + if (!have_mouse_listener) + g_timeout_add (100, spi_dec_poll_mouse_idle, registry); + } +} + +void +spi_device_event_controller_stop_poll_mouse (void) +{ + have_mouse_event_listener = FALSE; +}