-static void
-spi_device_event_controller_forward_mouse_event (SpiDEController *controller,
- XEvent *xevent)
-{
- Accessibility_DeviceEvent mouse_e;
- gchar event_detail[3];
- 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_detail, 3, "%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, SPI_DBUS_INTERFACE_EVENT_MOUSE, "Button", event_detail, ix, iy);
- }
-
- 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 void
-global_filter_fn (XEvent *xevent, void *data)
-{
- 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;
- }
- 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;
- }
- }
- XSynchronize (display, FALSE);
- }
-
- return;
-}
-
-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;
- }
- else
- {
- return (*x_default_error_handler) (display, error);
- }
-}
-
-static void
-spi_controller_register_with_devices (SpiDEController *controller)
-{
- 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 */
- /* register with: (translated) keystroke handler */
-
- priv->have_xkb = XkbQueryExtension (spi_get_display (),
- &priv->xkb_major_extension_opcode,
- &priv->xkb_base_event_code,
- &priv->xkb_base_error_code, NULL, NULL);
- if (priv->have_xkb)
- {
- gint i;
- guint64 reserved = 0;
- priv->xkb_desc = XkbGetMap (spi_get_display (), XkbKeySymsMask, XkbUseCoreKbd);
- XkbSelectEvents (spi_get_display (),
- XkbUseCoreKbd,
- XkbStateNotifyMask, XkbStateNotifyMask);
- _numlock_physical_mask = XkbKeysymToModifiers (spi_get_display (),
- XK_Num_Lock);
- for (i = priv->xkb_desc->max_key_code; i >= priv->xkb_desc->min_key_code; --i)
- {
- if (priv->xkb_desc->map->key_sym_map[i].kt_index[0] == XkbOneLevelIndex)
- {
- if (XKeycodeToKeysym (spi_get_display (), i, 0) != 0)
- {
- /* don't use this one if there's a grab client! */
-
- /* 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,
- spi_get_root_window (),
- TRUE,
- GrabModeSync, GrabModeSync);
- XSync (spi_get_display (), TRUE);
- XUngrabKey (spi_get_display (), i, 0,
- spi_get_root_window ());
- if (!spi_x_error_release ())
- {
- reserved = i;
- break;
- }
- }
- }
- }
- if (reserved)
- {
- priv->reserved_keycode = reserved;
- priv->reserved_keysym = XKeycodeToKeysym (spi_get_display (), reserved, 0);
- }
- else
- {
- priv->reserved_keycode = XKeysymToKeycode (spi_get_display (), XK_numbersign);
- priv->reserved_keysym = XK_numbersign;
- }
-#ifdef SPI_RESERVED_DEBUG
- unsigned sym = 0;
- sym = XKeycodeToKeysym (spi_get_display (), reserved, 0);
- fprintf (stderr, "%x\n", sym);
- fprintf (stderr, "setting the reserved keycode to %d (%s)\n",
- reserved,
- XKeysymToString (XKeycodeToKeysym (spi_get_display (),
- reserved, 0)));
-#endif
- }
-
- spi_set_filter (global_filter_fn, controller);
- spi_set_events (KeyPressMask | KeyReleaseMask);
-
- x_default_error_handler = XSetErrorHandler (_spi_controller_device_error_handler);
-}
-