1 /* AT-SPI - Assistive Technology Service Provider Interface
3 * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
5 * Copyright 2001, 2003 Sun Microsystems Inc.,
6 * Copyright 2001, 2002 Ximian, Inc.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the
20 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
24 /* deviceeventcontroller.c: implement the DeviceEventController interface */
30 #undef SPI_KEYEVENT_DEBUG
39 #include <dbus/dbus.h>
44 #include "de-marshaller.h"
46 #include "event-source.h"
48 #include "deviceeventcontroller.h"
49 #include "reentrant-list.h"
51 #include "introspection.h"
53 #define CHECK_RELEASE_DELAY 20
54 #define BIT(c, x) (c[x/8]&(1<<(x%8)))
55 static SpiDEController *saved_controller;
57 /* Our parent Gtk object type */
58 #define PARENT_TYPE G_TYPE_OBJECT
60 /* A pointer to our parent object class */
61 static int spi_error_code = 0;
66 typedef struct _SpiPoint SpiPoint;
67 static unsigned int mouse_mask_state = 0;
68 static unsigned int key_modifier_mask =
69 SPI_KEYMASK_MOD1 | SPI_KEYMASK_MOD2 | SPI_KEYMASK_MOD3 | SPI_KEYMASK_MOD4 |
70 SPI_KEYMASK_MOD5 | SPI_KEYMASK_SHIFT | SPI_KEYMASK_SHIFTLOCK |
71 SPI_KEYMASK_CONTROL | SPI_KEYMASK_NUMLOCK;
72 static unsigned int _numlock_physical_mask = SPI_KEYMASK_MOD2; /* a guess, will be reset */
74 static gboolean have_mouse_listener = FALSE;
75 static gboolean have_mouse_event_listener = FALSE;
80 guint pending_add : 1;
81 guint pending_remove : 1;
83 Accessibility_ControllerEventMask mod_mask;
84 dbus_uint32_t key_val; /* KeyCode */
85 } DEControllerGrabMask;
88 gboolean spi_controller_update_key_grabs (SpiDEController *controller,
89 Accessibility_DeviceEvent *recv);
91 static gboolean eventtype_seq_contains_event (dbus_uint32_t types,
92 const Accessibility_DeviceEvent *event);
93 static gboolean spi_dec_poll_mouse_moving (gpointer data);
94 static gboolean spi_dec_poll_mouse_idle (gpointer data);
96 G_DEFINE_TYPE(SpiDEController, spi_device_event_controller, G_TYPE_OBJECT)
99 spi_dec_plat_get_keycode (SpiDEController *controller,
105 SpiDEControllerClass *klass;
106 klass = SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS (controller);
107 if (klass->plat.get_keycode)
108 return klass->plat.get_keycode (controller, keysym, key_str, fix, modmask);
114 spi_dec_plat_mouse_check (SpiDEController *controller,
115 int *x, int *y, gboolean *moved)
117 SpiDEControllerClass *klass;
118 klass = SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS (controller);
119 if (klass->plat.mouse_check)
120 return klass->plat.mouse_check (controller, x, y, moved);
126 spi_dec_plat_grab_key (SpiDEController *controller, guint key_val, Accessibility_ControllerEventMask mod_mask)
128 SpiDEControllerClass *klass;
129 klass = SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS (controller);
130 if (klass->plat.grab_key)
131 return klass->plat.grab_key (controller, key_val, mod_mask);
137 spi_dec_plat_ungrab_key (SpiDEController *controller, guint key_val, Accessibility_ControllerEventMask mod_mask)
139 SpiDEControllerClass *klass;
140 klass = SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS (controller);
141 if (klass->plat.ungrab_key)
142 klass->plat.ungrab_key (controller, key_val, mod_mask);
146 spi_dec_plat_synth_keycode_press (SpiDEController *controller,
147 unsigned int keycode)
149 SpiDEControllerClass *klass;
150 klass = SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS (controller);
151 if (klass->plat.synth_keycode_press)
152 return klass->plat.synth_keycode_press (controller, keycode);
158 spi_dec_plat_synth_keycode_release (SpiDEController *controller,
159 unsigned int keycode)
161 SpiDEControllerClass *klass;
162 klass = SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS (controller);
163 if (klass->plat.synth_keycode_release)
164 return klass->plat.synth_keycode_release (controller, keycode);
170 spi_dec_plat_lock_modifiers (SpiDEController *controller, unsigned modifiers)
172 SpiDEControllerClass *klass;
173 klass = SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS (controller);
174 if (klass->plat.lock_modifiers)
175 return klass->plat.lock_modifiers (controller, modifiers);
181 spi_dec_plat_unlock_modifiers (SpiDEController *controller, unsigned modifiers)
183 SpiDEControllerClass *klass;
184 klass = SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS (controller);
185 if (klass->plat.unlock_modifiers)
186 return klass->plat.unlock_modifiers (controller, modifiers);
192 spi_dec_plat_synth_keystring (SpiDEController *controller, guint synth_type, gint keycode, const char *keystring)
194 SpiDEControllerClass *klass;
195 klass = SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS (controller);
196 if (klass->plat.synth_keystring)
197 return klass->plat.synth_keystring (controller, synth_type, keycode, keystring);
203 spi_dec_plat_emit_modifier_event (SpiDEController *controller, guint prev_mask,
206 SpiDEControllerClass *klass;
207 klass = SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS (controller);
208 if (klass->plat.emit_modifier_event)
209 klass->plat.emit_modifier_event (controller, prev_mask, current_mask);
213 spi_dec_plat_generate_mouse_event (SpiDEController *controller,
216 const char *eventName)
218 SpiDEControllerClass *klass;
219 klass = SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS (controller);
220 if (klass->plat.generate_mouse_event)
221 klass->plat.generate_mouse_event (controller, x, y, eventName);
225 invalid_arguments_error (DBusMessage *message)
230 errmsg= g_strdup_printf (
231 "Method \"%s\" with signature \"%s\" on interface \"%s\" was supplied with invalid arguments\n",
232 dbus_message_get_member (message),
233 dbus_message_get_signature (message),
234 dbus_message_get_interface (message));
235 reply = dbus_message_new_error (message,
236 DBUS_ERROR_INVALID_ARGS,
242 /* Private methods */
244 spi_dbus_add_disconnect_match (DBusConnection *bus, const char *name)
246 char *match = g_strdup_printf ("interface=%s,member=NameOwnerChanged,arg0=%s", DBUS_INTERFACE_DBUS, name);
250 dbus_error_init (&error);
251 dbus_bus_add_match (bus, match, &error);
253 if (dbus_error_is_set (&error))
255 dbus_error_free (&error);
267 spi_dbus_remove_disconnect_match (DBusConnection *bus, const char *name)
269 char *match = g_strdup_printf ("interface=%s,member=NameOwnerChanged,arg0=%s", DBUS_INTERFACE_DBUS, name);
273 dbus_error_init (&error);
274 dbus_bus_remove_match (bus, match, &error);
276 if (dbus_error_is_set (&error))
278 dbus_error_free (&error);
289 static DEControllerGrabMask *
290 spi_grab_mask_clone (DEControllerGrabMask *grab_mask)
292 DEControllerGrabMask *clone = g_new (DEControllerGrabMask, 1);
294 memcpy (clone, grab_mask, sizeof (DEControllerGrabMask));
296 clone->ref_count = 1;
297 clone->pending_add = TRUE;
298 clone->pending_remove = FALSE;
304 spi_grab_mask_free (DEControllerGrabMask *grab_mask)
310 spi_grab_mask_compare_values (gconstpointer p1, gconstpointer p2)
312 DEControllerGrabMask *l1 = (DEControllerGrabMask *) p1;
313 DEControllerGrabMask *l2 = (DEControllerGrabMask *) p2;
321 return ((l1->mod_mask != l2->mod_mask) || (l1->key_val != l2->key_val));
326 spi_dec_dbus_emit (SpiDEController *controller, const char *interface,
327 const char *name, const char *minor, int a1, int a2)
329 DBusMessage *signal = NULL;
330 DBusMessageIter iter, iter_struct, iter_variant;
332 const char *path = SPI_DBUS_PATH_ROOT;
333 const char *bus_name = dbus_bus_get_unique_name (controller->bus);
335 signal = dbus_message_new_signal (path, interface, name);
337 dbus_message_iter_init_append (signal, &iter);
339 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &minor);
340 dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &a1);
341 dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &a2);
342 dbus_message_iter_open_container (&iter, DBUS_TYPE_VARIANT, "i", &iter_variant);
343 dbus_message_iter_append_basic (&iter_variant, DBUS_TYPE_INT32, &nil);
344 dbus_message_iter_close_container (&iter, &iter_variant);
346 dbus_message_iter_open_container (&iter, DBUS_TYPE_STRUCT, NULL,
348 dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &bus_name);
349 dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_OBJECT_PATH, &path);
350 dbus_message_iter_close_container (&iter, &iter_struct);
352 dbus_connection_send (controller->bus, signal, NULL);
353 dbus_message_unref (signal);
357 spi_dec_poll_mouse_moved (gpointer data)
359 SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(data);
364 mask_return = spi_dec_plat_mouse_check (controller, &x, &y, &moved);
366 if ((mask_return & key_modifier_mask) !=
367 (mouse_mask_state & key_modifier_mask))
369 spi_dec_plat_emit_modifier_event (controller, mouse_mask_state, mask_return);
370 mouse_mask_state = mask_return;
377 spi_dec_poll_mouse_idle (gpointer data)
379 if (!have_mouse_event_listener && !have_mouse_listener)
381 else if (!spi_dec_poll_mouse_moved (data))
386 id = g_timeout_add (20, spi_dec_poll_mouse_moving, data);
387 g_source_set_name_by_id (id, "[at-spi2-core] spi_dec_poll_mouse_moving");
393 spi_dec_poll_mouse_moving (gpointer data)
395 if (!have_mouse_event_listener && !have_mouse_listener)
397 else if (spi_dec_poll_mouse_moved (data))
402 id = g_timeout_add (100, spi_dec_poll_mouse_idle, data);
403 g_source_set_name_by_id (id, "[at-spi2-core] check_release");
409 * Eventually we can use this to make the marshalling of mask types
410 * more sane, but for now we just use this to detect
411 * the use of 'virtual' masks such as numlock and convert them to
412 * system-specific mask values (i.e. ModMask).
415 static Accessibility_ControllerEventMask
416 spi_dec_translate_mask (Accessibility_ControllerEventMask mask)
418 Accessibility_ControllerEventMask tmp_mask;
419 gboolean has_numlock;
421 has_numlock = (mask & SPI_KEYMASK_NUMLOCK);
425 tmp_mask = mask ^ SPI_KEYMASK_NUMLOCK;
426 tmp_mask |= _numlock_physical_mask;
432 static DEControllerKeyListener *
433 spi_dec_key_listener_new (const char *bus_name,
436 const Accessibility_ControllerEventMask mask,
437 const dbus_uint32_t types,
438 const Accessibility_EventListenerMode *mode)
440 DEControllerKeyListener *key_listener = g_new0 (DEControllerKeyListener, 1);
441 key_listener->listener.bus_name = g_strdup(bus_name);
442 key_listener->listener.path = g_strdup(path);
443 key_listener->listener.type = SPI_DEVICE_TYPE_KBD;
444 key_listener->keys = keys;
445 key_listener->mask = spi_dec_translate_mask (mask);
446 key_listener->listener.types = types;
449 key_listener->mode = (Accessibility_EventListenerMode *) g_malloc(sizeof(Accessibility_EventListenerMode));
450 memcpy(key_listener->mode, mode, sizeof(*mode));
453 key_listener->mode = NULL;
456 g_print ("new listener, with mask %x, is_global %d, keys %p (%d)\n",
457 (unsigned int) key_listener->mask,
458 (int) (mode ? mode->global : 0),
459 (void *) key_listener->keys,
460 (int) (key_listener->keys ? g_slist_length(key_listener->keys) : 0));
466 static DEControllerListener *
467 spi_dec_listener_new (const char *bus_name,
471 DEControllerListener *listener = g_new0 (DEControllerListener, 1);
472 listener->bus_name = g_strdup(bus_name);
473 listener->path = g_strdup(path);
474 listener->type = SPI_DEVICE_TYPE_MOUSE;
475 listener->types = types;
479 static DEControllerListener *
480 spi_listener_clone (DEControllerListener *listener)
482 DEControllerListener *clone = g_new0 (DEControllerListener, 1);
483 clone->bus_name = g_strdup (listener->bus_name);
484 clone->path = g_strdup (listener->path);
485 clone->type = listener->type;
486 clone->types = listener->types;
490 static GSList *keylist_clone (GSList *s)
495 for (l = s; l; l = g_slist_next(l))
497 Accessibility_KeyDefinition *kd = (Accessibility_KeyDefinition *)g_malloc(sizeof(Accessibility_KeyDefinition));
500 Accessibility_KeyDefinition *kds = (Accessibility_KeyDefinition *)l->data;
501 kd->keycode = kds->keycode;
502 kd->keysym = kds->keysym;
503 kd->keystring = g_strdup(kds->keystring);
504 d = g_slist_append(d, kd);
510 static DEControllerKeyListener *
511 spi_key_listener_clone (DEControllerKeyListener *key_listener)
513 DEControllerKeyListener *clone = g_new0 (DEControllerKeyListener, 1);
514 clone->listener.bus_name = g_strdup (key_listener->listener.bus_name);
515 clone->listener.path = g_strdup (key_listener->listener.path);
516 clone->listener.type = SPI_DEVICE_TYPE_KBD;
517 clone->keys = keylist_clone (key_listener->keys);
518 clone->mask = key_listener->mask;
519 clone->listener.types = key_listener->listener.types;
520 if (key_listener->mode)
522 clone->mode = (Accessibility_EventListenerMode *)g_malloc(sizeof(Accessibility_EventListenerMode));
523 if (clone->mode) memcpy(clone->mode, key_listener->mode, sizeof(Accessibility_EventListenerMode));
530 static void keylist_free(GSList *keys)
534 for (l = keys; l; l = g_slist_next(l))
536 Accessibility_KeyDefinition *kd = (Accessibility_KeyDefinition *)l->data;
537 g_free(kd->keystring);
544 spi_key_listener_data_free (DEControllerKeyListener *key_listener)
546 keylist_free(key_listener->keys);
547 if (key_listener->mode) g_free(key_listener->mode);
548 g_free (key_listener->listener.bus_name);
549 g_free (key_listener->listener.path);
550 g_free (key_listener);
554 spi_key_listener_clone_free (DEControllerKeyListener *clone)
556 spi_key_listener_data_free (clone);
560 spi_listener_clone_free (DEControllerListener *clone)
562 g_free (clone->path);
563 g_free (clone->bus_name);
568 spi_dec_listener_free (DEControllerListener *listener)
570 if (listener->type == SPI_DEVICE_TYPE_KBD)
571 spi_key_listener_data_free ((DEControllerKeyListener *) listener);
574 g_free (listener->bus_name);
575 g_free (listener->path);
580 _register_keygrab (SpiDEController *controller,
581 DEControllerGrabMask *grab_mask)
585 l = g_list_find_custom (controller->keygrabs_list, grab_mask,
586 spi_grab_mask_compare_values);
589 DEControllerGrabMask *cur_mask = l->data;
591 cur_mask->ref_count++;
592 if (cur_mask->pending_remove)
594 cur_mask->pending_remove = FALSE;
599 controller->keygrabs_list =
600 g_list_prepend (controller->keygrabs_list,
601 spi_grab_mask_clone (grab_mask));
606 _deregister_keygrab (SpiDEController *controller,
607 DEControllerGrabMask *grab_mask)
611 l = g_list_find_custom (controller->keygrabs_list, grab_mask,
612 spi_grab_mask_compare_values);
616 DEControllerGrabMask *cur_mask = l->data;
618 cur_mask->ref_count--;
619 if (cur_mask->ref_count <= 0)
621 cur_mask->pending_remove = TRUE;
627 handle_keygrab (SpiDEController *controller,
628 DEControllerKeyListener *key_listener,
629 void (*process_cb) (SpiDEController *controller,
630 DEControllerGrabMask *grab_mask))
632 DEControllerGrabMask grab_mask = { 0 };
634 grab_mask.mod_mask = key_listener->mask;
635 if (g_slist_length (key_listener->keys) == 0) /* special case means AnyKey/AllKeys */
637 grab_mask.key_val = AnyKey;
639 fprintf (stderr, "AnyKey grab!");
641 process_cb (controller, &grab_mask);
647 for (l = key_listener->keys; l; l = g_slist_next(l))
649 Accessibility_KeyDefinition *keydef = l->data;
651 key_val = spi_dec_plat_get_keycode (controller, keydef->keysym, keydef->keystring, FALSE, NULL);
653 key_val = keydef->keycode;
654 grab_mask.key_val = key_val;
655 process_cb (controller, &grab_mask);
661 spi_controller_register_global_keygrabs (SpiDEController *controller,
662 DEControllerKeyListener *key_listener)
664 handle_keygrab (controller, key_listener, _register_keygrab);
665 return spi_controller_update_key_grabs (controller, NULL);
669 spi_controller_deregister_global_keygrabs (SpiDEController *controller,
670 DEControllerKeyListener *key_listener)
672 handle_keygrab (controller, key_listener, _deregister_keygrab);
673 spi_controller_update_key_grabs (controller, NULL);
677 append_keystroke_listener (DBusMessageIter *iter, DEControllerKeyListener *listener)
679 dbus_uint32_t d_uint;
680 DBusMessageIter iter_struct, iter_subarray, iter_substruct;
683 if (!dbus_message_iter_open_container (iter, DBUS_TYPE_STRUCT, NULL,
687 dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING,
688 &listener->listener.bus_name);
689 dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_OBJECT_PATH,
690 &listener->listener.path);
691 d_uint = listener->listener.type;
692 dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_UINT32, &d_uint);
693 d_uint = listener->listener.types;
694 dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_UINT32, &d_uint);
695 if (!dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY,
696 "(iisi)", &iter_subarray))
698 dbus_message_iter_close_container (iter, &iter_struct);
701 for (kl = listener->keys; kl; kl = kl->next)
703 Accessibility_KeyDefinition *kd = kl->data;
704 if (!dbus_message_iter_open_container (&iter_subarray, DBUS_TYPE_STRUCT,
705 NULL, &iter_substruct))
707 dbus_message_iter_append_basic (&iter_substruct, DBUS_TYPE_INT32, &kd->keycode);
708 dbus_message_iter_append_basic (&iter_substruct, DBUS_TYPE_INT32, &kd->keysym);
709 dbus_message_iter_append_basic (&iter_substruct, DBUS_TYPE_STRING, &kd->keystring);
710 dbus_message_iter_append_basic (&iter_substruct, DBUS_TYPE_INT32, &kd->unused);
711 dbus_message_iter_close_container (&iter_subarray, &iter_substruct);
713 dbus_message_iter_close_container (&iter_struct, &iter_subarray);
714 d_uint = listener->mask;
715 dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_UINT32, &d_uint);
716 if (dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_STRUCT,
717 NULL, &iter_substruct))
721 dbus_message_iter_append_basic (&iter_substruct, DBUS_TYPE_BOOLEAN,
722 &listener->mode->synchronous);
723 dbus_message_iter_append_basic (&iter_substruct, DBUS_TYPE_BOOLEAN,
724 &listener->mode->preemptive);
725 dbus_message_iter_append_basic (&iter_substruct, DBUS_TYPE_BOOLEAN,
726 &listener->mode->global);
730 dbus_bool_t dummy_val = FALSE;
731 dbus_message_iter_append_basic (&iter_substruct, DBUS_TYPE_BOOLEAN,
733 dbus_message_iter_append_basic (&iter_substruct, DBUS_TYPE_BOOLEAN,
735 dbus_message_iter_append_basic (&iter_substruct, DBUS_TYPE_BOOLEAN,
738 dbus_message_iter_close_container (&iter_struct, &iter_substruct);
740 dbus_message_iter_close_container (iter, &iter_struct);
744 notify_keystroke_listener (SpiDEController *controller,
745 DEControllerKeyListener *listener,
748 const char *path = SPI_DBUS_PATH_DEC;
749 const char *interface = SPI_DBUS_INTERFACE_DEVICE_EVENT_LISTENER;
750 const char *name = (enable
751 ? "KeystrokeListenerRegistered"
752 : "KeystrokeListenerDeregistered");
754 DBusMessageIter iter;
756 signal = dbus_message_new_signal (path, interface, name);
759 dbus_message_iter_init_append (signal, &iter);
760 append_keystroke_listener (&iter, listener);
761 dbus_connection_send (controller->bus, signal, NULL);
762 dbus_message_unref (signal);
766 append_mouse_listener (DBusMessageIter *iter, DEControllerListener *listener)
768 DBusMessageIter iter_struct;
769 dbus_uint32_t d_uint;
771 if (!dbus_message_iter_open_container (iter, DBUS_TYPE_STRUCT, NULL,
774 dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING,
775 &listener->bus_name);
776 dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_OBJECT_PATH,
778 d_uint = listener->types;
779 dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_UINT32, &d_uint);
780 dbus_message_iter_close_container (iter, &iter_struct);
784 notify_mouse_listener (SpiDEController *controller,
785 DEControllerListener *listener,
788 const char *path = SPI_DBUS_PATH_DEC;
789 const char *interface = SPI_DBUS_INTERFACE_DEVICE_EVENT_LISTENER;
790 const char *name = (enable
791 ? "DeviceListenerRegistered"
792 : "DeviceListenerDeregistered");
794 DBusMessageIter iter;
796 signal = dbus_message_new_signal (path, interface, name);
799 dbus_message_iter_init_append (signal, &iter);
800 append_mouse_listener (&iter, listener);
801 dbus_connection_send (controller->bus, signal, NULL);
802 dbus_message_unref (signal);
806 spi_controller_register_device_listener (SpiDEController *controller,
807 DEControllerListener *listener)
809 DEControllerKeyListener *key_listener;
812 switch (listener->type) {
813 case SPI_DEVICE_TYPE_KBD:
814 key_listener = (DEControllerKeyListener *) listener;
816 controller->key_listeners = g_list_prepend (controller->key_listeners,
818 spi_dbus_add_disconnect_match (controller->bus, key_listener->listener.bus_name);
819 if (key_listener->mode->global)
821 retval = spi_controller_register_global_keygrabs (controller, key_listener);
826 notify_keystroke_listener (controller, key_listener, TRUE);
828 case SPI_DEVICE_TYPE_MOUSE:
829 controller->mouse_listeners = g_list_prepend (controller->mouse_listeners, listener);
830 if (!have_mouse_listener)
832 have_mouse_listener = TRUE;
833 if (!have_mouse_event_listener) {
835 id = g_timeout_add (100, spi_dec_poll_mouse_idle, controller);
836 g_source_set_name_by_id (id, "[at-spi2-core] spi_dec_poll_mouse_idle");
839 spi_dbus_add_disconnect_match (controller->bus, listener->bus_name);
840 notify_mouse_listener (controller, listener, TRUE);
849 set_reply (DBusPendingCall *pending, void *user_data)
851 void **replyptr = (void **)user_data;
853 *replyptr = dbus_pending_call_steal_reply (pending);
856 static GSList *hung_processes = NULL;
859 reset_hung_process (DBusPendingCall *pending, void *data)
861 DBusMessage *message = data;
862 const char *dest = dbus_message_get_destination (message);
865 /* At this point we don't care about the result */
866 dbus_pending_call_unref (pending);
868 for (l = hung_processes; l; l = l->next)
870 if (!strcmp (l->data, dest))
873 hung_processes = g_slist_remove (hung_processes, l->data);
880 time_elapsed (struct timeval *origin)
884 gettimeofday (&tv, NULL);
885 return (tv.tv_sec - origin->tv_sec) * 1000 + (tv.tv_usec - origin->tv_usec) / 1000;
889 reset_hung_process_from_ping (DBusPendingCall *pending, void *data)
893 for (l = hung_processes; l; l = l->next)
895 if (!strcmp (l->data, data))
898 hung_processes = g_slist_remove (hung_processes, l->data);
903 dbus_pending_call_unref (pending);
907 send_and_allow_reentry (DBusConnection *bus, DBusMessage *message, int timeout, DBusError *error)
909 DBusPendingCall *pending;
910 DBusMessage *reply = NULL;
913 if (!dbus_connection_send_with_reply (bus, message, &pending, -1))
917 dbus_pending_call_set_notify (pending, set_reply, (void *)&reply, NULL);
918 gettimeofday (&tv, NULL);
921 if (!dbus_connection_read_write_dispatch (bus, timeout) ||
922 time_elapsed (&tv) > timeout)
924 const char *dest = dbus_message_get_destination (message);
927 dbus_message_ref (message);
928 dbus_pending_call_set_notify (pending, reset_hung_process, message,
929 (DBusFreeFunction) dbus_message_unref);
930 message = dbus_message_new_method_call (dest, "/",
931 "org.freedesktop.DBus.Peer",
935 dbus_connection_send_with_reply (bus, message, &pending, -1);
936 dbus_message_unref (message);
939 bus_name_dup = g_strdup (dest);
940 dbus_pending_call_set_notify (pending, reset_hung_process_from_ping,
942 for (l = hung_processes; l; l = l->next)
943 if (!strcmp (l->data, dest))
945 hung_processes = g_slist_prepend (hung_processes, g_strdup (dest));
949 dbus_pending_call_unref (pending);
953 Accessibility_DeviceEventListener_NotifyEvent(SpiDEController *controller,
954 SpiRegistry *registry,
955 DEControllerListener *listener,
956 const Accessibility_DeviceEvent *key_event)
958 DBusMessage *message = dbus_message_new_method_call(listener->bus_name,
960 SPI_DBUS_INTERFACE_DEVICE_EVENT_LISTENER,
962 dbus_bool_t consumed = FALSE;
964 gboolean hung = FALSE;
966 for (l = hung_processes; l; l = l->next)
968 if (!strcmp (l->data, listener->bus_name))
970 dbus_message_set_no_reply (message, TRUE);
976 if (spi_dbus_marshal_deviceEvent(message, key_event))
982 dbus_connection_send (controller->bus, message, NULL);
983 dbus_message_unref (message);
987 reply = send_and_allow_reentry (controller->bus, message, 3000, NULL);
990 dbus_message_get_args(reply, NULL, DBUS_TYPE_BOOLEAN, &consumed, DBUS_TYPE_INVALID);
991 dbus_message_unref(reply);
994 dbus_message_unref(message);
999 spi_controller_notify_mouselisteners (SpiDEController *controller,
1000 const Accessibility_DeviceEvent *event)
1003 GSList *notify = NULL, *l2;
1004 GList **listeners = &controller->mouse_listeners;
1005 gboolean is_consumed;
1006 #ifdef SPI_KEYEVENT_DEBUG
1007 gboolean found = FALSE;
1014 for (l = *listeners; l; l = l->next)
1016 DEControllerListener *listener = l->data;
1018 if (eventtype_seq_contains_event (listener->types, event))
1020 /* we clone (don't dup) the listener, to avoid refcount inc. */
1021 notify = g_slist_prepend (notify,
1022 spi_listener_clone (listener));
1023 #ifdef SPI_KEYEVENT_DEBUG
1029 #ifdef SPI_KEYEVENT_DEBUG
1032 g_print ("no match for event\n");
1036 is_consumed = FALSE;
1037 for (l2 = notify; l2 && !is_consumed; l2 = l2->next)
1039 DEControllerListener *listener = l2->data;
1041 is_consumed = Accessibility_DeviceEventListener_NotifyEvent (controller, controller->registry, listener, event);
1043 spi_listener_clone_free ((DEControllerListener *) l2->data);
1046 for (; l2; l2 = l2->next)
1048 DEControllerListener *listener = l2->data;
1049 spi_listener_clone_free (listener);
1050 /* clone doesn't have its own ref, so don't use spi_device_listener_free */
1053 g_slist_free (notify);
1056 if (is_consumed) g_message ("consumed\n");
1062 key_set_contains_key (GSList *key_set,
1063 const Accessibility_DeviceEvent *key_event)
1072 g_print ("null key set!\n");
1077 len = g_slist_length (key_set);
1079 if (len == 0) /* special case, means "all keys/any key" */
1082 g_print ("anykey\n");
1087 for (l = key_set,i = 0; l; l = g_slist_next(l),i++)
1089 Accessibility_KeyDefinition *kd = l->data;
1090 #ifdef SPI_KEYEVENT_DEBUG
1091 g_print ("key_set[%d] event = %d, code = %d; key_event %d, code %d, string %s\n",
1095 (int) key_event->id,
1096 (int) key_event->hw_code,
1097 key_event->event_string);
1099 if (kd->keysym == (dbus_uint32_t) key_event->id)
1103 if (kd->keycode == (dbus_uint32_t) key_event->hw_code)
1107 if (key_event->event_string && key_event->event_string[0] &&
1108 !strcmp (kd->keystring, key_event->event_string))
1118 eventtype_seq_contains_event (dbus_uint32_t types,
1119 const Accessibility_DeviceEvent *event)
1121 if (types == 0) /* special case, means "all events/any event" */
1126 return (types & (1 << event->type));
1130 spi_key_event_matches_listener (const Accessibility_DeviceEvent *key_event,
1131 DEControllerKeyListener *listener,
1132 dbus_bool_t is_system_global)
1134 if (((key_event->modifiers & 0xFF) == (dbus_uint16_t) (listener->mask & 0xFF)) &&
1135 key_set_contains_key (listener->keys, key_event) &&
1136 eventtype_seq_contains_event (listener->listener.types, key_event) &&
1137 (is_system_global == listener->mode->global))
1148 spi_controller_notify_keylisteners (SpiDEController *controller,
1149 Accessibility_DeviceEvent *key_event,
1150 dbus_bool_t is_system_global)
1153 GSList *notify = NULL, *l2;
1154 GList **key_listeners = &controller->key_listeners;
1155 gboolean is_consumed;
1162 /* set the NUMLOCK event mask bit if appropriate: see bug #143702 */
1163 if (key_event->modifiers & _numlock_physical_mask)
1164 key_event->modifiers |= SPI_KEYMASK_NUMLOCK;
1166 for (l = *key_listeners; l; l = l->next)
1168 DEControllerKeyListener *key_listener = l->data;
1170 if (spi_key_event_matches_listener (key_event, key_listener, is_system_global))
1172 /* we clone (don't dup) the listener, to avoid refcount inc. */
1173 notify = g_slist_prepend (notify,
1174 spi_key_listener_clone (key_listener));
1178 #ifdef SPI_KEYEVENT_DEBUG
1181 g_print ("no match for event\n");
1185 is_consumed = FALSE;
1186 for (l2 = notify; l2 && !is_consumed; l2 = l2->next)
1188 DEControllerKeyListener *key_listener = l2->data;
1190 is_consumed = Accessibility_DeviceEventListener_NotifyEvent (controller, controller->registry, &key_listener->listener, key_event) &&
1191 key_listener->mode->preemptive;
1193 spi_key_listener_clone_free (key_listener);
1196 for (; l2; l2 = l2->next)
1198 DEControllerKeyListener *key_listener = l2->data;
1199 spi_key_listener_clone_free (key_listener);
1200 /* clone doesn't have its own ref, so don't use spi_dec_listener_free */
1203 g_slist_free (notify);
1206 if (is_consumed) g_message ("consumed\n");
1212 spi_clear_error_state (void)
1214 gboolean retval = spi_error_code != 0;
1220 spi_controller_update_key_grabs (SpiDEController *controller,
1221 Accessibility_DeviceEvent *recv)
1224 gboolean update_failed = FALSE;
1227 g_return_val_if_fail (controller != NULL, FALSE);
1230 * masks known to work with default RH 7.1+:
1231 * 0 (no mods), LockMask, Mod1Mask, Mod2Mask, ShiftMask,
1232 * ShiftMask|LockMask, Mod1Mask|LockMask, Mod2Mask|LockMask,
1233 * ShiftMask|Mod1Mask, ShiftMask|Mod2Mask, Mod1Mask|Mod2Mask,
1234 * ShiftMask|LockMask|Mod1Mask, ShiftMask|LockMask|Mod2Mask,
1236 * ControlMask grabs are broken, must be in use already
1239 keycode = spi_dec_plat_get_keycode (controller, recv->id, NULL, TRUE, NULL);
1240 for (l = controller->keygrabs_list; l; l = next)
1243 gboolean re_issue_grab;
1244 DEControllerGrabMask *grab_mask = l->data;
1248 re_issue_grab = recv &&
1249 (recv->modifiers & grab_mask->mod_mask) &&
1250 (grab_mask->key_val == keycode);
1253 fprintf (stderr, "mask=%lx %lx (%c%c) %s\n",
1254 (long int) grab_mask->key_val,
1255 (long int) grab_mask->mod_mask,
1256 grab_mask->pending_add ? '+' : '.',
1257 grab_mask->pending_remove ? '-' : '.',
1258 re_issue_grab ? "re-issue": "");
1263 if (grab_mask->pending_add && grab_mask->pending_remove)
1267 else if (grab_mask->pending_remove)
1270 fprintf (stderr, "ungrabbing, mask=%x\n", grab_mask->mod_mask);
1272 spi_dec_plat_ungrab_key (controller,
1274 grab_mask->mod_mask);
1278 else if (grab_mask->pending_add || re_issue_grab)
1282 fprintf (stderr, "grab %d with mask %x\n", grab_mask->key_val, grab_mask->mod_mask);
1284 update_failed = spi_dec_plat_grab_key (controller,
1286 grab_mask->mod_mask);
1287 if (update_failed) {
1288 while (grab_mask->ref_count > 0) --grab_mask->ref_count;
1293 grab_mask->pending_add = FALSE;
1294 grab_mask->pending_remove = FALSE;
1298 g_assert (grab_mask->ref_count <= 0);
1300 controller->keygrabs_list = g_list_delete_link (
1301 controller->keygrabs_list, l);
1303 spi_grab_mask_free (grab_mask);
1308 return ! update_failed;
1312 * Implemented GObject::finalize
1315 spi_device_event_controller_object_finalize (GObject *object)
1317 SpiDEController *controller;
1318 GObjectClass *parent_class = G_OBJECT_CLASS(spi_device_event_controller_parent_class);
1319 SpiDEControllerClass *klass;
1321 controller = SPI_DEVICE_EVENT_CONTROLLER (object);
1322 klass = SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS (controller);
1324 fprintf(stderr, "spi_device_event_controller_object_finalize called\n");
1326 if (klass->plat.finalize)
1327 klass->plat.finalize (controller);
1329 parent_class->finalize (object);
1333 * DBus Accessibility::DEController::RegisterKeystrokeListener
1334 * method implementation
1336 static DBusMessage *
1337 impl_register_keystroke_listener (DBusConnection *bus,
1338 DBusMessage *message,
1341 SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(user_data);
1342 DEControllerKeyListener *dec_listener;
1343 DBusMessageIter iter, iter_array;
1345 GSList *keys = NULL;
1346 dbus_int32_t mask, type;
1347 Accessibility_EventListenerMode *mode;
1349 DBusMessage *reply = NULL;
1352 if (strcmp (dbus_message_get_signature (message), "oa(iisi)uu(bbb)") != 0)
1353 return invalid_arguments_error (message);
1355 dbus_message_iter_init(message, &iter);
1356 dbus_message_iter_get_basic(&iter, &path);
1357 dbus_message_iter_next(&iter);
1358 dbus_message_iter_recurse(&iter, &iter_array);
1359 while (dbus_message_iter_get_arg_type(&iter_array) != DBUS_TYPE_INVALID)
1361 Accessibility_KeyDefinition *kd = (Accessibility_KeyDefinition *)g_malloc(sizeof(Accessibility_KeyDefinition));
1362 if (!spi_dbus_message_iter_get_struct(&iter_array, DBUS_TYPE_INT32, &kd->keycode, DBUS_TYPE_INT32, &kd->keysym, DBUS_TYPE_STRING, &keystring, DBUS_TYPE_INVALID))
1366 kd->keystring = g_strdup (keystring);
1367 keys = g_slist_append(keys, kd);
1369 dbus_message_iter_next(&iter);
1370 dbus_message_iter_get_basic(&iter, &mask);
1371 dbus_message_iter_next(&iter);
1372 dbus_message_iter_get_basic(&iter, &type);
1373 dbus_message_iter_next(&iter);
1374 mode = (Accessibility_EventListenerMode *)g_malloc(sizeof(Accessibility_EventListenerMode));
1377 spi_dbus_message_iter_get_struct(&iter, DBUS_TYPE_BOOLEAN, &mode->synchronous, DBUS_TYPE_BOOLEAN, &mode->preemptive, DBUS_TYPE_BOOLEAN, &mode->global, DBUS_TYPE_INVALID);
1380 fprintf (stderr, "registering keystroke listener %s:%s with maskVal %lu\n",
1381 dbus_message_get_sender(message), path, (unsigned long) mask);
1383 dec_listener = spi_dec_key_listener_new (dbus_message_get_sender(message), path, keys, mask, type, mode);
1385 ret = spi_controller_register_device_listener (
1386 controller, (DEControllerListener *) dec_listener);
1387 reply = dbus_message_new_method_return (message);
1390 dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &ret, DBUS_TYPE_INVALID);
1396 * DBus Accessibility::DEController::RegisterDeviceEventListener
1397 * method implementation
1399 static DBusMessage *
1400 impl_register_device_event_listener (DBusConnection *bus,
1401 DBusMessage *message,
1404 SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(user_data);
1405 DEControllerListener *dec_listener;
1407 dbus_int32_t event_types;
1409 DBusMessage *reply = NULL;
1411 if (!dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_UINT32, &event_types, DBUS_TYPE_INVALID))
1413 return invalid_arguments_error (message);
1415 dec_listener = spi_dec_listener_new (dbus_message_get_sender(message), path, event_types);
1416 ret = spi_controller_register_device_listener (
1417 controller, (DEControllerListener *) dec_listener);
1418 reply = dbus_message_new_method_return (message);
1421 dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &ret, DBUS_TYPE_INVALID);
1427 DBusConnection *bus;
1428 DEControllerListener *listener;
1429 } RemoveListenerClosure;
1431 static SpiReEntrantContinue
1432 remove_listener_cb (GList * const *list,
1435 DEControllerListener *listener = (*list)->data;
1436 RemoveListenerClosure *ctx = user_data;
1438 if (!strcmp(ctx->listener->bus_name, listener->bus_name) &&
1439 !strcmp(ctx->listener->path, listener->path))
1441 spi_re_entrant_list_delete_link (list);
1442 spi_dbus_remove_disconnect_match (ctx->bus, listener->bus_name);
1443 spi_dec_listener_free (listener);
1446 return SPI_RE_ENTRANT_CONTINUE;
1449 static SpiReEntrantContinue
1450 copy_key_listener_cb (GList * const *list,
1453 DEControllerKeyListener *key_listener = (*list)->data;
1454 RemoveListenerClosure *ctx = user_data;
1456 if (!strcmp(ctx->listener->bus_name, key_listener->listener.bus_name) &&
1457 !strcmp(ctx->listener->path, key_listener->listener.path))
1459 /* TODO: FIXME aggregate keys in case the listener is registered twice */
1460 DEControllerKeyListener *ctx_key_listener =
1461 (DEControllerKeyListener *) ctx->listener;
1462 keylist_free (ctx_key_listener->keys);
1463 ctx_key_listener->keys = keylist_clone(key_listener->keys);
1466 return SPI_RE_ENTRANT_CONTINUE;
1470 spi_controller_deregister_device_listener (SpiDEController *controller,
1471 DEControllerListener *listener)
1473 RemoveListenerClosure ctx;
1475 ctx.bus = controller->bus;
1476 ctx.listener = listener;
1478 notify_mouse_listener (controller, listener, FALSE);
1480 spi_re_entrant_list_foreach (&controller->mouse_listeners,
1481 remove_listener_cb, &ctx);
1482 if (!controller->mouse_listeners)
1483 have_mouse_listener = FALSE;
1487 spi_deregister_controller_key_listener (SpiDEController *controller,
1488 DEControllerKeyListener *key_listener)
1490 RemoveListenerClosure ctx;
1492 ctx.bus = controller->bus;
1493 ctx.listener = (DEControllerListener *) spi_key_listener_clone (key_listener);
1495 notify_keystroke_listener (controller, key_listener, FALSE);
1497 /* special case, copy keyset from existing controller list entry */
1498 if (g_slist_length(key_listener->keys) == 0)
1500 spi_re_entrant_list_foreach (&controller->key_listeners,
1501 copy_key_listener_cb, &ctx);
1504 spi_controller_deregister_global_keygrabs (controller, key_listener);
1506 spi_re_entrant_list_foreach (&controller->key_listeners,
1507 remove_listener_cb, &ctx);
1509 spi_key_listener_clone_free ((DEControllerKeyListener *) ctx.listener);
1513 spi_remove_device_listeners (SpiDEController *controller, const char *bus_name)
1517 for (l = controller->mouse_listeners; l; l = tmp)
1519 DEControllerListener *listener = l->data;
1521 if (!strcmp (listener->bus_name, bus_name))
1523 spi_controller_deregister_device_listener (controller, listener);
1524 tmp = controller->mouse_listeners;
1527 for (l = controller->key_listeners; l; l = tmp)
1529 DEControllerKeyListener *key_listener = l->data;
1531 if (!strcmp (key_listener->listener.bus_name, bus_name))
1533 /* TODO: untangle the below line(s) */
1534 spi_deregister_controller_key_listener (controller, key_listener);
1535 tmp = controller->key_listeners;
1541 * DBus Accessibility::DEController::DeregisterKeystrokeListener
1542 * method implementation
1544 static DBusMessage *
1545 impl_deregister_keystroke_listener (DBusConnection *bus,
1546 DBusMessage *message,
1549 SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(user_data);
1550 DEControllerKeyListener *key_listener;
1551 DBusMessageIter iter, iter_array;
1553 GSList *keys = NULL;
1554 dbus_int32_t mask, type;
1555 DBusMessage *reply = NULL;
1557 dbus_message_iter_init(message, &iter);
1558 if (strcmp (dbus_message_get_signature (message), "oa(iisi)uu") != 0)
1560 g_warning ("Received DeregisterKeystrokeListener with strange signature '%s'", dbus_message_get_signature (message));
1561 return invalid_arguments_error (message);
1564 dbus_message_iter_get_basic(&iter, &path);
1565 dbus_message_iter_next(&iter);
1566 dbus_message_iter_recurse(&iter, &iter_array);
1567 while (dbus_message_iter_get_arg_type(&iter_array) != DBUS_TYPE_INVALID)
1569 Accessibility_KeyDefinition *kd = (Accessibility_KeyDefinition *)g_malloc(sizeof(Accessibility_KeyDefinition));
1572 if (!spi_dbus_message_iter_get_struct(&iter_array, DBUS_TYPE_INT32, &kd->keycode, DBUS_TYPE_INT32, &kd->keysym, DBUS_TYPE_STRING, &keystring, DBUS_TYPE_INVALID))
1576 kd->keystring = g_strdup (keystring);
1577 keys = g_slist_append(keys, kd);
1579 dbus_message_iter_next(&iter);
1580 dbus_message_iter_get_basic(&iter, &mask);
1581 dbus_message_iter_next(&iter);
1582 dbus_message_iter_get_basic(&iter, &type);
1583 dbus_message_iter_next(&iter);
1584 key_listener = spi_dec_key_listener_new (dbus_message_get_sender(message), path, keys, mask, type, NULL);
1585 #ifdef SPI_DEREGISTER_DEBUG
1586 fprintf (stderr, "deregistering keystroke listener %p with maskVal %lu\n",
1587 (void *) l, (unsigned long) mask->value);
1590 spi_deregister_controller_key_listener (controller, key_listener);
1592 spi_dec_listener_free ((DEControllerListener *) key_listener);
1593 reply = dbus_message_new_method_return (message);
1598 * DBus Accessibility::DEController::DeregisterDeviceEventListener
1599 * method implementation
1601 static DBusMessage *
1602 impl_deregister_device_event_listener (DBusConnection *bus,
1603 DBusMessage *message,
1606 SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(user_data);
1607 DEControllerListener *listener;
1609 dbus_int32_t event_types;
1610 DBusMessage *reply = NULL;
1612 if (!dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_UINT32, &event_types, DBUS_TYPE_INVALID))
1614 return invalid_arguments_error (message);
1616 listener = spi_dec_listener_new (dbus_message_get_sender(message), path, event_types);
1617 spi_controller_deregister_device_listener (
1618 controller, listener);
1619 reply = dbus_message_new_method_return (message);
1623 static DBusMessage *
1624 impl_get_keystroke_listeners (DBusConnection *bus,
1625 DBusMessage *message,
1628 SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(user_data);
1629 DBusMessageIter iter, iter_array;
1630 DBusMessage *reply = dbus_message_new_method_return (message);
1636 dbus_message_iter_init_append (reply, &iter);
1637 dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY,
1638 "(souua(iisi)u(bbb))", &iter_array);
1639 for (l = controller->key_listeners; l; l = l->next)
1641 append_keystroke_listener (&iter_array, l->data);
1643 dbus_message_iter_close_container (&iter, &iter_array);
1647 static DBusMessage *
1648 impl_get_device_event_listeners (DBusConnection *bus,
1649 DBusMessage *message,
1652 SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(user_data);
1653 DBusMessageIter iter, iter_array;
1655 DBusMessage *reply = dbus_message_new_method_return (message);
1660 dbus_message_iter_init_append (reply, &iter);
1661 dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY,
1662 "(sou)", &iter_array);
1663 for (l = controller->key_listeners; l; l = l->next)
1665 append_mouse_listener (&iter_array, l->data);
1667 dbus_message_iter_close_container (&iter, &iter_array);
1672 get_modifier_state (SpiDEController *controller)
1674 return mouse_mask_state;
1678 spi_dec_synth_keysym (SpiDEController *controller, long keysym)
1680 long key_synth_code;
1681 unsigned int modifiers, synth_mods, lock_mods;
1683 key_synth_code = spi_dec_plat_get_keycode (controller, keysym, NULL, TRUE, &synth_mods);
1685 if ((key_synth_code == 0) || (synth_mods == 0xFF)) return FALSE;
1687 /* TODO: set the modifiers accordingly! */
1688 modifiers = get_modifier_state (controller);
1689 /* side-effect; we may unset mousebutton modifiers here! */
1692 if (synth_mods != modifiers) {
1693 lock_mods = synth_mods & ~modifiers;
1694 spi_dec_plat_lock_modifiers (controller, lock_mods);
1696 spi_dec_plat_synth_keycode_press (controller, key_synth_code);
1697 spi_dec_plat_synth_keycode_release (controller, key_synth_code);
1699 if (synth_mods != modifiers)
1700 spi_dec_plat_unlock_modifiers (controller, lock_mods);
1707 * DBus Accessibility::DEController::RegisterKeystrokeListener
1708 * method implementation
1710 static DBusMessage *
1711 impl_generate_keyboard_event (DBusConnection *bus, DBusMessage *message, void *user_data)
1713 SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(user_data);
1714 dbus_int32_t keycode;
1716 dbus_uint32_t synth_type;
1717 DBusMessage *reply = NULL;
1719 if (!dbus_message_get_args(message, NULL, DBUS_TYPE_INT32, &keycode, DBUS_TYPE_STRING, &keystring, DBUS_TYPE_UINT32, &synth_type, DBUS_TYPE_INVALID))
1721 return invalid_arguments_error (message);
1725 fprintf (stderr, "synthesizing keystroke %ld, type %d\n",
1726 (long) keycode, (int) synth_type);
1728 /* TODO: hide/wrap/remove X dependency */
1731 * TODO: when initializing, query for XTest extension before using,
1732 * and fall back to XSendEvent() if XTest is not available.
1737 case Accessibility_KEY_PRESS:
1738 spi_dec_plat_synth_keycode_press (controller, keycode);
1740 case Accessibility_KEY_PRESSRELEASE:
1741 spi_dec_plat_synth_keycode_press (controller, keycode);
1742 case Accessibility_KEY_RELEASE:
1743 spi_dec_plat_synth_keycode_release (controller, keycode);
1745 case Accessibility_KEY_SYM:
1746 #ifdef SPI_XKB_DEBUG
1747 fprintf (stderr, "KeySym synthesis\n");
1750 * note: we are using long for 'keycode'
1751 * in our arg list; it can contain either
1752 * a keycode or a keysym.
1754 spi_dec_synth_keysym (controller, (KeySym) keycode);
1756 case Accessibility_KEY_STRING:
1757 if (!spi_dec_plat_synth_keystring (controller, synth_type, keycode, keystring))
1758 fprintf (stderr, "Keystring synthesis failure, string=%s\n",
1762 reply = dbus_message_new_method_return (message);
1766 /* Accessibility::DEController::GenerateMouseEvent */
1767 static DBusMessage *
1768 impl_generate_mouse_event (DBusConnection *bus, DBusMessage *message, void *user_data)
1773 DBusMessage *reply = NULL;
1775 if (!dbus_message_get_args(message, NULL, DBUS_TYPE_INT32, &x, DBUS_TYPE_INT32, &y, DBUS_TYPE_STRING, &eventName, DBUS_TYPE_INVALID))
1777 return invalid_arguments_error (message);
1781 fprintf (stderr, "generating mouse %s event at %ld, %ld\n",
1782 eventName, (long int) x, (long int) y);
1784 spi_dec_plat_generate_mouse_event (saved_controller, x, y, eventName);
1785 reply = dbus_message_new_method_return (message);
1789 /* Accessibility::DEController::NotifyListenersSync */
1790 static DBusMessage *
1791 impl_notify_listeners_sync (DBusConnection *bus, DBusMessage *message, void *user_data)
1793 SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(user_data);
1794 Accessibility_DeviceEvent event;
1796 DBusMessage *reply = NULL;
1798 if (!spi_dbus_demarshal_deviceEvent(message, &event))
1800 return invalid_arguments_error (message);
1803 g_print ("notifylistening listeners synchronously: controller %p, event id %d\n",
1804 controller, (int) event.id);
1806 ret = spi_controller_notify_keylisteners (controller,
1807 (Accessibility_DeviceEvent *)
1810 reply = dbus_message_new_method_return (message);
1813 dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &ret, DBUS_TYPE_INVALID);
1818 static DBusMessage *
1819 impl_notify_listeners_async (DBusConnection *bus, DBusMessage *message, void *user_data)
1821 SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(user_data);
1822 Accessibility_DeviceEvent event;
1823 DBusMessage *reply = NULL;
1825 if (!spi_dbus_demarshal_deviceEvent(message, &event))
1827 return invalid_arguments_error (message);
1830 g_print ("notifylistening listeners asynchronously: controller %p, event id %d\n",
1831 controller, (int) event.id);
1833 spi_controller_notify_keylisteners (controller, (Accessibility_DeviceEvent *)
1835 reply = dbus_message_new_method_return (message);
1840 spi_device_event_controller_class_init (SpiDEControllerClass *klass)
1842 GObjectClass * object_class = (GObjectClass *) klass;
1844 spi_device_event_controller_parent_class = g_type_class_peek_parent (klass);
1846 object_class->finalize = spi_device_event_controller_object_finalize;
1849 if (g_getenv ("DISPLAY"))
1850 spi_dec_setup_x11 (klass);
1853 g_type_class_add_private (object_class, sizeof (long)); /* dummy */
1857 spi_device_event_controller_init (SpiDEController *device_event_controller)
1859 SpiDEControllerClass *klass;
1860 klass = SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS (device_event_controller);
1862 /* TODO: shouldn't be gpointer below */
1863 device_event_controller->priv = G_TYPE_INSTANCE_GET_PRIVATE (device_event_controller,
1864 SPI_DEVICE_EVENT_CONTROLLER_TYPE,
1866 device_event_controller->message_queue = g_queue_new ();
1867 saved_controller = device_event_controller;
1869 if (klass->plat.init)
1870 klass->plat.init (device_event_controller);
1874 /*---------------------------------------------------------------------------*/
1876 static const char *introspection_header =
1877 "<?xml version=\"1.0\"?>\n";
1879 static const char *introspection_node_element =
1880 "<node name=\"%s\">\n";
1882 static const char *introspection_footer =
1885 static DBusMessage *
1886 impl_Introspect (DBusConnection * bus,
1887 DBusMessage * message, void *user_data)
1892 const gchar *pathstr = SPI_DBUS_PATH_DEC;
1896 output = g_string_new(introspection_header);
1898 g_string_append_printf(output, introspection_node_element, pathstr);
1900 g_string_append (output, spi_org_a11y_atspi_DeviceEventController);
1902 g_string_append(output, introspection_footer);
1903 final = g_string_free(output, FALSE);
1905 reply = dbus_message_new_method_return (message);
1906 dbus_message_append_args(reply, DBUS_TYPE_STRING, &final, DBUS_TYPE_INVALID);
1912 /*---------------------------------------------------------------------------*/
1915 handle_dec_method_from_idle (DBusConnection *bus, DBusMessage *message, void *user_data)
1917 const gchar *iface = dbus_message_get_interface (message);
1918 const gchar *member = dbus_message_get_member (message);
1919 DBusHandlerResult result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1920 DBusMessage *reply = NULL;
1922 if (!strcmp (iface, SPI_DBUS_INTERFACE_DEC))
1924 result = DBUS_HANDLER_RESULT_HANDLED;
1925 if (!strcmp (member, "RegisterKeystrokeListener"))
1926 reply = impl_register_keystroke_listener (bus, message, user_data);
1927 else if (!strcmp (member, "RegisterDeviceEventListener"))
1928 reply = impl_register_device_event_listener (bus, message, user_data);
1929 else if (!strcmp (member, "DeregisterKeystrokeListener"))
1930 reply = impl_deregister_keystroke_listener (bus, message, user_data);
1931 else if (!strcmp (member, "DeregisterDeviceEventListener"))
1932 reply = impl_deregister_device_event_listener (bus, message, user_data);
1933 else if (!strcmp (member, "GetKeystrokeListeners"))
1934 reply = impl_get_keystroke_listeners (bus, message, user_data);
1935 else if (!strcmp (member, "GetDeviceEventListeners"))
1936 reply = impl_get_device_event_listeners (bus, message, user_data);
1937 else if (!strcmp (member, "GenerateKeyboardEvent"))
1938 reply = impl_generate_keyboard_event (bus, message, user_data);
1939 else if (!strcmp (member, "GenerateMouseEvent"))
1940 reply = impl_generate_mouse_event (bus, message, user_data);
1941 else if (!strcmp (member, "NotifyListenersSync"))
1942 reply = impl_notify_listeners_sync (bus, message, user_data);
1943 else if (!strcmp (member, "NotifyListenersAsync"))
1944 reply = impl_notify_listeners_async (bus, message, user_data);
1946 result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1949 if (!strcmp (iface, "org.freedesktop.DBus.Introspectable"))
1951 result = DBUS_HANDLER_RESULT_HANDLED;
1952 if (!strcmp (member, "Introspect"))
1953 reply = impl_Introspect (bus, message, user_data);
1955 result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1958 if (result == DBUS_HANDLER_RESULT_HANDLED)
1962 reply = dbus_message_new_method_return (message);
1965 dbus_connection_send (bus, reply, NULL);
1966 dbus_message_unref (reply);
1971 message_queue_dispatch (gpointer data)
1973 saved_controller->message_queue_idle = 0;
1974 while (!g_queue_is_empty (saved_controller->message_queue))
1976 DBusMessage *message = g_queue_pop_head (saved_controller->message_queue);
1977 data = g_queue_pop_head (saved_controller->message_queue);
1978 handle_dec_method_from_idle (saved_controller->bus, message, data);
1979 dbus_message_unref (message);
1984 static DBusHandlerResult
1985 handle_dec_method (DBusConnection *bus, DBusMessage *message, void *user_data)
1987 const gchar *iface = dbus_message_get_interface (message);
1988 const gchar *member = dbus_message_get_member (message);
1989 const gint type = dbus_message_get_type (message);
1991 /* Check for basic reasons not to handle */
1992 if (type != DBUS_MESSAGE_TYPE_METHOD_CALL ||
1995 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1997 dbus_message_ref (message);
1998 g_queue_push_tail (saved_controller->message_queue, message);
1999 g_queue_push_tail (saved_controller->message_queue, user_data);
2000 if (!saved_controller->message_queue_idle) {
2001 saved_controller->message_queue_idle = g_idle_add (message_queue_dispatch, NULL);
2002 g_source_set_name_by_id (saved_controller->message_queue_idle, "[at-spi2-core] message_queue_dispatch");
2004 return DBUS_HANDLER_RESULT_HANDLED;
2007 static DBusObjectPathVTable dec_vtable =
2011 NULL, NULL, NULL, NULL
2015 spi_registry_dec_new (SpiRegistry *reg, DBusConnection *bus)
2017 SpiDEController *dec = g_object_new (SPI_DEVICE_EVENT_CONTROLLER_TYPE, NULL);
2019 dec->registry = g_object_ref (reg);
2020 reg->dec = g_object_ref (dec);
2023 dbus_connection_register_object_path (bus, SPI_DBUS_PATH_DEC, &dec_vtable, dec);
2029 spi_device_event_controller_start_poll_mouse (SpiRegistry *registry)
2031 if (!have_mouse_event_listener)
2033 have_mouse_event_listener = TRUE;
2034 if (!have_mouse_listener) {
2036 id = g_timeout_add (100, spi_dec_poll_mouse_idle, registry->dec);
2037 g_source_set_name_by_id (id, "[at-spi2-core] spi_dec_poll_mouse_idle");
2043 spi_device_event_controller_stop_poll_mouse (void)
2045 have_mouse_event_listener = FALSE;