* Boston, MA 02111-1307, USA.
*/
-/* deviceeventcontroler.c: implement the DeviceEventController interface */
+/* deviceeventcontroller.c: implement the DeviceEventController interface */
#include <config.h>
/* A pointer to our parent object class */
static GObjectClass *spi_device_event_controller_parent_class;
static int spi_error_code = 0;
+static GdkPoint *last_mouse_pos = NULL;
+static unsigned int mouse_button_state = 0;
+static unsigned int mouse_button_mask =
+ Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask;
int (*x_default_error_handler) (Display *display, XErrorEvent *error_event);
CORBA_Environment *ev);
static void spi_device_event_controller_forward_key_event (SpiDEController *controller,
const XEvent *event);
+static void spi_deregister_controller_key_listener (SpiDEController *controller,
+ DEControllerKeyListener *key_listener,
+ CORBA_Environment *ev);
+
static gboolean spi_clear_error_state (void);
+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()
}
}
+static gboolean
+spi_dec_poll_mouse_moved (gpointer data)
+{
+ SpiRegistry *registry = SPI_REGISTRY (data);
+ CORBA_Environment ev;
+ Accessibility_Event e;
+ Window root_return, child_return;
+ int win_x_return,win_y_return;
+ int x, y;
+ unsigned int mask_return;
+ gchar event_name[24];
+ Display *display = spi_get_display ();
+ if (last_mouse_pos == NULL) {
+ last_mouse_pos = g_new0 (GdkPoint, 1);
+ last_mouse_pos->x = 0;
+ last_mouse_pos->y = 0;
+ e.type = g_strdup ("mouse:abs");
+ } else {
+ e.type = g_strdup ("mouse:rel");
+ }
+ if (display != NULL)
+ XQueryPointer(display, DefaultRootWindow (display),
+ &root_return, &child_return,
+ &x, &y,
+ &win_x_return, &win_y_return, &mask_return);
+ if ((mask_return & mouse_button_mask) != mouse_button_state) {
+ int button_number = 0;
+ if (!(mask_return & Button1Mask) &&
+ (mouse_button_state & Button1Mask)) {
+ button_number = 1;
+ } else if (!(mask_return & Button2Mask) &&
+ (mouse_button_state & Button2Mask)) {
+ button_number = 2;
+ } else if (!(mask_return & Button3Mask) &&
+ (mouse_button_state & Button3Mask)) {
+ button_number = 3;
+ } else if (!(mask_return & Button4Mask) &&
+ (mouse_button_state & Button1Mask)) {
+ button_number = 4;
+ } else if (!(mask_return & Button5Mask) &&
+ (mouse_button_state & Button5Mask)) {
+ button_number = 5;
+ }
+ if (button_number) {
+#ifdef SPI_DEBUG
+ fprintf (stderr, "Button %d Released\n",
+ button_number);
+#endif
+ snprintf (event_name, 22, "mouse:button:%dr", button_number);
+ e.type = CORBA_string_dup (event_name);
+ e.source = BONOBO_OBJREF (registry->desktop);
+ e.detail1 = last_mouse_pos->x;
+ e.detail2 = last_mouse_pos->y;
+ CORBA_exception_init (&ev);
+ Accessibility_Registry_notifyEvent (BONOBO_OBJREF (registry),
+ &e,
+ &ev);
+ }
+ mouse_button_state = mask_return & mouse_button_mask;
+ }
+ if (x != last_mouse_pos->x || y != last_mouse_pos->y) {
+ e.source = BONOBO_OBJREF (registry->desktop);
+ e.detail1 = x - last_mouse_pos->x;
+ e.detail2 = y - last_mouse_pos->y;
+ CORBA_exception_init (&ev);
+ if (last_mouse_pos == NULL)
+ last_mouse_pos = g_new0 (GdkPoint, 1);
+ last_mouse_pos->x = x;
+ last_mouse_pos->y = y;
+ Accessibility_Registry_notifyEvent (BONOBO_OBJREF (registry),
+ &e,
+ &ev);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static gboolean
+spi_dec_poll_mouse_idle (gpointer data)
+{
+ if (! spi_dec_poll_mouse_moved (data))
+ return TRUE;
+ else
+ {
+ g_timeout_add (20, spi_dec_poll_mouse_moving, data);
+ return FALSE;
+ }
+}
+
+static gboolean
+spi_dec_poll_mouse_moving (gpointer data)
+{
+ if (spi_dec_poll_mouse_moved (data))
+ return TRUE;
+ else
+ {
+ g_timeout_add (100, spi_dec_poll_mouse_idle, data);
+ return FALSE;
+ }
+}
+
+static int
+spi_dec_ungrab_mouse (gpointer data)
+{
+ Display *display = spi_get_display ();
+ fprintf (stderr, "mouse ungrab : display = %p\n", display);
+ if (display)
+ {
+ XUngrabButton (spi_get_display (), AnyButton, AnyModifier,
+ XDefaultRootWindow (spi_get_display ()));
+ fprintf (stderr, "mouse grab released\n");
+ }
+ return FALSE;
+}
+
+static void
+spi_dec_init_mouse_listener (SpiRegistry *registry)
+{
+ Display *display = spi_get_display ();
+ g_timeout_add (100, spi_dec_poll_mouse_idle, registry);
+
+ if (display)
+ {
+ XGrabButton (display, AnyButton, 0,
+ gdk_x11_get_default_root_xwindow (),
+ True, ButtonPressMask | ButtonReleaseMask,
+ GrabModeSync, GrabModeAsync, None, None);
+ XSync (display, False);
+ fprintf (stderr, "mouse buttons grabbed\n");
+ }
+}
+
static DEControllerKeyListener *
spi_dec_key_listener_new (CORBA_Object l,
const Accessibility_KeySet *keys,
return key_listener;
}
+static DEControllerKeyListener *
+spi_key_listener_clone (DEControllerKeyListener *key_listener, CORBA_Environment *ev)
+{
+ DEControllerKeyListener *clone = g_new0 (DEControllerKeyListener, 1);
+ clone->listener.object =
+ CORBA_Object_duplicate (key_listener->listener.object, ev);
+ clone->listener.type = SPI_DEVICE_TYPE_KBD;
+ clone->keys = ORBit_copy_value (key_listener->keys, TC_Accessibility_KeySet);
+ clone->mask = key_listener->mask;
+ clone->typeseq = ORBit_copy_value (key_listener->typeseq, TC_Accessibility_KeyEventTypeSeq);
+ if (key_listener->mode)
+ clone->mode = ORBit_copy_value (key_listener->mode, TC_Accessibility_EventListenerMode);
+ else
+ clone->mode = NULL;
+ return clone;
+}
+
static void
-spi_dec_key_listener_free (DEControllerKeyListener *key_listener,
- CORBA_Environment *ev)
+spi_key_listener_data_free (DEControllerKeyListener *key_listener, CORBA_Environment *ev)
{
- bonobo_object_release_unref (key_listener->listener.object, ev);
CORBA_free (key_listener->typeseq);
CORBA_free (key_listener->keys);
g_free (key_listener);
}
static void
+spi_key_listener_clone_free (DEControllerKeyListener *clone, CORBA_Environment *ev)
+{
+ CORBA_Object_release (clone->listener.object, ev);
+ spi_key_listener_data_free (clone, ev);
+}
+
+static void
+spi_dec_key_listener_free (DEControllerKeyListener *key_listener,
+ CORBA_Environment *ev)
+{
+ bonobo_object_release_unref (key_listener->listener.object, ev);
+ spi_key_listener_data_free (key_listener, ev);
+}
+
+static void
_register_keygrab (SpiDEController *controller,
DEControllerGrabMask *grab_mask)
{
return FALSE;
}
+static void
+spi_device_event_controller_forward_mouse_event (SpiDEController *controller,
+ XEvent *xevent)
+{
+ Accessibility_Event e;
+ CORBA_Environment ev;
+ gchar event_name[24];
+ int button = ((XButtonEvent *) xevent)->button;
+
+ mouse_button_state = ((XButtonEvent *) xevent)->state;
+
+ switch (button)
+ {
+ case 1:
+ mouse_button_state |= Button1Mask;
+ break;
+ case 2:
+ mouse_button_state |= Button2Mask;
+ break;
+ case 3:
+ mouse_button_state |= Button3Mask;
+ break;
+ case 4:
+ mouse_button_state |= Button4Mask;
+ break;
+ case 5:
+ mouse_button_state |= Button5Mask;
+ break;
+ }
+ last_mouse_pos->x = ((XButtonEvent *) xevent)->x_root;
+ last_mouse_pos->y = ((XButtonEvent *) xevent)->y_root;
+
+#ifdef SPI_DEBUG
+ fprintf (stderr, "mouse button %d %s (%x)\n",
+ ((XButtonEvent *) xevent)->button,
+ (xevent->type == ButtonPress) ? "Press" : "Release",
+ mouse_button_state);
+#endif
+ snprintf (event_name, 22, "mouse:button:%d%c", button,
+ (xevent->type == ButtonPress) ? 'p' : 'r');
+
+ e.type = CORBA_string_dup (event_name);
+ e.source = BONOBO_OBJREF (controller->registry->desktop);
+ e.detail1 = last_mouse_pos->x;
+ e.detail2 = last_mouse_pos->y;
+ CORBA_exception_init (&ev);
+ Accessibility_Registry_notifyEvent (BONOBO_OBJREF (controller->registry),
+ &e,
+ &ev);
+
+ XAllowEvents (spi_get_display (), ReplayPointer, CurrentTime);
+}
+
static GdkFilterReturn
global_filter_fn (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data)
{
XEvent *xevent = gdk_xevent;
SpiDEController *controller;
- if (xevent->type != KeyPress && xevent->type != KeyRelease)
+ if (xevent->type == KeyPress && xevent->type == KeyRelease)
{
+ controller = SPI_DEVICE_EVENT_CONTROLLER (data);
+ spi_device_event_controller_forward_key_event (controller, xevent);
+ /* FIXME: is this right ? */
return GDK_FILTER_CONTINUE;
}
-
- controller = SPI_DEVICE_EVENT_CONTROLLER (data);
-
- spi_device_event_controller_forward_key_event (controller, xevent);
-
- /* FIXME: is this right ? */
+ if (xevent->type == ButtonPress || xevent->type == ButtonRelease)
+ {
+ controller = SPI_DEVICE_EVENT_CONTROLLER (data);
+ spi_device_event_controller_forward_mouse_event (controller, xevent);
+ }
+
return GDK_FILTER_CONTINUE;
}
}
static gboolean
-spi_notify_keylisteners (GList **key_listeners,
- const Accessibility_DeviceEvent *key_event,
- CORBA_boolean is_system_global,
- CORBA_Environment *ev)
+spi_controller_notify_keylisteners (SpiDEController *controller,
+ const Accessibility_DeviceEvent *key_event,
+ CORBA_boolean is_system_global,
+ CORBA_Environment *ev)
{
GList *l;
GSList *notify = NULL, *l2;
+ GList **key_listeners = &controller->key_listeners;
gboolean is_consumed;
if (!key_listeners)
if (ls != CORBA_OBJECT_NIL)
{
- notify = g_slist_prepend (notify, CORBA_Object_duplicate (ls, ev));
+ /* we clone (don't dup) the listener, to avoid refcount inc. */
+ notify = g_slist_prepend (notify,
+ spi_key_listener_clone (key_listener, ev));
}
}
}
is_consumed = FALSE;
for (l2 = notify; l2 && !is_consumed; l2 = l2->next)
{
- Accessibility_DeviceEventListener ls = l2->data;
+ DEControllerKeyListener *key_listener = l2->data;
+ Accessibility_DeviceEventListener ls = key_listener->listener.object;
is_consumed = Accessibility_DeviceEventListener_notifyEvent (ls, key_event, ev);
if (BONOBO_EX (ev))
{
is_consumed = FALSE;
+ spi_deregister_controller_key_listener (controller, key_listener,
+ ev);
CORBA_exception_free (ev);
}
for (; l2; l2 = l2->next)
{
- CORBA_Object_release (l2->data, ev);
+ DEControllerKeyListener *key_listener = l2->data;
+ spi_key_listener_clone_free (key_listener, ev);
+ /* clone doesn't have its own ref, so don't use spi_key_listener_free */
}
g_slist_free (notify);
return SPI_RE_ENTRANT_CONTINUE;
}
+
+static void
+spi_deregister_controller_key_listener (SpiDEController *controller,
+ DEControllerKeyListener *key_listener,
+ CORBA_Environment *ev)
+{
+ RemoveKeyListenerClosure ctx;
+
+ ctx.ev = ev;
+ ctx.key_listener = key_listener;
+
+ /* special case, copy keyset from existing controller list entry */
+ if (key_listener->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);
+
+}
+
/*
* CORBA Accessibility::DEController::deregisterKeystrokeListener
* method implementation
CORBA_Environment *ev)
{
DEControllerKeyListener *key_listener;
- RemoveKeyListenerClosure ctx;
SpiDEController *controller;
controller = SPI_DEVICE_EVENT_CONTROLLER (bonobo_object (servant));
(void *) l, (unsigned long) mask->value);
#endif
- ctx.ev = ev;
- ctx.key_listener = key_listener;
-
- /* 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_deregister_controller_key_listener (controller, key_listener, ev);
spi_dec_key_listener_free (key_listener, ev);
}
g_print ("notifylistening listeners synchronously: controller %p, event id %d\n",
controller, (int) event->id);
#endif
- return spi_notify_keylisteners (&controller->key_listeners, event, CORBA_FALSE, ev) ?
+ return spi_controller_notify_keylisteners (controller, event, CORBA_FALSE, ev) ?
CORBA_TRUE : CORBA_FALSE;
}
#ifdef SPI_DEBUG
fprintf (stderr, "notifying listeners asynchronously\n");
#endif
- spi_notify_keylisteners (&controller->key_listeners, event, CORBA_FALSE, ev);
+ spi_controller_notify_keylisteners (controller, event, CORBA_FALSE, ev);
}
static void
spi_controller_update_key_grabs (controller, &key_event);
/* relay to listeners, and decide whether to consume it or not */
- is_consumed = spi_notify_keylisteners (
- &controller->key_listeners, &key_event, CORBA_TRUE, &ev);
+ is_consumed = spi_controller_notify_keylisteners (
+ controller, &key_event, CORBA_TRUE, &ev);
CORBA_exception_free (&ev);
retval->registry = SPI_REGISTRY (bonobo_object_ref (
BONOBO_OBJECT (registry)));
+ spi_dec_init_mouse_listener (registry);
+ /* TODO: kill mouse listener on finalize */
+
return retval;
}