From 9c85b622b335c319078629dd7b8ccbed04044f91 Mon Sep 17 00:00:00 2001 From: billh Date: Wed, 26 Jun 2002 18:55:11 +0000 Subject: [PATCH] Added notification of mouse button events, for instance register for events of type "mouse:button" or "mouse:button:1p" for button-1-press events only. git-svn-id: http://svn.gnome.org/svn/at-spi/trunk@327 e2bd861d-eb25-0410-b326-f6ed22b6b98c --- ChangeLog | 27 ++++++++ registryd/deviceeventcontroller.c | 138 +++++++++++++++++++++++++++++++++++--- test/event-listener-test.c | 2 + 3 files changed, 159 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index 71ca1b1..450abf5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,32 @@ 2002-06-25 Bill Haneman + * registryd/deviceeventcontroller.c: fix for 84261 + (spi_dec_mouse_moved): + Added test of mouse button mask, so that we can detect mouse + button release. Unfortunately we can't otherwise detect mouse + button release events without consuming the mouse press event, + because of the way XGrabButton works. This means that our mouse + release events have a latency dependent on the polling period + while the mouse button is down. At least in this case we only + have to poll while the button is down, and not at other times. + If the button masks don't match with what the last press event + reported, we report the appropriate button release event. + (spi_dec_ungrab_mouse): + New method (not yet called). + (spi_device_event_controller_forward_mouse_event): + New method, sends mouse press event from GdkFilter. + (spi_dec_init_mouse_listener): + Added code to call XGrabButton, redirecting mouse button events to + the root window and our Gdk event loop. + (global_filter_fn): + Added code to filter mouse button events, and reordered. + + * test/event-listener-test.c: + (main): + Added registration for mouse events of type "mouse:button". + +2002-06-25 Bill Haneman + * registryd/deviceeventcontroller.c: partial fix for 84261 (spi_dec_poll_mouse_idle): New method, a timeout which checks to see if the mouse diff --git a/registryd/deviceeventcontroller.c b/registryd/deviceeventcontroller.c index d843209..6009c05 100644 --- a/registryd/deviceeventcontroller.c +++ b/registryd/deviceeventcontroller.c @@ -50,7 +50,10 @@ /* 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 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); @@ -156,6 +159,7 @@ spi_dec_poll_mouse_moved (gpointer data) 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); @@ -170,11 +174,48 @@ spi_dec_poll_mouse_moved (gpointer data) &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), @@ -209,10 +250,35 @@ spi_dec_poll_mouse_moving (gpointer data) } } +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 * @@ -422,22 +488,78 @@ spi_controller_register_device_listener (SpiDEController *controller, 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; } diff --git a/test/event-listener-test.c b/test/event-listener-test.c index eb665c7..bed7264 100644 --- a/test/event-listener-test.c +++ b/test/event-listener-test.c @@ -61,6 +61,8 @@ main (int argc, char **argv) SPI_registerGlobalEventListener (specific_listener, "mouse:rel"); SPI_registerGlobalEventListener (specific_listener, + "mouse:button"); + SPI_registerGlobalEventListener (specific_listener, "mouse:abs"); SPI_registerGlobalEventListener (generic_listener, "object:property-change"); -- 2.7.4