X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=test%2Fscreen-review-test.c;h=958821228f52c89408096c63a587fe4c2d99e983;hb=59c99dae55f98dd70d972a4365464589ed0f7517;hp=070af602822a4662d58b735358ca5467bb05b507;hpb=c4d4854798b0db73376f23a3e70a8a75909a4620;p=platform%2Fcore%2Fuifw%2Fat-spi2-atk.git diff --git a/test/screen-review-test.c b/test/screen-review-test.c index 070af60..9588212 100644 --- a/test/screen-review-test.c +++ b/test/screen-review-test.c @@ -23,10 +23,44 @@ #include #include "../cspi/spi-private.h" -#define CLIP_DEBUG +#undef CLIP_DEBUG -#define BOUNDS_CONTAIN_X(b, p) (((p)>=(b)->x) && ((p)<=((b)->x + (b)->width))\ - && ((b)->width > 0) && ((b)->height > 0)) +/* + * Screen Review Algorithm Demonstration, Benchmark, and Test-bed. + * + * Issues: + * + * * bounds now fail to include window border decoration + * (which we can't really know about yet). + * + * * brute-force algorithm uses no client-side cache; performance mediocre. + * + * * we don't have good ordering information for the toplevel windows, + * and our current heuristic is not guaranteed if + * 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. + * + * * (others). + */ + +#undef CHUNK_LIST_DEBUG /* define to get list of text chunks before clip */ + +#define BOUNDS_CONTAIN_X_BOUNDS(b, p) ( ((p).x>=(b).x) &&\ + (((p).x + (p).width) <= \ + ((b).x + (b).width)) && \ + ((b).width > 0) && ((b).height > 0)) #define BOUNDS_CONTAIN_Y(b, p) (((p)>=(b)->y) && ((p)<=((b)->y + (b)->height))\ && ((b)->width > 0) && ((b)->height > 0)) @@ -47,11 +81,14 @@ (c)->clip_bounds.width) >= \ ((i)->clip_bounds.x + \ (i)->clip_bounds.width))) +/* + * #define CHUNK_BOUNDS_WITHIN(c, i) ((i) && ((c)->clip_bounds.x >= \ + * (i)->text_bounds.x) && \ + * (((c)->clip_bounds.x + (c)->clip_bounds.width) \ + * <= ((i)->text_bounds.x + (i)->text_bounds.width))) + */ -//#define CHUNK_BOUNDS_WITHIN(c, i) ((i) && ((c)->clip_bounds.x >= \ -// (i)->text_bounds.x) && \ -// (((c)->clip_bounds.x + (c)->clip_bounds.width) \ -// <= ((i)->text_bounds.x + (i)->text_bounds.width))) +#define IS_CLIPPING_CONTAINER(a) ((a) != SPI_ROLE_PAGE_TAB) static void report_screen_review_line (const AccessibleEvent *event, void *user_data); @@ -106,7 +143,7 @@ main (int argc, char **argv) SPI_registerGlobalEventListener (mouseclick_listener, "Gtk:GtkWidget:button-press-event"); #define JAVA_TEST_HACK -#ifdef JAVA_TEST_HACK +#ifdef JAVA_TEST_HACK /* Only use this to test Java apps */ SPI_registerGlobalEventListener (mouseclick_listener, "object:text-caret-moved"); isJava = TRUE; @@ -124,14 +161,6 @@ main (int argc, char **argv) } static inline gboolean -bounds_contain_y (BoundaryRect *bounds, int y) -{ - return (y > bounds->y && y <= (bounds->y + bounds->height) - && bounds->width && bounds->height); -} - - -static inline gboolean chunk_bounds_within (TextChunk *chunk, TextChunk *test_chunk) { int x1, x2, tx1, tx2; @@ -144,10 +173,6 @@ chunk_bounds_within (TextChunk *chunk, TextChunk *test_chunk) gtx1 = (chunk->clip_bounds.x >= test_chunk->clip_bounds.x); ltx2 = (chunk->clip_bounds.x + chunk->clip_bounds.width <= test_chunk->clip_bounds.x + test_chunk->clip_bounds.width); - -// fprintf (stderr, "testing BOUNDS %d-%d WITHIN %d-%d: %s\n", -// x1, x2, tx1, tx2, ((gtx1 && ltx2) ? "T" : "F")); - return gtx1 && ltx2; } @@ -185,6 +210,9 @@ boundary_clip (BoundaryRect *bounds, BoundaryRect *clipBounds) bounds->height = MAX (y2 - bounds->y, 0); if (!bounds->width || !bounds->height) bounds->isEmpty = TRUE; + if (IS_CLIPPING_CONTAINER (bounds->role)) { + *clipBounds = *bounds; + } #ifdef CLIP_DEBUG fprintf (stderr, "%d-%d\n", bounds->x, bounds->x+bounds->width); @@ -269,8 +297,9 @@ text_chunk_split_insert (GList *chunk_list, GList *iter, TextChunk *chunk) TextChunk *iter_copy = text_chunk_copy (iter_chunk); /* TODO: FIXME something is wrong here */ #ifdef CLIP_DEBUG - fprintf (stderr, "***clip insert of %s into %s\n", chunk->string, - iter_chunk->string); + fprintf (stderr, "***clip insert of %s into %s\n", + chunk->string ? chunk->string : "", + iter_chunk->string ? iter_chunk->string : ""); #endif chunk_list = g_list_insert_before (chunk_list, iter, iter_copy); text_chunk_tail_clip (iter_copy, chunk); @@ -346,10 +375,11 @@ text_chunk_list_clip_and_insert (GList *text_chunk_list, GList *next) { #ifdef CLIP_DEBUG - fprintf (stderr, "clip-and-insert for %s, between %s and %s\n", - chunk->string, - (prev ? ((TextChunk *)prev->data)->string : ""), - (next ? ((TextChunk *)next->data)->string : "")); + if (chunk->string) + fprintf (stderr, "clip-and-insert for %s, between %s and %s\n", + chunk->string, + (prev && ((TextChunk *)prev->data)->string ? ((TextChunk *)prev->data)->string : ""), + (next && ((TextChunk *)next->data)->string ? ((TextChunk *)next->data)->string : "")); #endif /* cases: */ if (!prev && !next) { /* first element in, no clip needed */ @@ -466,15 +496,16 @@ review_buffer_get_text_chunk (ScreenReviewBuffer *reviewBuffer, &text_chunk->start_char_bounds.height, SPI_COORD_TYPE_SCREEN); #ifdef CLIP_DEBUG - fprintf (stderr, "%s: start char (%d) x, width %d %d;", + fprintf (stderr, "%s: start char (%d) x, width %d %d; ", s, start, text_chunk->start_char_bounds.x, text_chunk->start_char_bounds.width); #endif - end--; /* XXX: bug workaround */ + if (s && strlen (s) && s[strlen (s) - 1] == '\n') + end--; AccessibleText_getCharacterExtents ( - text, end--, + text, end - 1, &text_chunk->end_char_bounds.x, &text_chunk->end_char_bounds.y, &text_chunk->end_char_bounds.width, @@ -482,7 +513,7 @@ review_buffer_get_text_chunk (ScreenReviewBuffer *reviewBuffer, SPI_COORD_TYPE_SCREEN); #ifdef CLIP_DEBUG fprintf (stderr, "end char (%d) x, width %d %d\n", - end, + end - 1, text_chunk->end_char_bounds.x, text_chunk->end_char_bounds.width); #endif @@ -503,14 +534,34 @@ review_buffer_get_text_chunk (ScreenReviewBuffer *reviewBuffer, text_chunk->text_bounds.height = y2 - text_chunk->text_bounds.y; text_chunk->start_offset = start; text_chunk->end_offset = end; - if ((role != SPI_ROLE_TABLE_CELL) /* XXX bug workaround */ - && !bounds_contain_y (&text_chunk->text_bounds, - screen_y)) { + if (text_chunk->text_bounds.x < text_chunk->clip_bounds.x) { + text_chunk->text_bounds.x = text_chunk->clip_bounds.x; + text_chunk->text_bounds.isClipped = TRUE; + } + if ((text_chunk->text_bounds.x + + text_chunk->text_bounds.width) + > (text_chunk->clip_bounds.x + + text_chunk->clip_bounds.width)) { + text_chunk->text_bounds.width = + MAX (0, (text_chunk->clip_bounds.x + + text_chunk->clip_bounds.width) - + text_chunk->text_bounds.x); + text_chunk->text_bounds.isClipped = TRUE; + } + if (!BOUNDS_CONTAIN_Y (&text_chunk->text_bounds, + screen_y)) { +#ifdef CLIP_DEBUG + fprintf (stderr, "%s out of bounds (%d-%d)\n", s, + text_chunk->text_bounds.y, + text_chunk->text_bounds.y + + text_chunk->text_bounds.height); +#endif s = NULL; } } else { if (role == SPI_ROLE_PUSH_BUTTON || role == SPI_ROLE_CHECK_BOX || + role == SPI_ROLE_LABEL || role == SPI_ROLE_MENU || role == SPI_ROLE_MENU_ITEM) { /* don't like this special casing :-( */ @@ -570,23 +621,26 @@ clip_into_buffers (Accessible *accessible, BoundaryRect* parentClipBounds[], BoundaryRect** clip_bounds; TextChunk *text_chunk; AccessibleComponent *component; + AccessibleRole role; int layer; clip_bounds = clip_bounds_clone (parentClipBounds); if (Accessible_isComponent (accessible)) { + role = Accessible_getRole (accessible); component = Accessible_getComponent (accessible); layer = AccessibleComponent_getLayer (component); bounds = *clip_bounds[layer]; - if (!bounds.isEmpty || 1) { + if (!bounds.isEmpty) { AccessibleComponent_getExtents (component, &bounds.x, &bounds.y, &bounds.width, &bounds.height, SPI_COORD_TYPE_SCREEN); + bounds.role = role; if (clip_bounds[layer]) boundary_clip (&bounds, clip_bounds[layer]); - if (bounds_contain_y (&bounds, screen_y)) { + if (BOUNDS_CONTAIN_Y (&bounds, screen_y)) { text_chunk = review_buffer_get_text_chunk ( reviewBuffers[layer], accessible, &bounds, screen_x, screen_y); @@ -595,7 +649,8 @@ clip_into_buffers (Accessible *accessible, BoundaryRect* parentClipBounds[], reviewBuffers[layer]->text_chunks, text_chunk); } else { - clip_bounds[layer]->isEmpty = TRUE; + bounds.isEmpty = + IS_CLIPPING_CONTAINER (bounds.role); } } Accessible_unref (component); @@ -614,53 +669,131 @@ clip_into_buffers (Accessible *accessible, BoundaryRect* parentClipBounds[], /* TODO: free the parent clip bounds */ } +#undef CHARACTER_CLIP_DEBUG + static char* -text_chunk_get_clipped_string (TextChunk *chunk) +text_chunk_get_clipped_substring_by_char (TextChunk *chunk, int start, int end) { - char *s; + BoundaryRect char_bounds; int i; - int len; - gunichar c; GString *string = g_string_new (""); - BoundaryRect char_bounds; - if (!chunk->text_bounds.isClipped) - s = chunk->string; - else if (chunk->source) { - len = chunk->end_offset - chunk->start_offset; -#ifdef CLIP_DEBUG - fprintf (stderr, "clipping %s\n", chunk->string); -#endif - for (i = 0; i < len; ++i) { - AccessibleText_getCharacterExtents (chunk->source, - i, - &char_bounds.x, - &char_bounds.y, - &char_bounds.width, - &char_bounds.height, - SPI_COORD_TYPE_SCREEN); + gunichar c; + for (i = start; i < end; ++i) { + AccessibleText_getCharacterExtents (chunk->source, + i, + &char_bounds.x, + &char_bounds.y, + &char_bounds.width, + &char_bounds.height, + SPI_COORD_TYPE_SCREEN); #ifdef CHARACTER_CLIP_DEBUG - fprintf (stderr, "testing %d-%d against %d-%d\n", - char_bounds.x, char_bounds.x+char_bounds.width, - chunk->text_bounds.x, - chunk->text_bounds.x + chunk->text_bounds.width); + fprintf (stderr, "testing %d-%d against %d-%d\n", + char_bounds.x, char_bounds.x+char_bounds.width, + chunk->text_bounds.x, + chunk->text_bounds.x + chunk->text_bounds.width); #endif - if (BOUNDS_CONTAIN_X (&chunk->text_bounds, - char_bounds.x)) { - c = AccessibleText_getCharacterAtOffset ( - chunk->source, i); + if (BOUNDS_CONTAIN_X_BOUNDS (chunk->text_bounds, + char_bounds)) { + c = AccessibleText_getCharacterAtOffset ( + chunk->source, i); #ifdef CLIP_DEBUG - fprintf (stderr, "[%c]", c); + fprintf (stderr, "[%c]", c); #endif - g_string_append_unichar (string, c); - } + g_string_append_unichar (string, c); } - s = string->str; + } + return string->str; + g_string_free (string, FALSE); + +} + + +/* + * Note: this routine shouldn't have to do as much as it currently does, + * but at the moment it works around a pango?/gail? bug which + * causes WORD boundary type queries to return incorrect strings. + */ +static char * +string_strip_newlines (char *s, long offset, long *start_offset, long *end_offset) +{ + int i; + char *word_start = s; + /* FIXME: potential memory leak here */ + for (i=0; s && s[i]; ++i) + { + if (s [i] == '\n' && i > (offset - *start_offset) ) { + s [i] = '\0'; + *end_offset = *start_offset + i; + return word_start; + } else if (s [i] == '\n') { + word_start = &s[i + 1]; + } + } + return word_start; +} + +static char* +text_chunk_get_clipped_string (TextChunk *chunk) +{ + char *s, *string = ""; + int i; + long start = chunk->start_offset, end = chunk->end_offset; + long word_start, word_end, range_end; + BoundaryRect start_bounds, end_bounds; + gboolean start_inside, end_inside; + if (!chunk->text_bounds.isClipped) + string = chunk->string; + else if (chunk->source) { +#ifdef CLIP_DEBUG + fprintf (stderr, "clipping %s\n", chunk->string); +#endif + /* while words at offset lie within the bounds, add them */ + do { + s = AccessibleText_getTextAtOffset (chunk->source, + start, + SPI_TEXT_BOUNDARY_WORD_START, + &word_start, + &word_end); + range_end = word_end; + s = string_strip_newlines (s, start, &word_start, &word_end); + AccessibleText_getCharacterExtents (chunk->source, + word_start, + &start_bounds.x, + &start_bounds.y, + &start_bounds.width, + &start_bounds.height, + SPI_COORD_TYPE_SCREEN); + AccessibleText_getCharacterExtents (chunk->source, + word_end - 1, + &end_bounds.x, + &end_bounds.y, + &end_bounds.width, + &end_bounds.height, + SPI_COORD_TYPE_SCREEN); + start_inside = BOUNDS_CONTAIN_X_BOUNDS (chunk->text_bounds, + start_bounds); + end_inside = BOUNDS_CONTAIN_X_BOUNDS (chunk->text_bounds, + end_bounds); + if (start_inside && end_inside) { + /* word is contained in bounds */ + string = g_strconcat (string, s, NULL); + } else if (start_inside || end_inside) { + /* one end of word is in */ + if (word_end > end) word_end = end; + s = text_chunk_get_clipped_substring_by_char ( + chunk, + MAX (word_start, chunk->start_offset), + MIN (word_end, chunk->end_offset)); + string = g_strconcat (string, s, NULL); + } else { + } + start = range_end; + } while (start < chunk->end_offset); } else { /* we're clipped, but don't implement AccessibleText :-( */ /* punt for now, maybe we can do betterc someday */ - s = chunk->string; + string = chunk->string; } - g_string_free (string, FALSE); - return s; + return string; } static char* @@ -690,16 +823,21 @@ review_buffer_composite (ScreenReviewBuffer *buffers[]) 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) { iter = buffers[i]->text_chunks; +#ifdef CLIP_DEBUG fprintf (stderr, "layer %d has %d chunks\n", i, g_list_length (iter)); +#endif while (iter) { chunk = (TextChunk *) iter->data; if (chunk) { +#ifdef CLIP_DEBUG fprintf (stderr, "inserting chunk <%s>\n", - chunk->string); + chunk->string ? chunk->string : ""); +#endif chunk_list = text_chunk_list_insert_chunk (chunk_list, chunk); @@ -707,6 +845,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); } @@ -791,12 +930,12 @@ get_screen_review_line_at (int x, int y) for (i = 0; i < SPI_LAYER_LAST_DEFINED; ++i) { *clip_bounds[i] = toplevel_bounds; } -#ifdef CLIP_DEBUG - fprintf (stderr, "toplevel clip starting\n"); - debug_chunk_list (reviewBuffers[SPI_LAYER_WIDGET]->text_chunks); -#endif clip_into_buffers (toplevel, clip_bounds, reviewBuffers, x, y); +#ifdef CHUNK_LIST_DEBUG + fprintf (stderr, "toplevel clip done\n"); + debug_chunk_list (reviewBuffers[SPI_LAYER_WIDGET]->text_chunks); +#endif } } Accessible_unref (toplevel);