From 210e1cfe72d147251941eaa4c789970c51f12960 Mon Sep 17 00:00:00 2001 From: billh Date: Sun, 24 Nov 2002 14:49:51 +0000 Subject: [PATCH] Updated NEWS; fixed bug causing multiple event emission if registry dies and is restarted; workaround for GOK bug 98420. git-svn-id: http://svn.gnome.org/svn/at-spi/trunk@372 e2bd861d-eb25-0410-b326-f6ed22b6b98c --- ChangeLog | 28 ++++ NEWS | 38 ++++- atk-bridge/bridge.c | 8 +- registryd/deviceeventcontroller.c | 289 +++++++++++++++++++++++--------------- 4 files changed, 251 insertions(+), 112 deletions(-) diff --git a/ChangeLog b/ChangeLog index 860fcbc..d792845 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,31 @@ +2002-11-24 Bill Haneman + + * NEWS: + Updated NEWS (accidentally didn't make it into 1.1.5 tarball, + retagged). + + * atk-bridge/bridge.c: + (spi_atk_register_event_listeners): + Don't re-register for ATK events if the registry has died + and the app needs to re-register; the ATK listeners are in + process and doing so will cause duplicate emission. + + * registryd/deviceeventcontroller.c: + (spi_poll_mouse_moved): + Reformat the source, detect and emit multiple button-change + events (i.e. if multiple buttons have changed between poll + intervals). + Add code to detect mouse-down events even when the pointer + is grabbed; workaround for GOK bug 98420. + (spi_controller_register_with_devices): + Call XTestGrabControl with 'impervious' flag set to True, + allows us to synthesize events and query the pointer even during + an active grab by another client. + (spi_device_event_controller_forward_mouse_event): + Set the mouse_mask_state to the mouse_button_state from + the intercepted event, to synchronize the grab listener with + the poll state. + 2002-11-20 Bill Haneman * cspi/spi_accessible.c: diff --git a/NEWS b/NEWS index d06a90c..324472a 100644 --- a/NEWS +++ b/NEWS @@ -1,7 +1,43 @@ (top) in HEAD: -* bugfixes for: 84856 +What's new in at-spi-1.1.5: + +* event struct in libspi is bigger, increased unimplemented + slot count for sufficient future bincompatible expansion. + (WARNING: breaks bincompat for direct CORBA clients. CSPI clients + not affected.) + +* New accessor methods allow state-coherent query of many + event types. + +* API Frozen for GNOME 2.2. + +* New role types: APPLICATION, HEADER, FOOTER, PARAGRAPH, RULER. + +* New relations, FLOWS_FROM, FLOWS_TO, EMBEDS, EMBEDDED_BY, + SUBWINDOW_OF. + +* New state, MANAGES_DESCENDANTS. New event, "active-descendant-changed". + +* reduced debug output, unless you set AT_SPI_DEBUG environment + variable to string which parses to an integer value > 0. + +* added definitions for SPI_KEYMASK_BUTTON1, etc. + +* added SPI_LAYER_WINDOW. + +* Added ability to register 'device event listeners' which can + consume device events, such as mouse events. + +* Added support for mouse and key-modifier event notification. + +* deprecated KeyEventType in favor of EventType. + +* bugfixes for >50 bugs including: 98836, 98842, 97916, 95828, + 93592, 95940, 95517, 93658, 95055, 94555, 84856. + +* updated copyrights to include Ximian. What's new in at-spi-1.1.0: diff --git a/atk-bridge/bridge.c b/atk-bridge/bridge.c index e1befea..86bbaa5 100644 --- a/atk-bridge/bridge.c +++ b/atk-bridge/bridge.c @@ -46,6 +46,7 @@ static CORBA_Environment ev; static Accessibility_Registry registry = NULL; static SpiApplication *this_app = NULL; static gboolean registry_died = FALSE; +static gboolean atk_listeners_registered = FALSE; static guint toplevel_handler; /* NOT YET USED @@ -274,7 +275,12 @@ spi_atk_register_event_listeners (void) guint id; GObject *ao = g_object_new (ATK_TYPE_OBJECT, NULL); AtkObject *bo = atk_no_op_object_new (ao); - + + + if (atk_listeners_registered) return; + + atk_listeners_registered = TRUE; + /* Register for focus event notifications, and register app with central registry */ listener_ids = g_array_sized_new (FALSE, TRUE, sizeof (guint), 16); diff --git a/registryd/deviceeventcontroller.c b/registryd/deviceeventcontroller.c index 8fe64e4..df24cde 100644 --- a/registryd/deviceeventcontroller.c +++ b/registryd/deviceeventcontroller.c @@ -1,5 +1,5 @@ -/* - * AT-SPI - Assistive Technology Service Provider Interface +/* AT-SPI - Assistive Technology Service Provider Interface + * * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) * * Copyright 2001, 2002 Sun Microsystems Inc., @@ -199,106 +199,170 @@ spi_dec_poll_mouse_moved (gpointer data) 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); - - if (mask_return != mouse_mask_state) { - if ((mask_return & mouse_button_mask) != - (mouse_mask_state & mouse_button_mask)) { - int button_number = 0; - if (!(mask_return & Button1Mask) && - (mouse_mask_state & Button1Mask)) { - button_number = 1; - } else if (!(mask_return & Button2Mask) && - (mouse_mask_state & Button2Mask)) { - button_number = 2; - } else if (!(mask_return & Button3Mask) && - (mouse_mask_state & Button3Mask)) { - button_number = 3; - } else if (!(mask_return & Button4Mask) && - (mouse_mask_state & Button1Mask)) { - button_number = 4; - } else if (!(mask_return & Button5Mask) && - (mouse_mask_state & Button5Mask)) { - button_number = 5; - } - if (button_number) { + 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 ((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 & Button1Mask)) + { + mouse_mask_state &= ~Button4Mask; + button_number = 4; + } + else if ((mask_return & Button4Mask) && + !(mouse_mask_state & Button1Mask)) + { + 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 Released\n", - button_number); + fprintf (stderr, "Button %d %s\n", + button_number, (is_down) ? "Pressed" : "Released"); #endif - snprintf (event_name, 22, "mouse:button:%dr", button_number); - /* TODO: distinguish between physical and - * logical buttons - */ - mouse_e.type = 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 (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 (registry), - &e, - &ev); - } + 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 (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 (registry), + &e, + &ev); } - if ((mask_return & key_modifier_mask) != - (mouse_mask_state & key_modifier_mask)) { + } + + if ((mask_return & key_modifier_mask) != + (mouse_mask_state & key_modifier_mask)) { #ifdef SPI_DEBUG - fprintf (stderr, "MODIFIER CHANGE EVENT!\n"); + fprintf (stderr, "MODIFIER CHANGE EVENT!\n"); #endif - e.type = "keyboard:modifiers"; - e.source = BONOBO_OBJREF (registry->desktop); - e.detail1 = mouse_mask_state; - e.detail2 = mask_return; - spi_init_any_nil (&e.any_data); - CORBA_exception_init (&ev); - Accessibility_Registry_notifyEvent (BONOBO_OBJREF (registry), - &e, - &ev); - } - mouse_mask_state = mask_return; - } + e.type = "keyboard:modifiers"; + e.source = BONOBO_OBJREF (registry->desktop); + e.detail1 = mouse_mask_state; + e.detail2 = mask_return; + spi_init_any_nil (&e.any_data); + CORBA_exception_init (&ev); + Accessibility_Registry_notifyEvent (BONOBO_OBJREF (registry), + &e, + &ev); + } + mouse_mask_state = mask_return; + } + if (poll_count++ == poll_count_modulus) { - poll_count = 0; - e.type = "mouse:abs"; - e.source = BONOBO_OBJREF (registry->desktop); - e.detail1 = x; - e.detail2 = y; - spi_init_any_nil (&e.any_data); - CORBA_exception_init (&ev); - Accessibility_Registry_notifyEvent (BONOBO_OBJREF (registry), - &e, - &ev); + poll_count = 0; + e.type = "mouse:abs"; + e.source = BONOBO_OBJREF (registry->desktop); + e.detail1 = x; + e.detail2 = y; + spi_init_any_nil (&e.any_data); + CORBA_exception_init (&ev); + Accessibility_Registry_notifyEvent (BONOBO_OBJREF (registry), + &e, + &ev); } if (x != last_mouse_pos->x || y != last_mouse_pos->y) { - e.type = "mouse:rel"; - e.source = BONOBO_OBJREF (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 (registry), - &e, - &ev); - return TRUE; + e.type = "mouse:rel"; + e.source = BONOBO_OBJREF (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 (registry), + &e, + &ev); + return TRUE; } return FALSE; } @@ -691,7 +755,7 @@ spi_device_event_controller_forward_mouse_event (SpiDEController *controller, int button = xbutton_event->button; unsigned int mouse_button_state = xbutton_event->state; - + switch (button) { case 1: @@ -732,22 +796,26 @@ spi_device_event_controller_forward_mouse_event (SpiDEController *controller, mouse_e.timestamp = (CORBA_unsigned_long) xbutton_event->time; mouse_e.event_string = ""; mouse_e.is_text = CORBA_FALSE; - is_consumed = spi_controller_notify_mouselisteners (controller, &mouse_e, &ev); - - 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; - spi_init_any_nil (&e.any_data); - CORBA_exception_init (&ev); - - Accessibility_Registry_notifyEvent (BONOBO_OBJREF (controller->registry), - &e, - &ev); - + if ((mouse_button_state & mouse_button_mask) != + (mouse_mask_state & mouse_button_mask)) + { + mouse_mask_state = mouse_button_state; + is_consumed = + spi_controller_notify_mouselisteners (controller, &mouse_e, &ev); + 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; + spi_init_any_nil (&e.any_data); + CORBA_exception_init (&ev); + + Accessibility_Registry_notifyEvent (BONOBO_OBJREF (controller->registry), + &e, + &ev); + } 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 */ @@ -856,7 +924,8 @@ spi_controller_register_with_devices (SpiDEController *controller) { DEControllerPrivateData *priv = (DEControllerPrivateData *) g_object_get_qdata (G_OBJECT (controller), spi_dec_private_quark); - + /* FIXME: should check for extension first! */ + XTestGrabControl (spi_get_display (), True); priv->xkb_desc = XkbGetMap (spi_get_display (), 0, XkbUseCoreKbd); /* calls to device-specific implementations and routines go here */ -- 2.7.4