- }
- }
-
-#ifdef SPI_KEYEVENT_DEBUG
- if (!found)
- {
- g_print ("no match for event\n");
- }
-#endif
-
- is_consumed = FALSE;
- for (l2 = notify; l2 && !is_consumed; l2 = l2->next)
- {
- DEControllerListener *listener = l2->data;
-
- 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;
- spi_listener_clone_free (listener);
- /* clone doesn't have its own ref, so don't use spi_device_listener_free */
- }
-
- g_slist_free (notify);
-
-#ifdef SPI_DEBUG
- if (is_consumed) g_message ("consumed\n");
-#endif
- return is_consumed;
-}
-
-static void
-spi_device_event_controller_forward_mouse_event (SpiDEController *controller,
- XEvent *xevent)
-{
- Accessibility_DeviceEvent mouse_e;
- gchar event_name[24];
- gboolean is_consumed = FALSE;
- gboolean xkb_mod_unlatch_occurred;
- XButtonEvent *xbutton_event = (XButtonEvent *) xevent;
- dbus_uint32_t ix, iy;
-
- int button = xbutton_event->button;
-
- unsigned int mouse_button_state = xbutton_event->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",
- xbutton_event->button,
- (xevent->type == ButtonPress) ? "Press" : "Release",
- mouse_button_state);
-#endif
- snprintf (event_name, 22, "mouse:button_%d%c", button,
- (xevent->type == ButtonPress) ? 'p' : 'r');
-
- /* TODO: FIXME distinguish between physical and logical buttons */
- mouse_e.type = (xevent->type == ButtonPress) ?
- Accessibility_BUTTON_PRESSED_EVENT :
- Accessibility_BUTTON_RELEASED_EVENT;
- mouse_e.id = button;
- mouse_e.hw_code = button;
- mouse_e.modifiers = (dbus_uint16_t) xbutton_event->state;
- mouse_e.timestamp = (dbus_uint32_t) xbutton_event->time;
- mouse_e.event_string = "";
- mouse_e.is_text = FALSE;
- if ((mouse_button_state & mouse_button_mask) !=
- (mouse_mask_state & mouse_button_mask))
- {
- if ((mouse_mask_state & key_modifier_mask) !=
- (mouse_button_state & key_modifier_mask))
- spi_dec_emit_modifier_event (controller,
- mouse_mask_state, mouse_button_state);
- mouse_mask_state = mouse_button_state;
- is_consumed =
- 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);
- }
-
- xkb_mod_unlatch_occurred = (xevent->type == ButtonPress ||
- xevent->type == ButtonRelease);
-
- /* if client wants to consume this event, and XKB latch state was
- * unset by this button event, we reset it
- */
- if (is_consumed && xkb_mod_unlatch_occurred)
- spi_dec_set_unlatch_pending (controller, mouse_mask_state);
-
- XAllowEvents (spi_get_display (),
- (is_consumed) ? SyncPointer : ReplayPointer,
- CurrentTime);
-}
-
-static GdkFilterReturn
-global_filter_fn (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data)
-{
- XEvent *xevent = gdk_xevent;
- SpiDEController *controller;
- DEControllerPrivateData *priv;
- Display *display = spi_get_display ();
- controller = SPI_DEVICE_EVENT_CONTROLLER (data);
- priv = (DEControllerPrivateData *)
- g_object_get_qdata (G_OBJECT (controller), spi_dec_private_quark);
-
- if (xevent->type == MappingNotify)
- xmkeymap = NULL;
-
- if (xevent->type == KeyPress || xevent->type == KeyRelease)
- {
- if (controller->xevie_display == NULL)
- {
- gboolean is_consumed;
-
- is_consumed =
- spi_device_event_controller_forward_key_event (controller, xevent);
-
- if (is_consumed)
- {
- int n_events;
- int i;
- XEvent next_event;
- n_events = XPending (display);
-
-#ifdef SPI_KEYEVENT_DEBUG
- g_print ("Number of events pending: %d\n", n_events);
-#endif
- for (i = 0; i < n_events; i++)
- {
- XNextEvent (display, &next_event);
- if (next_event.type != KeyPress &&
- next_event.type != KeyRelease)
- g_warning ("Unexpected event type %d in queue", next_event.type);
- }
-
- XAllowEvents (display, AsyncKeyboard, CurrentTime);
- if (n_events)
- XUngrabKeyboard (display, CurrentTime);
- }
- else
- {
- if (xevent->type == KeyPress)
- wait_for_release_event (xevent, controller);
- XAllowEvents (display, ReplayKeyboard, CurrentTime);
- }
- }
-
- return GDK_FILTER_CONTINUE;
- }
- if (xevent->type == ButtonPress || xevent->type == ButtonRelease)
- {
- spi_device_event_controller_forward_mouse_event (controller, xevent);
- }
- if (xevent->type == priv->xkb_base_event_code)
- {
- XkbAnyEvent * xkb_ev = (XkbAnyEvent *) xevent;
- /* ugly but probably necessary...*/
- XSynchronize (display, TRUE);
-
- if (xkb_ev->xkb_type == XkbStateNotify)
- {
- XkbStateNotifyEvent *xkb_snev =
- (XkbStateNotifyEvent *) xkb_ev;
- /* check the mouse, to catch mouse events grabbed by
- * another client; in case we should revert this XKB delatch
- */
- if (!priv->pending_xkb_mod_relatch_mask)
- {
- int x, y;
- gboolean moved;
- spi_dec_mouse_check (controller, &x, &y, &moved);
- }
- /* we check again, since the previous call may have
- changed this flag */
- if (priv->pending_xkb_mod_relatch_mask)
- {
- unsigned int feedback_mask;
-#ifdef SPI_XKB_DEBUG
- fprintf (stderr, "relatching %x\n",
- priv->pending_xkb_mod_relatch_mask);
-#endif
- /* temporarily turn off the latch bell, if it's on */
- XkbGetControls (display,
- XkbAccessXFeedbackMask,
- priv->xkb_desc);
- feedback_mask = priv->xkb_desc->ctrls->ax_options;
- if (feedback_mask & XkbAX_StickyKeysFBMask)
- {
- XkbControlsChangesRec changes = {XkbAccessXFeedbackMask,
- 0, False};
- priv->xkb_desc->ctrls->ax_options
- &= ~(XkbAX_StickyKeysFBMask);
- XkbChangeControls (display, priv->xkb_desc, &changes);
- }
- /* TODO: account for lock as well as latch */
- XkbLatchModifiers (display,
- XkbUseCoreKbd,
- priv->pending_xkb_mod_relatch_mask,
- priv->pending_xkb_mod_relatch_mask);
- if (feedback_mask & XkbAX_StickyKeysFBMask)
- {
- XkbControlsChangesRec changes = {XkbAccessXFeedbackMask,
- 0, False};
- priv->xkb_desc->ctrls->ax_options = feedback_mask;
- XkbChangeControls (display, priv->xkb_desc, &changes);
- }
-#ifdef SPI_XKB_DEBUG
- fprintf (stderr, "relatched %x\n",
- priv->pending_xkb_mod_relatch_mask);
-#endif
- priv->pending_xkb_mod_relatch_mask = 0;
- }
- else
- {
- 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;
-}
-
-static int
-_spi_controller_device_error_handler (Display *display, XErrorEvent *error)
-{
- if (error->error_code == BadAccess)
- {
- g_message ("Could not complete key grab: grab already in use.\n");
- spi_error_code = BadAccess;
- return 0;