+2002-06-02 Bill Haneman <bill.haneman@sun.com>
+
+ 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 <laca@sun.com>
* configure.in: add the Xtst libdir to the runpath on Solaris,
2002-05-29 Bill Haneman <bill.haneman@sun.com>
+ * 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.
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)
{
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"
g_error ("Could not initialize Bonobo");
}
- obj_id = "OAFIID:Accessibility_Registry:proto0.1";
+ obj_id = "OAFIID:Accessibility_Registry:1.0";
CORBA_exception_init (&ev);
* 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,
<oaf_info>
- <oaf_server iid="OAFIID:Accessibility_Registry:proto0.1"
+ <oaf_server iid="OAFIID:Accessibility_Registry:1.0"
type="exe" location="@REGISTRYD_PATH@/at-spi-registryd">
<oaf_attribute name="repo_ids" type="stringv">
<item value="IDL:Bonobo/Unknown:1.0"/>
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,
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
}
}
-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
spi_controller_update_key_grabs (controller, NULL);
}
-static void
+static gboolean
spi_controller_register_device_listener (SpiDEController *controller,
DEControllerListener *listener,
CORBA_Environment *ev)
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
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)
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)
{
* 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,
(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);
}
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 ();
/* registry.c: the main accessibility service registry implementation */
#undef SPI_LISTENER_DEBUG
+#undef SPI_DEBUG
#include <config.h>
#ifdef SPI_DEBUG
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
(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
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 ();
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) {
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) {
*
* 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.
*
* 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).
*/
BoundaryRect end_char_bounds;
} TextChunk;
-typedef struct _ScreenReviewBuffer { /* TODO: implement */
+typedef struct _ScreenReviewBuffer {
GList *text_chunks;
} ScreenReviewBuffer;
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];
}
&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;
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;
}
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 : "<null>");
+#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",
iter = iter->next;
}
}
-#endif
+
chunk_list = buffers[SPI_LAYER_WIDGET]->text_chunks;
return text_chunk_list_to_string (chunk_list);
}
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;
&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);