Beispiel #1
0
static void maybeEmitTextFocusChange(RefPtr<AccessibilityObject>&& object)
{
    // This static variable is needed to keep track of the old object
    // as per previous calls to this function, in order to properly
    // decide whether to emit some signals or not.
    static NeverDestroyed<RefPtr<AccessibilityObject>> oldObject;

    // Ensure the oldObject belongs to the same document that the
    // current object so further comparisons make sense. Otherwise,
    // just reset oldObject to 0 so it won't be taken into account in
    // the immediately following call to this function.
    if (object && oldObject.get() && oldObject.get()->document() != object->document())
        oldObject.get() = nullptr;

    AtkObject* axObject = object ? object->wrapper() : 0;
    AtkObject* oldAxObject = oldObject.get() ? oldObject.get()->wrapper() : nullptr;

    if (axObject != oldAxObject) {
        if (oldAxObject && ATK_IS_TEXT(oldAxObject)) {
            g_signal_emit_by_name(oldAxObject, "focus-event", false);
            atk_object_notify_state_change(oldAxObject, ATK_STATE_FOCUSED, false);
        }
        if (axObject && ATK_IS_TEXT(axObject)) {
            g_signal_emit_by_name(axObject, "focus-event", true);
            atk_object_notify_state_change(axObject, ATK_STATE_FOCUSED, true);
        }
    }

    // Update pointer to last focused object.
    oldObject.get() = WTFMove(object);
}
static void
_do_test(AtkObject *obj)
{
   const char *type_name = g_type_name(G_TYPE_FROM_INSTANCE(obj));
   AtkStateSet *state_set = atk_object_ref_state_set(obj);

   g_assert_cmpstr(type_name, ==, "EailLabel");

   /**
    * AtkText tests
    */
   g_assert(ATK_IS_TEXT(obj));

   g_assert(atk_state_set_contains_state(state_set, ATK_STATE_MULTI_LINE));
   g_object_unref(state_set);

   /* atk_text_get_text */
   gchar *text = atk_text_get_text(ATK_TEXT(obj), 6, 11);
   g_assert_cmpstr(text, ==, "ipsum");
   g_free(text);

   /* atk_text_get_character_at_offset */
   g_assert(atk_text_get_character_at_offset(ATK_TEXT(obj), 12) == 'd');

   /* atk_text_get_character_count */
   g_assert(atk_text_get_character_count(ATK_TEXT(obj)) == 440);
}
Beispiel #3
0
static void test_webkit_atk_get_text_at_offset_text_input(void)
{
    WebKitWebView* webView;
    AtkObject* obj;
    GMainLoop* loop;
    AtkText* text_obj;

    webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
    g_object_ref_sink(webView);
    GtkAllocation alloc = { 0, 0, 800, 600 };
    gtk_widget_size_allocate(GTK_WIDGET(webView), &alloc);
    webkit_web_view_load_string(webView, contentsInTextInput, NULL, NULL, NULL);
    loop = g_main_loop_new(NULL, TRUE);

    g_timeout_add(100, (GSourceFunc)bail_out, loop);
    g_main_loop_run(loop);

    /* Get to the inner AtkText object */
    obj = gtk_widget_get_accessible(GTK_WIDGET(webView));
    g_assert(obj);
    obj = atk_object_ref_accessible_child(obj, 0);
    g_assert(obj);
    obj = atk_object_ref_accessible_child(obj, 0);
    g_assert(obj);

    text_obj = ATK_TEXT(obj);
    g_assert(ATK_IS_TEXT(text_obj));

    run_get_text_tests(text_obj);

    g_object_unref(webView);
}
Beispiel #4
0
static const char *
get_name (AtkObject *accessible)
{
  char *name;

  name = g_object_get_data (G_OBJECT (accessible), "gtk-accessibility-dump-name");
  if (name)
    return name;

  if (GTK_IS_ACCESSIBLE (accessible))
    {
      GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible));

      name = g_strdup (gtk_buildable_get_name (GTK_BUILDABLE (widget)));
    }

  if (name == NULL && ATK_IS_TEXT (accessible))
    {
      name = atk_text_get_text (ATK_TEXT (accessible), 0, -1);
    }

  if (name == NULL)
    {
      /* Generate a unique, repeatable name */
      name = g_strdup_printf ("unnamed-%s-%d", G_OBJECT_TYPE_NAME (accessible), unnamed_object_count++);
    }

  g_object_set_data_full (G_OBJECT (accessible), "gtk-accessibility-dump-name", name, g_free);
  return name;
}
JSRetainPtr<JSStringRef> AccessibilityUIElement::stringAttributeValue(JSStringRef attribute)
{
    if (!ATK_IS_OBJECT(m_element.get()))
        return JSStringCreateWithCharacters(0, 0);

    String atkAttributeName = coreAttributeToAtkAttribute(attribute);

    // Try object attributes first.
    String attributeValue = getAttributeSetValueForId(ATK_OBJECT(m_element.get()), ObjectAttributeType, atkAttributeName);

    // Try text attributes if the requested one was not found and we have an AtkText object.
    if (attributeValue.isEmpty() && ATK_IS_TEXT(m_element.get()))
        attributeValue = getAttributeSetValueForId(ATK_OBJECT(m_element.get()), TextAttributeType, atkAttributeName);

    // Additional check to make sure that the exposure of the state ATK_STATE_INVALID_ENTRY
    // is consistent with the exposure of aria-invalid as a text attribute, if present.
    if (atkAttributeName == attributesMap[InvalidNameIndex][AtkDomain]) {
        bool isInvalidState = checkElementState(m_element.get(), ATK_STATE_INVALID_ENTRY);
        if (attributeValue.isEmpty())
            return JSStringCreateWithUTF8CString(isInvalidState ? "true" : "false");

        // If the text attribute was there, check that it's consistent with
        // what the state says or force the test to fail otherwise.
        bool isAriaInvalid = attributeValue != "false";
        if (isInvalidState != isAriaInvalid)
            return JSStringCreateWithCharacters(0, 0);
    }

    return JSStringCreateWithUTF8CString(attributeValue.utf8().data());
}
void AccessibilityUIElement::setSelectedTextRange(unsigned location, unsigned length)
{
    if (!ATK_IS_TEXT(m_element.get()))
        return;

    atk_text_set_selection(ATK_TEXT(m_element.get()), 0, location, location + length);
}
Beispiel #7
0
static void testWebkitAtkGetTextInParagraphAndBodyModerate(void)
{
    WebKitWebView* webView;
    AtkObject* obj;
    AtkObject* obj1;
    AtkObject* obj2;
    GMainLoop* loop;
    AtkText* textObj1;
    AtkText* textObj2;

    webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
    g_object_ref_sink(webView);
    GtkAllocation alloc = { 0, 0, 800, 600 };
    gtk_widget_size_allocate(GTK_WIDGET(webView), &alloc);
    webkit_web_view_load_string(webView, contentsInParagraphAndBodyModerate, NULL, NULL, NULL);
    loop = g_main_loop_new(NULL, TRUE);

    g_timeout_add(100, (GSourceFunc)bail_out, loop);
    g_main_loop_run(loop);

    /* Get to the inner AtkText object */
    obj = gtk_widget_get_accessible(GTK_WIDGET(webView));
    g_assert(obj);
    obj1 = atk_object_ref_accessible_child(obj, 0);
    g_assert(obj1);
    obj2 = atk_object_ref_accessible_child(obj, 1);
    g_assert(obj2);

    textObj1 = ATK_TEXT(obj1);
    g_assert(ATK_IS_TEXT(textObj1));
    textObj2 = ATK_TEXT(obj2);
    g_assert(ATK_IS_TEXT(textObj2));

    char *text = atk_text_get_text(textObj1, 0, -1);
    g_assert_cmpstr(text, ==, "This is a test.");

    text = atk_text_get_text(textObj2, 0, 53);
    g_assert_cmpstr(text, ==, "Hello world.\nThis sentence is green.\nThis one is not.");

    g_object_unref(obj1);
    g_object_unref(obj2);
    g_object_unref(webView);
}
JSRetainPtr<JSStringRef> AccessibilityUIElement::selectedTextRange()
{
    if (!ATK_IS_TEXT(m_element.get()))
        return JSStringCreateWithCharacters(0, 0);

    gint start, end;
    g_free(atk_text_get_selection(ATK_TEXT(m_element.get()), 0, &start, &end));

    GOwnPtr<gchar> selection(g_strdup_printf("{%d, %d}", start, end - start));
    return JSStringCreateWithUTF8CString(selection.get());
}
JSStringRef AccessibilityUIElement::stringValue()
{
    if (!m_element || !ATK_IS_TEXT(m_element))
        return JSStringCreateWithCharacters(0, 0);

    GOwnPtr<gchar> text(atk_text_get_text(ATK_TEXT(m_element), 0, -1));
    GOwnPtr<gchar> textWithReplacedCharacters(replaceCharactersForResults(text.get()));
    GOwnPtr<gchar> axValue(g_strdup_printf("AXValue: %s", textWithReplacedCharacters.get()));

    return JSStringCreateWithUTF8CString(axValue.get());
}
Beispiel #10
0
void AXObjectCache::nodeTextChangePlatformNotification(AccessibilityObject* object, AXTextChange textChange, unsigned offset, const String& text)
{
    if (!object || text.isEmpty())
        return;

    AccessibilityObject* parentObject = object->parentObjectUnignored();
    if (!parentObject)
        return;

    AtkObject* wrapper = parentObject->wrapper();
    if (!wrapper || !ATK_IS_TEXT(wrapper))
        return;

    Node* node = object->node();
    if (!node)
        return;

    // Ensure document's layout is up-to-date before using TextIterator.
    Document& document = node->document();
    document.updateLayout();

    // Select the right signal to be emitted
    CString detail;
    switch (textChange) {
    case AXTextInserted:
        detail = "text-insert";
        break;
    case AXTextDeleted:
        detail = "text-remove";
        break;
    case AXTextAttributesChanged:
        detail = "text-attributes-changed";
        break;
    }

    String textToEmit = text;
    unsigned offsetToEmit = offset;

    // If the object we're emitting the signal from represents a
    // password field, we will emit the masked text.
    if (parentObject->isPasswordField()) {
        String maskedText = parentObject->passwordFieldValue();
        textToEmit = maskedText.substring(offset, text.length());
    } else {
        // Consider previous text objects that might be present for
        // the current accessibility object to ensure we emit the
        // right offset (e.g. multiline text areas).
        RefPtr<Range> range = Range::create(document, node->parentNode(), 0, node, 0);
        offsetToEmit = offset + TextIterator::rangeLength(range.get());
    }

    g_signal_emit_by_name(wrapper, detail.data(), offsetToEmit, textToEmit.length(), textToEmit.utf8().data());
}
Beispiel #11
0
static void emitTextSelectionChange(AccessibilityObject* object, VisibleSelection selection, int offset)
{
    AtkObject* axObject = object->wrapper();
    if (!axObject || !ATK_IS_TEXT(axObject))
        return;

    // We need to adjust the offset for the list item marker in Left-To-Right text because
    // the list item marker is exposed through the text of the accessible list item rather
    // than through a separate accessible object.
    RenderObject* renderer = object->renderer();
    if (is<RenderListItem>(renderer) && renderer->style().direction() == LTR)
        offset += downcast<RenderListItem>(*renderer).markerTextWithSuffix().length();

    g_signal_emit_by_name(axObject, "text-caret-moved", offset);
    if (selection.isRange())
        g_signal_emit_by_name(axObject, "text-selection-changed");
}
// parameterized attributes
int AccessibilityUIElement::lineForIndex(int index)
{
    if (!ATK_IS_TEXT(m_element.get()))
        return -1;

    if (index < 0 || index > atk_text_get_character_count(ATK_TEXT(m_element.get())))
        return -1;

    GOwnPtr<gchar> text(atk_text_get_text(ATK_TEXT(m_element.get()), 0, index));
    int lineNo = 0;
    for (gchar* offset = text.get(); *offset; ++offset) {
        if (*offset == '\n')
            ++lineNo;
    }

    return lineNo;
}
static void
_do_test(AtkObject *obj)
{
   const char *type_name = g_type_name(G_TYPE_FROM_INSTANCE(obj));
   const char *name = atk_object_get_name(ATK_OBJECT(obj));
   const char *type_name_child;
   AtkStateSet *state_set;
   AtkObject *xobj;

   _printf("type_name: %s\n", type_name ? type_name : "NULL");
   g_assert(name);
   _printf("name: %s\n", name);

   g_assert_cmpstr(type_name, ==, "EailCheck");

   g_assert(ATK_IS_OBJECT(obj));
   g_assert(ATK_IS_ACTION(obj));
   g_assert(ATK_IS_TEXT(obj));

   state_set = atk_object_ref_state_set(obj);

   if (!strcmp(name, CHECK_TEXT1))
     {
        _printf("check test: %s\n", CHECK_TEXT1);

        g_assert(atk_state_set_contains_state(state_set, ATK_STATE_CHECKED));

        // test children
        g_assert(0 == atk_object_get_n_accessible_children(obj));
     }
   else if (!strcmp(name, CHECK_TEXT2))
     {
       _printf("check test: %s\n", CHECK_TEXT2);

       g_assert(!atk_state_set_contains_state(state_set, ATK_STATE_CHECKED));

       // test children
       g_assert(1 == atk_object_get_n_accessible_children(obj));

       xobj = atk_object_ref_accessible_child(obj, 0);
       g_assert(NULL != xobj);
       type_name_child = g_type_name(G_TYPE_FROM_INSTANCE(xobj));
       _printf("type_name_child: %s\n", type_name_child);
       g_assert_cmpstr(type_name_child, ==, "EailIcon");
     }
Beispiel #14
0
static void _set_values (AtkObject *obj) {

  GValue *value_back, val;
  static gint count = 0;
  gdouble double_value;

  value_back = &val;

  if(ATK_IS_VALUE(obj)) {
	/* Spin button also inherits the text interfaces from GailEntry. 
	 * Check when spin button recieves focus.
     */

	if(ATK_IS_TEXT(obj) && ATK_IS_EDITABLE_TEXT(obj)) {
		if(count == 0) {	
			gint x;
			gchar* text;
			count++;
			x = atk_text_get_character_count (ATK_TEXT (obj));
  			text = atk_text_get_text (ATK_TEXT (obj), 0, x);
			g_print("Text : %s\n", text);
			text = "5.7";
			atk_editable_text_set_text_contents(ATK_EDITABLE_TEXT(obj),text);
			g_print("Set text to %s\n",text);
			atk_value_get_current_value(ATK_VALUE(obj), value_back);
			g_return_if_fail (G_VALUE_HOLDS_DOUBLE (value_back));
			g_print("atk_value_get_current_value returns %f\n", 
				g_value_get_double( value_back));
			} 
	} else {
		memset (value_back, 0, sizeof (GValue));
		g_value_init (value_back, G_TYPE_DOUBLE);
		g_value_set_double (value_back, 10.0);	
		if (atk_value_set_current_value (ATK_VALUE (obj), value_back))
		{
 			double_value = g_value_get_double (value_back);
  			g_print("atk_value_set_current_value returns %f\n", 
			double_value);
		}
	}
  }
}
JSStringRef AccessibilityUIElement::language()
{
    if (!m_element)
        return JSStringCreateWithCharacters(0, 0);

    // In ATK, the document language is exposed as the document's locale.
    if (atk_object_get_role(ATK_OBJECT(m_element)) == ATK_ROLE_DOCUMENT_FRAME)
        return JSStringCreateWithUTF8CString(g_strdup_printf("AXLanguage: %s", atk_document_get_locale(ATK_DOCUMENT(m_element))));

    // For all other objects, the language is exposed as an AtkText attribute.
    if (!ATK_IS_TEXT(m_element))
        return JSStringCreateWithCharacters(0, 0);

    for (GSList* textAttributes = atk_text_get_default_attributes(ATK_TEXT(m_element)); textAttributes; textAttributes = textAttributes->next) {
        AtkAttribute* atkAttribute = static_cast<AtkAttribute*>(textAttributes->data);
        if (!strcmp(atkAttribute->name, atk_text_attribute_get_name(ATK_TEXT_ATTR_LANGUAGE)))
            return JSStringCreateWithUTF8CString(g_strdup_printf("AXLanguage: %s", atkAttribute->value));
    }

    return JSStringCreateWithCharacters(0, 0);
}
Beispiel #16
0
SpiAccessible *
spi_accessible_construct (GType type, AtkObject *o)
{
    SpiAccessible *retval;
    CORBA_Environment ev;

    CORBA_exception_init (&ev);

    g_assert (o);
    g_assert (g_type_is_a (type, SPI_ACCESSIBLE_TYPE));

    if ((retval = g_hash_table_lookup (get_public_refs (), o)))
      {
        bonobo_object_ref (BONOBO_OBJECT (retval));
	return retval;
      }
    else
      {
        retval = g_object_new (type, NULL);
        spi_base_construct (SPI_BASE (retval), G_OBJECT(o));
      }
    
    g_hash_table_insert (get_public_refs (), o, retval);
    g_signal_connect (G_OBJECT (retval), "destroy",
		      G_CALLBACK (de_register_public_ref),
		      NULL);

    /* aggregate appropriate SPI interfaces based on ATK interfaces */
 
    if (ATK_IS_ACTION (o))
      {
        bonobo_object_add_interface (bonobo_object (retval),
		BONOBO_OBJECT (spi_action_interface_new (o)));
      }

    if (ATK_IS_COMPONENT (o))
      {
        bonobo_object_add_interface (bonobo_object (retval),
				     BONOBO_OBJECT (spi_component_interface_new (o)));
      }

    if (ATK_IS_EDITABLE_TEXT (o))
      {
         bonobo_object_add_interface (bonobo_object (retval),
				      BONOBO_OBJECT(spi_editable_text_interface_new (o)));
      }

    else if (ATK_IS_TEXT (o))
       {
         bonobo_object_add_interface (bonobo_object (retval),
				      BONOBO_OBJECT (spi_text_interface_new (o)));
       }

    if (ATK_IS_HYPERTEXT (o))
      {
        bonobo_object_add_interface (bonobo_object (retval),
				     BONOBO_OBJECT (spi_hypertext_interface_new (o)));
      }

    if (ATK_IS_IMAGE (o))
      {
        bonobo_object_add_interface (bonobo_object (retval),
				     BONOBO_OBJECT (spi_image_interface_new (o)));
      }

    if (ATK_IS_SELECTION (o))
      {
        bonobo_object_add_interface (bonobo_object (retval),
				     BONOBO_OBJECT (spi_selection_interface_new (o)));
      }

    if (ATK_IS_TABLE (o))
      {
        bonobo_object_add_interface (bonobo_object (retval),
				     BONOBO_OBJECT (spi_table_interface_new (o)));
      }

    if (ATK_IS_VALUE (o))
      {
        bonobo_object_add_interface (bonobo_object (retval),
				     BONOBO_OBJECT (spi_value_interface_new (o)));
      }

    if (ATK_IS_STREAMABLE_CONTENT (o))
      {
        bonobo_object_add_interface (bonobo_object (retval),
				     BONOBO_OBJECT (spi_streamable_interface_new (o)));
      }
    if (ATK_IS_DOCUMENT (o)) /* We add collection interface to document */
      {

	   
	 SpiDocument *doc = spi_document_interface_new (o);
	 bonobo_object_add_interface (BONOBO_OBJECT (doc), 
				      BONOBO_OBJECT (spi_collection_interface_new (o)));

	 bonobo_object_add_interface (bonobo_object (retval),
					BONOBO_OBJECT (doc));
      }
    if (ATK_IS_HYPERLINK_IMPL (o))
      {
	  /* !!! the cast below is used instead of the ATK_HYPERLINK macro, since 
	   the object 'o' is not really a hyperlink, but is in fact an AtkHyperlinkImpl.
	   Ouch.  This works since it gets cast back to GObject, but it's nasty and needs
	   to be cleaned up.
	  */
	bonobo_object_add_interface (bonobo_object (retval),
				     BONOBO_OBJECT (spi_hyperlink_new ((AtkHyperlink*)o)));
      }

    return retval;
}
static void test_webkit_atk_get_text_at_offset(void)
{
    WebKitWebView* webView;
    AtkObject *obj;
    GMainLoop* loop;
    AtkText* text_obj;
    char* text;

    webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
    g_object_ref_sink(webView);
    webkit_web_view_load_string(webView, contents, NULL, NULL, NULL);
    loop = g_main_loop_new(NULL, TRUE);

    g_timeout_add(100, (GSourceFunc)bail_out, loop);
    g_main_loop_run(loop);

    /* Get to the inner AtkText object */
    obj = gtk_widget_get_accessible(GTK_WIDGET(webView));
    g_assert(obj);
    obj = atk_object_ref_accessible_child(obj, 0);
    g_assert(obj);
    obj = atk_object_ref_accessible_child(obj, 0);
    g_assert(obj);

    text_obj = ATK_TEXT(obj);
    g_assert(ATK_IS_TEXT(text_obj));

    text = atk_text_get_text(text_obj, 0, -1);
    g_assert_cmpstr(text, ==, "This is a test. This is the second sentence. And this the third.");
    g_free(text);

    /* ATK_TEXT_BOUNDARY_CHAR */
    test_get_text_function(text_obj, atk_text_get_text_at_offset, ATK_TEXT_BOUNDARY_CHAR,
                           0, "T", 0, 1);

    test_get_text_function(text_obj, atk_text_get_text_after_offset, ATK_TEXT_BOUNDARY_CHAR,
                           0, "h", 1, 2);

    test_get_text_function(text_obj, atk_text_get_text_before_offset, ATK_TEXT_BOUNDARY_CHAR,
                           0, "", 0, 0);

    test_get_text_function(text_obj, atk_text_get_text_before_offset, ATK_TEXT_BOUNDARY_CHAR,
                           1, "T", 0, 1);
    
    /* ATK_TEXT_BOUNDARY_WORD_START */
    test_get_text_function(text_obj, atk_text_get_text_at_offset, ATK_TEXT_BOUNDARY_WORD_START,
                           0, "This ", 0, 5);

    test_get_text_function(text_obj, atk_text_get_text_at_offset, ATK_TEXT_BOUNDARY_WORD_START,
                           4, "This ", 0, 5);

    test_get_text_function(text_obj, atk_text_get_text_at_offset, ATK_TEXT_BOUNDARY_WORD_START,
                           10, "test. ", 10, 16);

    test_get_text_function(text_obj, atk_text_get_text_at_offset, ATK_TEXT_BOUNDARY_WORD_START,
                           58, "third.", 58, 64);

    test_get_text_function(text_obj, atk_text_get_text_before_offset, ATK_TEXT_BOUNDARY_WORD_START,
                           5, "This ", 0, 5);

    test_get_text_function(text_obj, atk_text_get_text_before_offset, ATK_TEXT_BOUNDARY_WORD_START,
                           7, "This ", 0, 5);

    test_get_text_function(text_obj, atk_text_get_text_after_offset, ATK_TEXT_BOUNDARY_WORD_START,
                           0, "is ", 5, 8);

    test_get_text_function(text_obj, atk_text_get_text_after_offset, ATK_TEXT_BOUNDARY_WORD_START,
                           4, "is ", 5, 8);

    test_get_text_function(text_obj, atk_text_get_text_after_offset, ATK_TEXT_BOUNDARY_WORD_START,
                           3, "is ", 5, 8);

    /* ATK_TEXT_BOUNDARY_WORD_END */
    test_get_text_function(text_obj, atk_text_get_text_at_offset, ATK_TEXT_BOUNDARY_WORD_END,
                           0, "This", 0, 4);

    test_get_text_function(text_obj, atk_text_get_text_at_offset, ATK_TEXT_BOUNDARY_WORD_END,
                           4, " is", 4, 7);

    test_get_text_function(text_obj, atk_text_get_text_at_offset, ATK_TEXT_BOUNDARY_WORD_END,
                           5, " is", 4, 7);

    test_get_text_function(text_obj, atk_text_get_text_at_offset, ATK_TEXT_BOUNDARY_WORD_END,
                           9, " test", 9, 14);

    test_get_text_function(text_obj, atk_text_get_text_before_offset, ATK_TEXT_BOUNDARY_WORD_END,
                           5, "This", 0, 4);

    test_get_text_function(text_obj, atk_text_get_text_before_offset, ATK_TEXT_BOUNDARY_WORD_END,
                           4, "This", 0, 4);

    test_get_text_function(text_obj, atk_text_get_text_before_offset, ATK_TEXT_BOUNDARY_WORD_END,
                           7, " is", 4, 7);

    test_get_text_function(text_obj, atk_text_get_text_after_offset, ATK_TEXT_BOUNDARY_WORD_END,
                           5, " a", 7, 9);

    test_get_text_function(text_obj, atk_text_get_text_after_offset, ATK_TEXT_BOUNDARY_WORD_END,
                           4, " a", 7, 9);

    test_get_text_function(text_obj, atk_text_get_text_at_offset, ATK_TEXT_BOUNDARY_WORD_END,
                           58, " third", 57, 63);

    /* ATK_TEXT_BOUNDARY_SENTENCE_START */
    test_get_text_function(text_obj, atk_text_get_text_at_offset, ATK_TEXT_BOUNDARY_SENTENCE_START,
                           0, "This is a test. ", 0, 16);

    test_get_text_function(text_obj, atk_text_get_text_at_offset, ATK_TEXT_BOUNDARY_SENTENCE_START,
                           15, "This is a test. ", 0, 16);

    test_get_text_function(text_obj, atk_text_get_text_after_offset, ATK_TEXT_BOUNDARY_SENTENCE_START,
                           0, "This is the second sentence. ", 16, 45);

    test_get_text_function(text_obj, atk_text_get_text_after_offset, ATK_TEXT_BOUNDARY_SENTENCE_START,
                           15, "This is the second sentence. ", 16, 45);

    test_get_text_function(text_obj, atk_text_get_text_before_offset, ATK_TEXT_BOUNDARY_SENTENCE_START,
                           16, "This is a test. ", 0, 16);

    test_get_text_function(text_obj, atk_text_get_text_before_offset, ATK_TEXT_BOUNDARY_SENTENCE_START,
                           44, "This is a test. ", 0, 16);

    test_get_text_function(text_obj, atk_text_get_text_before_offset, ATK_TEXT_BOUNDARY_SENTENCE_START,
                           15, "", 0, 0);

    /* ATK_TEXT_BOUNDARY_SENTENCE_END */
    test_get_text_function(text_obj, atk_text_get_text_at_offset, ATK_TEXT_BOUNDARY_SENTENCE_END,
                           0, "This is a test.", 0, 15);

    test_get_text_function(text_obj, atk_text_get_text_at_offset, ATK_TEXT_BOUNDARY_SENTENCE_END,
                           15, " This is the second sentence.", 15, 44);

    test_get_text_function(text_obj, atk_text_get_text_at_offset, ATK_TEXT_BOUNDARY_SENTENCE_END,
                           16, " This is the second sentence.", 15, 44);

    test_get_text_function(text_obj, atk_text_get_text_at_offset, ATK_TEXT_BOUNDARY_SENTENCE_END,
                           17, " This is the second sentence.", 15, 44);

    test_get_text_function(text_obj, atk_text_get_text_after_offset, ATK_TEXT_BOUNDARY_SENTENCE_END,
                           0, " This is the second sentence.", 15, 44);

    test_get_text_function(text_obj, atk_text_get_text_after_offset, ATK_TEXT_BOUNDARY_SENTENCE_END,
                           15, " And this the third.", 44, 64);

    test_get_text_function(text_obj, atk_text_get_text_before_offset, ATK_TEXT_BOUNDARY_SENTENCE_END,
                           16, "This is a test.", 0, 15);

    test_get_text_function(text_obj, atk_text_get_text_before_offset, ATK_TEXT_BOUNDARY_SENTENCE_END,
                           15, "This is a test.", 0, 15);

    test_get_text_function(text_obj, atk_text_get_text_before_offset, ATK_TEXT_BOUNDARY_SENTENCE_END,
                           14, "", 0, 0);

    test_get_text_function(text_obj, atk_text_get_text_before_offset, ATK_TEXT_BOUNDARY_SENTENCE_END,
                           44, " This is the second sentence.", 15, 44);

    /* It's trick to test these properly right now, since our a11y
       implementation splits different lines in different a11y
       items */
    /* ATK_TEXT_BOUNDARY_LINE_START */
    test_get_text_function(text_obj, atk_text_get_text_at_offset, ATK_TEXT_BOUNDARY_LINE_START,
                           0, "This is a test. This is the second sentence. And this the third.", 0, 64);

    /* ATK_TEXT_BOUNDARY_LINE_END */
    test_get_text_function(text_obj, atk_text_get_text_at_offset, ATK_TEXT_BOUNDARY_LINE_END,
                           0, "This is a test. This is the second sentence. And this the third.", 0, 64);

    g_object_unref(webView);
}