+ if ((mask_return & mouse_button_mask) !=
+ (mouse_mask_state & mouse_button_mask))
+ {
+ int button_number = 0;
+ gboolean is_down = False;
+
+ if (!(mask_return & Button1Mask) &&
+ (mouse_mask_state & Button1Mask))
+ {
+ mouse_mask_state &= ~Button1Mask;
+ button_number = 1;
+ }
+ else if ((mask_return & Button1Mask) &&
+ !(mouse_mask_state & Button1Mask))
+ {
+ mouse_mask_state |= Button1Mask;
+ button_number = 1;
+ is_down = True;
+ }
+ else if (!(mask_return & Button2Mask) &&
+ (mouse_mask_state & Button2Mask))
+ {
+ mouse_mask_state &= ~Button2Mask;
+ button_number = 2;
+ }
+ else if ((mask_return & Button2Mask) &&
+ !(mouse_mask_state & Button2Mask))
+ {
+ mouse_mask_state |= Button2Mask;
+ button_number = 2;
+ is_down = True;
+ }
+ else if (!(mask_return & Button3Mask) &&
+ (mouse_mask_state & Button3Mask))
+ {
+ mouse_mask_state &= ~Button3Mask;
+ button_number = 3;
+ }
+ else if ((mask_return & Button3Mask) &&
+ !(mouse_mask_state & Button3Mask))
+ {
+ mouse_mask_state |= Button3Mask;
+ button_number = 3;
+ is_down = True;
+ }
+ else if (!(mask_return & Button4Mask) &&
+ (mouse_mask_state & Button4Mask))
+ {
+ mouse_mask_state &= ~Button4Mask;
+ button_number = 4;
+ }
+ else if ((mask_return & Button4Mask) &&
+ !(mouse_mask_state & Button4Mask))
+ {
+ mouse_mask_state |= Button4Mask;
+ button_number = 4;
+ is_down = True;
+ }
+ else if (!(mask_return & Button5Mask) &&
+ (mouse_mask_state & Button5Mask))
+ {
+ mouse_mask_state &= ~Button5Mask;
+ button_number = 5;
+ }
+ else if ((mask_return & Button5Mask) &&
+ !(mouse_mask_state & Button5Mask))
+ {
+ mouse_mask_state |= Button5Mask;
+ button_number = 5;
+ is_down = True;
+ }
+ if (button_number) {
+#ifdef SPI_DEBUG
+ fprintf (stderr, "Button %d %s\n",
+ button_number, (is_down) ? "Pressed" : "Released");
+#endif
+ snprintf (event_name, 22, "mouse:button:%d%c", button_number,
+ (is_down) ? 'p' : 'r');
+ /* TODO: distinguish between physical and
+ * logical buttons
+ */
+ mouse_e.type = (is_down) ?
+ Accessibility_BUTTON_PRESSED_EVENT :
+ Accessibility_BUTTON_RELEASED_EVENT;
+ mouse_e.id = button_number;
+ mouse_e.hw_code = button_number;
+ mouse_e.modifiers = (CORBA_unsigned_short) mouse_mask_state;
+ mouse_e.timestamp = 0;
+ mouse_e.event_string = "";
+ mouse_e.is_text = CORBA_FALSE;
+ is_consumed =
+ spi_controller_notify_mouselisteners (controller,
+ &mouse_e,
+ &ev);
+ e.type = event_name;
+ e.source = BONOBO_OBJREF (controller->registry->desktop);
+ e.detail1 = last_mouse_pos->x;
+ e.detail2 = last_mouse_pos->y;
+ spi_init_any_nil (&e.any_data);
+ CORBA_exception_init (&ev);
+ if (!is_consumed)
+ {
+ Accessibility_Registry_notifyEvent (BONOBO_OBJREF (controller->registry),
+ &e,
+ &ev);
+ }
+ else
+ spi_dec_set_unlatch_pending (controller, mask_return);
+ }
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+
+static guint
+spi_dec_mouse_check (SpiDEController *controller,
+ int *x, int *y, gboolean *moved)
+{
+ Accessibility_Event e;
+ CORBA_Environment ev;
+ int win_x_return,win_y_return;
+ unsigned int mask_return;
+ Window root_return, child_return;
+ Display *display = spi_get_display ();
+
+ if (display != NULL)
+ XQueryPointer(display, DefaultRootWindow (display),
+ &root_return, &child_return,
+ x, y,
+ &win_x_return, &win_y_return, &mask_return);
+ /*
+ * Since many clients grab the pointer, and X goes an automatic
+ * pointer grab on mouse-down, we often must detect mouse button events
+ * by polling rather than via a button grab.
+ * The while loop (rather than if) is used since it's possible that
+ * multiple buttons have changed state since we last checked.
+ */
+ if (mask_return != mouse_mask_state)
+ {
+ while (spi_dec_button_update_and_emit (controller, mask_return));
+ }
+
+ if (*x != last_mouse_pos->x || *y != last_mouse_pos->y)
+ {
+ e.type = "mouse:abs";
+ e.source = BONOBO_OBJREF (controller->registry->desktop);
+ e.detail1 = *x;
+ e.detail2 = *y;
+ spi_init_any_nil (&e.any_data);
+ CORBA_exception_init (&ev);
+ Accessibility_Registry_notifyEvent (BONOBO_OBJREF (controller->registry),
+ &e,
+ &ev);
+ e.type = "mouse:rel";
+ e.source = BONOBO_OBJREF (controller->registry->desktop);
+ e.detail1 = *x - last_mouse_pos->x;
+ e.detail2 = *y - last_mouse_pos->y;
+ spi_init_any_nil (&e.any_data);
+ CORBA_exception_init (&ev);
+ last_mouse_pos->x = *x;
+ last_mouse_pos->y = *y;
+ Accessibility_Registry_notifyEvent (BONOBO_OBJREF (controller->registry),
+ &e,
+ &ev);
+ *moved = True;
+ }
+ else
+ {
+ *moved = False;
+ }
+
+ return mask_return;
+}
+
+static void
+spi_dec_emit_modifier_event (SpiDEController *controller, guint prev_mask,
+ guint current_mask)
+{
+ Accessibility_Event e;
+ CORBA_Environment ev;
+
+#ifdef SPI_XKB_DEBUG
+ fprintf (stderr, "MODIFIER CHANGE EVENT! %x to %x\n",
+ prev_mask, current_mask);
+#endif
+ e.type = "keyboard:modifiers";
+ e.source = BONOBO_OBJREF (controller->registry->desktop);
+ e.detail1 = prev_mask & key_modifier_mask;
+ e.detail2 = current_mask & key_modifier_mask;
+ spi_init_any_nil (&e.any_data);
+ CORBA_exception_init (&ev);
+ Accessibility_Registry_notifyEvent (BONOBO_OBJREF (controller->registry),
+ &e,
+ &ev);
+}
+
+static gboolean
+spi_dec_poll_mouse_moved (gpointer data)
+{
+ SpiRegistry *registry = SPI_REGISTRY (data);
+ SpiDEController *controller = registry->de_controller;
+ 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))
+ {
+ spi_dec_emit_modifier_event (controller, mouse_mask_state, mask_return);
+ mouse_mask_state = mask_return;
+ }
+
+ return moved;
+}
+
+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 ();
+ if (display)
+ {
+ XUngrabButton (spi_get_display (), AnyButton, AnyModifier,
+ XDefaultRootWindow (spi_get_display ()));
+ }
+ 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, AnyModifier,
+ gdk_x11_get_default_root_xwindow (),
+ True, ButtonPressMask | ButtonReleaseMask,
+ GrabModeSync, GrabModeAsync, None, None);
+ XSync (display, False);