From 8cc22dc406e33c90b501d661208fce3d457afac1 Mon Sep 17 00:00:00 2001 From: billh Date: Mon, 3 Jun 2002 14:44:55 +0000 Subject: [PATCH] Revved to 1.0.0; at-spi 1.0 is now API frozen. Revved registry activation (OAFIID) version to 1.0. API changes: Accessibility_Registry.idl: registerKeystrokeListener now returns a boolean. Enhancements to the screen review demo/test code. git-svn-id: http://svn.gnome.org/svn/at-spi/trunk@309 e2bd861d-eb25-0410-b326-f6ed22b6b98c --- ChangeLog | 78 ++++++++++++++ atk-bridge/bridge.c | 2 +- configure.in | 6 +- cspi/bonobo/cspi-bonobo.c | 2 +- idl/Accessibility_Registry.idl | 4 +- registryd/Accessibility_Registry.server.in.in | 2 +- registryd/deviceeventcontroller.c | 86 +++++++++++++-- registryd/registry-main.c | 2 +- registryd/registry.c | 9 +- registryd/registryd.c | 2 +- test/app.c | 2 +- test/at.c | 2 +- test/screen-review-test.c | 145 +++++++++++++++++++++----- 13 files changed, 295 insertions(+), 47 deletions(-) diff --git a/ChangeLog b/ChangeLog index 42439fc..c70fa91 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,72 @@ +2002-06-02 Bill Haneman + + AT-SPI 1.0 API FINAL: at-spi 1.0 is now + API frozen. + + * configure.in: Revved to 1.0.0. + + * idl/Accessibility_Registry.idl: + (registerKeystrokeListener): + Added boolean return value. + + * registryd/registry.c: + (notify_listeners_cb): Minor fix to debug output. + + * registryd/Accessibility_Registry.server.in.in: + Revved version number in OAFIID to 1.0. + + * registryd/registryd.c: + (main): + Use new OAFIID version. + + * cspi/bonobo/cspi-bonobo.c: + (cspi_init): + Use new OAFIID version. + + * test/at.c: + (main): + * test/app.c: + (main): + * atk-bridge/bridge.c: + (atk_bridge_init): + Use new OAFIID version. + + * registryd/deviceeventcontroller.c: + (impl_register_keystroke_listener): + Added CORBA_boolean return value. + (spi_controller_register_device_listener): + Added gboolean return value. + (spi_controller_register_global_keygrabs): + Added gboolean return value. + (spi_key_set_contains_key): + Added implementation for many more control keys, + for instance F1-F12, arrow keys, End, Home, Page_Up, + Page_Down, Escape. + [TODO: some still not implemented]. + + * text/screen-review-test.c: + (text_chunk_pad_string): + New function: it provides mapping between coordinate + positions of text chunks and character positions in the + screen-review-line output string. + (text_chunk_to_string): + New function, calls text_chunk_pad_string with various + pad/delimiter characters. Pushbuttons are delimited with + square brackets, Frames with vertical 'pipe' lines, and + other text with double quotes. + (text_chunk_list_to_string): + Calls new function text_chunk_to_string. + (toplevel_composite): + New function to composite layers CANVAS through + POPUP in each toplevel (other layers are composited + across toplevels, i.e. BACKGROUND and OVERLAY). + (review_buffer_composite): + Revise to use new methods. + + + + + 2002-05-31 Laszlo Peter * configure.in: add the Xtst libdir to the runpath on Solaris, @@ -9,6 +78,15 @@ 2002-05-29 Bill Haneman + * test/screen-review-test.c: + (text_chunk_pad_string): + Added method, which pads the string according to the + text bounds of the chunk. It also takes a 3-character + string as a param which indicates the characters to be + used for start, padding, and end delimitation of the chunk. + (text_chunk_to_string): + Changed to use text_chunk_pad_string. + * configure.in: Fixed bug in AC_OUTPUT that was causing path substitution in Accessibility_Registry.server to fail. diff --git a/atk-bridge/bridge.c b/atk-bridge/bridge.c index 91f8749..974b483 100644 --- a/atk-bridge/bridge.c +++ b/atk-bridge/bridge.c @@ -110,7 +110,7 @@ atk_bridge_init (gint *argc, gchar **argv[]) CORBA_exception_init(&ev); registry = bonobo_activation_activate_from_id ( - "OAFIID:Accessibility_Registry:proto0.1", 0, NULL, &ev); + "OAFIID:Accessibility_Registry:1.0", 0, NULL, &ev); if (ev._major != CORBA_NO_EXCEPTION) { diff --git a/configure.in b/configure.in index 5749679..7a75488 100644 --- a/configure.in +++ b/configure.in @@ -1,8 +1,8 @@ AC_INIT(idl/Accessibility.idl) -AT_SPI_MAJOR_VERSION=0 -AT_SPI_MINOR_VERSION=13 -AT_SPI_MICRO_VERSION=1 +AT_SPI_MAJOR_VERSION=1 +AT_SPI_MINOR_VERSION=0 +AT_SPI_MICRO_VERSION=0 AT_SPI_INTERFACE_AGE=0 AT_SPI_BINARY_AGE=0 AT_SPI_VERSION="$AT_SPI_MAJOR_VERSION.$AT_SPI_MINOR_VERSION.$AT_SPI_MICRO_VERSION" diff --git a/cspi/bonobo/cspi-bonobo.c b/cspi/bonobo/cspi-bonobo.c index c5bd670..eb51feb 100644 --- a/cspi/bonobo/cspi-bonobo.c +++ b/cspi/bonobo/cspi-bonobo.c @@ -86,7 +86,7 @@ cspi_init (void) g_error ("Could not initialize Bonobo"); } - obj_id = "OAFIID:Accessibility_Registry:proto0.1"; + obj_id = "OAFIID:Accessibility_Registry:1.0"; CORBA_exception_init (&ev); diff --git a/idl/Accessibility_Registry.idl b/idl/Accessibility_Registry.idl index 6e8e554..74165cf 100644 --- a/idl/Accessibility_Registry.idl +++ b/idl/Accessibility_Registry.idl @@ -226,13 +226,13 @@ module Accessibility { * receive the events synchronously, potentially consuming them, * or just be notified asynchronously of those events that have * been generated. - * Returns: void + * Returns: %true if successful, %false if not * * Register to intercept keyboard events, and either pass them on or * consume them. * **/ - void registerKeystrokeListener (in DeviceEventListener listener, + boolean registerKeystrokeListener (in DeviceEventListener listener, in KeySet keys, in ControllerEventMask mask, in KeyEventTypeSeq type, diff --git a/registryd/Accessibility_Registry.server.in.in b/registryd/Accessibility_Registry.server.in.in index b5e70fe..368186b 100644 --- a/registryd/Accessibility_Registry.server.in.in +++ b/registryd/Accessibility_Registry.server.in.in @@ -1,5 +1,5 @@ - diff --git a/registryd/deviceeventcontroller.c b/registryd/deviceeventcontroller.c index bad5705..c0bc354 100644 --- a/registryd/deviceeventcontroller.c +++ b/registryd/deviceeventcontroller.c @@ -84,7 +84,7 @@ typedef struct { static void spi_controller_register_with_devices (SpiDEController *controller); static gboolean spi_controller_update_key_grabs (SpiDEController *controller, Accessibility_DeviceEvent *recv); -static void spi_controller_register_device_listener (SpiDEController *controller, +static gboolean spi_controller_register_device_listener (SpiDEController *controller, DEControllerListener *l, CORBA_Environment *ev); static void spi_device_event_controller_forward_key_event (SpiDEController *controller, @@ -239,6 +239,9 @@ handle_keygrab (SpiDEController *controller, if (key_listener->keys->_length == 0) /* special case means AnyKey/AllKeys */ { grab_mask.key_val = AnyKey; +#ifdef SPI_DEBUG + fprintf (stderr, "AnyKey grab!"); */ +#endif process_cb (controller, &grab_mask); } else @@ -268,12 +271,12 @@ handle_keygrab (SpiDEController *controller, } } -static void +static gboolean spi_controller_register_global_keygrabs (SpiDEController *controller, DEControllerKeyListener *key_listener) { handle_keygrab (controller, key_listener, _register_keygrab); - spi_controller_update_key_grabs (controller, NULL); + return spi_controller_update_key_grabs (controller, NULL); } static void @@ -284,7 +287,7 @@ spi_controller_deregister_global_keygrabs (SpiDEController *controller, spi_controller_update_key_grabs (controller, NULL); } -static void +static gboolean spi_controller_register_device_listener (SpiDEController *controller, DEControllerListener *listener, CORBA_Environment *ev) @@ -299,12 +302,15 @@ spi_controller_register_device_listener (SpiDEController *controller, key_listener); if (key_listener->mode->global) { - spi_controller_register_global_keygrabs (controller, key_listener); + return spi_controller_register_global_keygrabs (controller, key_listener); } + else + return TRUE; break; default: break; } + return FALSE; } static GdkFilterReturn @@ -355,6 +361,7 @@ spi_controller_register_with_devices (SpiDEController *controller) x_default_error_handler = XSetErrorHandler (_spi_controller_device_error_handler); } +#define SPI_KEYEVENT_DEBUG static gboolean spi_key_set_contains_key (Accessibility_KeySet *key_set, const Accessibility_DeviceEvent *key_event) @@ -560,6 +567,69 @@ spi_keystroke_from_x_key_event (XKeyEvent *x_key_event) case XK_Return: key_event.event_string = CORBA_string_dup ("Return"); break; + case XK_Home: + key_event.event_string = CORBA_string_dup ("Home"); + break; + case XK_Page_Down: + key_event.event_string = CORBA_string_dup ("Page_Down"); + break; + case XK_Page_Up: + key_event.event_string = CORBA_string_dup ("Page_Up"); + break; + case XK_F1: + key_event.event_string = CORBA_string_dup ("F1"); + break; + case XK_F2: + key_event.event_string = CORBA_string_dup ("F2"); + break; + case XK_F3: + key_event.event_string = CORBA_string_dup ("F3"); + break; + case XK_F4: + key_event.event_string = CORBA_string_dup ("F4"); + break; + case XK_F5: + key_event.event_string = CORBA_string_dup ("F5"); + break; + case XK_F6: + key_event.event_string = CORBA_string_dup ("F6"); + break; + case XK_F7: + key_event.event_string = CORBA_string_dup ("F7"); + break; + case XK_F8: + key_event.event_string = CORBA_string_dup ("F8"); + break; + case XK_F9: + key_event.event_string = CORBA_string_dup ("F9"); + break; + case XK_F10: + key_event.event_string = CORBA_string_dup ("F10"); + break; + case XK_F11: + key_event.event_string = CORBA_string_dup ("F11"); + break; + case XK_F12: + key_event.event_string = CORBA_string_dup ("F12"); + break; + case XK_End: + key_event.event_string = CORBA_string_dup ("End"); + break; + case XK_Escape: + key_event.event_string = CORBA_string_dup ("Escape"); + break; + case XK_Up: + key_event.event_string = CORBA_string_dup ("Up"); + break; + case XK_Down: + key_event.event_string = CORBA_string_dup ("Down"); + break; + case XK_Left: + key_event.event_string = CORBA_string_dup ("Left"); + break; + case XK_Right: + key_event.event_string = CORBA_string_dup ("Right"); + break; default: if (XLookupString (x_key_event, cbuf, cbuf_bytes, &keysym, NULL) > 0) { @@ -706,7 +776,7 @@ spi_device_event_controller_object_finalize (GObject *object) * CORBA Accessibility::DEController::registerKeystrokeListener * method implementation */ -static void +static CORBA_boolean impl_register_keystroke_listener (PortableServer_Servant servant, const Accessibility_DeviceEventListener l, const Accessibility_KeySet *keys, @@ -723,8 +793,8 @@ impl_register_keystroke_listener (PortableServer_Servant servan (void *) l, (unsigned long) mask); #endif dec_listener = spi_dec_key_listener_new (l, keys, mask, type, mode, ev); - spi_controller_register_device_listener ( - controller, (DEControllerListener *) dec_listener, ev); + return spi_controller_register_device_listener ( + controller, (DEControllerListener *) dec_listener, ev); } diff --git a/registryd/registry-main.c b/registryd/registry-main.c index 47ac78b..71b86f6 100644 --- a/registryd/registry-main.c +++ b/registryd/registry-main.c @@ -41,7 +41,7 @@ main (int argc, char **argv) g_error ("Could not initialize oaf / Bonobo"); } - obj_id = "OAFIID:Accessibility_Registry:proto0.1"; + obj_id = "OAFIID:Accessibility_Registry:1.0"; registry = spi_registry_new (); diff --git a/registryd/registry.c b/registryd/registry.c index c4e93d9..d74fc8c 100644 --- a/registryd/registry.c +++ b/registryd/registry.c @@ -23,6 +23,7 @@ /* registry.c: the main accessibility service registry implementation */ #undef SPI_LISTENER_DEBUG +#undef SPI_DEBUG #include #ifdef SPI_DEBUG @@ -351,12 +352,13 @@ impl_accessibility_registry_register_global_event_listener ( const CORBA_char *event_name, CORBA_Environment *ev) { - SpiRegistry *registry = SPI_REGISTRY (bonobo_object_from_servant (servant)); + SpiRegistry *registry = SPI_REGISTRY (bonobo_object_from_servant (servant)); SpiListenerStruct *ls = spi_listener_struct_new (listener, ev); EventTypeStruct etype; GList **list; #ifdef SPI_DEBUG + fprintf (stderr, "registering"); fprintf (stderr, "registering for events of type %s\n", event_name); #endif @@ -560,8 +562,9 @@ notify_listeners_cb (GList * const *list, gpointer user_data) (ls->event_type_quark == ctx->etype.minor)) { #ifdef SPI_DEBUG - fprintf (stderr, "notifying listener %d\n", g_list_index (listeners, l->data)); - s = Accessibility_Accessible__get_name (ctx->source, ev); + fprintf (stderr, "notifying listener %d\n", 0); +/* g_list_index (list, l->data)); */ + s = Accessibility_Accessible__get_name (ctx->source, ctx->ev); fprintf (stderr, "event source name %s\n", s); CORBA_free (s); #endif diff --git a/registryd/registryd.c b/registryd/registryd.c index 228b474..f5ab438 100644 --- a/registryd/registryd.c +++ b/registryd/registryd.c @@ -42,7 +42,7 @@ main (int argc, char **argv) g_error ("Could not initialize oaf / Bonobo"); } - obj_id = "OAFIID:Accessibility_Registry:proto0.1"; + obj_id = "OAFIID:Accessibility_Registry:1.0"; registry = spi_registry_new (); diff --git a/test/app.c b/test/app.c index c11b29e..9bf749d 100644 --- a/test/app.c +++ b/test/app.c @@ -67,7 +67,7 @@ main(int argc, char **argv) e.source = bonobo_object_corba_objref ( bonobo_object (accessible)); e.type = CORBA_string_dup ("focus:"); - obj_id = "OAFIID:Accessibility_Registry:proto0.1"; + obj_id = "OAFIID:Accessibility_Registry:1.0"; oclient = bonobo_activation_activate_from_id (obj_id, 0, NULL, &ev); if (ev._major != CORBA_NO_EXCEPTION) { diff --git a/test/at.c b/test/at.c index 1c2c185..418ce81 100644 --- a/test/at.c +++ b/test/at.c @@ -62,7 +62,7 @@ main(int argc, char **argv) g_error ("Could not initialize Bonobo"); } - obj_id = "OAFIID:Accessibility_Registry:proto0.1"; + obj_id = "OAFIID:Accessibility_Registry:1.0"; oclient = bonobo_activation_activate_from_id (obj_id, 0, NULL, &ev); if (ev._major != CORBA_NO_EXCEPTION) { diff --git a/test/screen-review-test.c b/test/screen-review-test.c index af19d52..7cde0ec 100644 --- a/test/screen-review-test.c +++ b/test/screen-review-test.c @@ -30,8 +30,7 @@ * * Issues: * - * * bounds now fail to include window border decoration - * (which we can't really know about yet). + * * there are bugs in the compositing code. * * * brute-force algorithm uses no client-side cache; performance mediocre. * @@ -40,17 +39,13 @@ * the active window is not always on top (i.e. autoraise is * not enabled). * - * * text-bearing objects that don't implement AccessibleText (such as buttons) - * don't get their text clipped since we don't know the character - * bounding boxes. - * * * can't know about "inaccessible" objects that may be obscuring the * accessible windows (inherent to API-based approach). * - * * this implementation doesn't worry about text column-alignment, it generates - * review lines of more-or-less arbitrary length. The x-coordinate - * info is preserved in the reviewBuffers list structures, but the - * "buffer-to-string" algorithm (currently) ignores it. + * * text column alignment is crude since it relies on a hard-coded + * (and arbitrary) ratio of horizontal pixels to character columns. + * For small proportional fonts, overruns are likely to result in + * occasional review lines that exceed the standard length. * * * (others). */ @@ -116,7 +111,7 @@ typedef struct _TextChunk { BoundaryRect end_char_bounds; } TextChunk; -typedef struct _ScreenReviewBuffer { /* TODO: implement */ +typedef struct _ScreenReviewBuffer { GList *text_chunks; } ScreenReviewBuffer; @@ -185,7 +180,7 @@ clip_bounds_clone (BoundaryRect *bounds[]) BoundaryRect **bounds_clone; bounds_clone = (BoundaryRect **) g_new0 (gpointer, SPI_LAYER_LAST_DEFINED); - for (i = 0; i < SPI_LAYER_LAST_DEFINED; ++i) { + for (i = 1; i < SPI_LAYER_LAST_DEFINED; ++i) { bounds_clone[i] = g_new0 (BoundaryRect, 1); *bounds_clone[i] = *bounds[i]; } @@ -746,7 +741,6 @@ string_guess_clip (TextChunk *chunk) &b.x, &b.y, &b.width, &b.height, SPI_COORD_TYPE_SCREEN); - /* TODO: finish this! */ start_offset = len * (chunk->text_bounds.x - b.x) / b.width; end_offset = len * (chunk->text_bounds.x + chunk->text_bounds.width - b.x) / b.width; @@ -829,20 +823,82 @@ text_chunk_get_clipped_string (TextChunk *chunk) return string; } + +static char* +text_chunk_pad_string (TextChunk *chunk, char *string, glong offset, const char *pad_chars) +{ + char *s = ""; + char *cp; + char startbuf[6], padbuf[6], endbuf[6]; + int pixels_per_column = 6; + /* this is an arbitrary pixel-to-textcolumn mapping at present */ + glong end_padding; + gint howmany; + howmany = g_unichar_to_utf8 (g_utf8_get_char (pad_chars), startbuf); + startbuf[howmany] = '\0'; + g_assert (howmany < 7 && howmany > 0); + cp = g_utf8_find_next_char (pad_chars, NULL); + howmany = g_unichar_to_utf8 (g_utf8_get_char (cp), padbuf); + padbuf[howmany] = '\0'; + g_assert (howmany < 7 && howmany > 0); + cp = g_utf8_find_next_char (cp, NULL); + howmany = g_unichar_to_utf8 (g_utf8_get_char (cp), endbuf); + endbuf[howmany] = '\0'; + g_assert (howmany < 7 && howmany > 0); + end_padding = chunk->clip_bounds.x / pixels_per_column; + while (offset < end_padding - 1) { + s = g_strconcat (s, padbuf, NULL); /* could be more efficient */ + ++offset; + } + s = g_strconcat (s, startbuf, string, NULL); + offset += g_utf8_strlen (string, -1) + 1; + end_padding = chunk->text_bounds.x / pixels_per_column; + while (offset < end_padding) { + s = g_strconcat (s, padbuf, NULL); /* could be more efficient */ + ++offset; + } + end_padding = (chunk->clip_bounds.x + chunk->clip_bounds.width) / + pixels_per_column; + while (offset < end_padding - 1) { + s = g_strconcat (s, padbuf, NULL); /* could be more efficient */ + ++offset; + } + s = g_strconcat (s, endbuf, NULL); + return s; +} + +static char* +text_chunk_to_string (TextChunk *chunk, glong offset) +{ + char *s = NULL; + if (chunk->string) { + s = text_chunk_get_clipped_string (chunk); + if (chunk->clip_bounds.role == SPI_ROLE_PUSH_BUTTON) { + s = text_chunk_pad_string (chunk, s, offset, "[ ]"); + } else if (chunk->clip_bounds.role == SPI_ROLE_FRAME) { + s = text_chunk_pad_string (chunk, s, offset, "| |"); + } else if (chunk->clip_bounds.role == SPI_ROLE_TEXT) { + s = text_chunk_pad_string (chunk, s, offset, "\" \""); + } else { + s = text_chunk_pad_string (chunk, s, offset, " "); + } + } + return s; +} + static char* text_chunk_list_to_string (GList *iter) { char *s = ""; char *string; TextChunk *chunk = NULL; + int offset = 0; while (iter) { chunk = (TextChunk *)iter->data; - if (chunk /* && chunk->string */) { - string = text_chunk_get_clipped_string (chunk); + if (chunk) { + string = text_chunk_to_string (chunk, g_utf8_strlen (s, -1)); if (string) - s = g_strconcat (s, "|", string, NULL); - else /* XXX test */ - s = g_strconcat (s, ":", NULL); + s = g_strconcat (s, string, NULL); } iter = iter->next; } @@ -850,15 +906,54 @@ text_chunk_list_to_string (GList *iter) return s; } +#define COMPOSITE_DEBUG + +static void +toplevel_composite (ScreenReviewBuffer *buffers[]) +{ + int i; + GList *chunk_list, *iter; + TextChunk *chunk; + + chunk_list = buffers[SPI_LAYER_CANVAS]->text_chunks; + for (i = SPI_LAYER_MDI; i < SPI_LAYER_OVERLAY; ++i) { + iter = buffers[i]->text_chunks; +#ifdef COMPOSITE_DEBUG + fprintf (stderr, "layer %d has %d chunks\n", + i, g_list_length (iter)); +#endif + while (iter) { + chunk = (TextChunk *) iter->data; + if (chunk) { +#ifdef COMPOSITE_DEBUG + fprintf (stderr, "inserting chunk <%s>\n", + chunk->string ? chunk->string : ""); +#endif + chunk_list = + text_chunk_list_insert_chunk (chunk_list, + chunk); + } + iter = iter->next; + } + } +} + static char* review_buffer_composite (ScreenReviewBuffer *buffers[]) { + /* TODO: FIXME: something is wrong here, compositing fails */ int i; GList *chunk_list, *iter; TextChunk *chunk; -#ifdef NEED_TO_FIX_THIS - chunk_list = buffers[0]->text_chunks; - for (i = 1; i < SPI_LAYER_LAST_DEFINED; ++i) { + chunk_list = buffers[SPI_LAYER_BACKGROUND]->text_chunks; + for (i = 2; i < SPI_LAYER_LAST_DEFINED; ++i) { + if (i == SPI_LAYER_WIDGET) i = SPI_LAYER_OVERLAY; + /* + * Q: why skip these layers ? + * A: since layers WIDGET, MDI, and POPUP have already been + * composited into layer CANVAS for each toplevel before this + * routine is called. + */ iter = buffers[i]->text_chunks; #ifdef CLIP_DEBUG fprintf (stderr, "layer %d has %d chunks\n", @@ -878,7 +973,7 @@ review_buffer_composite (ScreenReviewBuffer *buffers[]) iter = iter->next; } } -#endif + chunk_list = buffers[SPI_LAYER_WIDGET]->text_chunks; return text_chunk_list_to_string (chunk_list); } @@ -898,7 +993,7 @@ get_screen_review_line_at (int x, int y) GTimer *timer = g_timer_new (); int i; - for (i = 0; i < SPI_LAYER_LAST_DEFINED; ++i) { + for (i = 1; i < SPI_LAYER_LAST_DEFINED; ++i) { reviewBuffers[i] = g_new0 (ScreenReviewBuffer, 1); clip_bounds[i] = g_new0 (BoundaryRect, 1); clip_bounds[i]->isClipped = FALSE; @@ -960,11 +1055,13 @@ get_screen_review_line_at (int x, int y) &toplevel_bounds.height, SPI_COORD_TYPE_SCREEN); toplevel_bounds.isEmpty = FALSE; - for (i = 0; i < SPI_LAYER_LAST_DEFINED; ++i) { + for (i = 1; i < SPI_LAYER_LAST_DEFINED; ++i) { *clip_bounds[i] = toplevel_bounds; } clip_into_buffers (toplevel, clip_bounds, reviewBuffers, x, y); + + toplevel_composite (reviewBuffers); #ifdef CHUNK_LIST_DEBUG fprintf (stderr, "toplevel clip done\n"); debug_chunk_list (reviewBuffers[SPI_LAYER_WIDGET]->text_chunks); -- 2.7.4