[SCM] WebKit Debian packaging branch, debian/experimental, updated. upstream/1.3.3-9427-gc2be6fc

mario at webkit.org mario at webkit.org
Wed Dec 22 16:18:09 UTC 2010


The following commit has been merged in the debian/experimental branch:
commit 234e740c063e19b88a6068b09c7bfee804f28564
Author: mario at webkit.org <mario at webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Sun Nov 21 23:03:30 2010 +0000

    2010-11-21  Mario Sanchez Prada  <msanchez at igalia.com>
    
            Reviewed by Chris Fleizach.
    
            [GTK] Implement ROLE_COMBO_BOX
            https://bugs.webkit.org/show_bug.cgi?id=25678
    
            Implement the remaining bits for combo boxes.
    
            This patch finishes the implementation, from the point of view of
            the Atk library, of those objects exposed to ATK as combo boxes,
            and their related elements (menus and menu items). It therefore
            implements the proper interfaces for each type of object related
            to combo boxes (AtkSelection for the combo box, AtkText for every
            menu item and AtkAction for the combo box, the menu and the menu
            items), takes care of emitting the proper signals when focus or a
            given a selection changes and adds a new unit test to check all
            this new stuff.
    
            Make possible to ask an AccessibleMenuListOption for a sensible
            string representation, so far only available through the private
            and MSAA related method nameForMSAA. Just moved the implementation
            of that method to an overriden version of stringValue(), which is
            platform independent, and called that from nameForMSAA().
    
            * accessibility/AccessibilityMenuListOption.h:
            * accessibility/AccessibilityMenuListOption.cpp:
            (WebCore::AccessibilityMenuListOption::nameForMSAA): Just call to
            stringValue(), which holds from now on that used to be here.
            (WebCore::AccessibilityMenuListOption::stringValue): New, override
            of AccessibilityObject::stringValue() to return a proper string.
    
            Emit the missing signals when a selection is made.
    
            * accessibility/gtk/AXObjectCacheAtk.cpp:
            (WebCore::AXObjectCache::postPlatformNotification): Emit the usual
            'focus' signals when a selection is made over the combo box.
    
            * accessibility/gtk/AccessibilityObjectWrapperAtk.cpp:
            (setAtkStateSetFromCoreObject): Ensure the EXPANDABLE and EXPANDED
            Atk states are added to the state set when needed.
            (listObjectForSelection): New, returns the proper list object (the
            one holding the list of available options as its children) for an
            specific AtkObject implementing AtkSelection. This is needed
            because sometimes the selectable options are not directly children
            of the AtkSelection object (i.e. a combo box has a 'menu' object
            as its only child of it, holding the list of options as children).
            (optionFromList): Use listObjectForSelection() to get the actual
            object holding the list of children as the available options.
            (optionFromSelection): Add support for combo boxes.
            (webkit_accessible_selection_add_selection): Ditto.
            (webkit_accessible_selection_clear_selection): Ditto.
            (webkit_accessible_selection_get_selection_count): Ditto.
            (webkit_accessible_selection_is_child_selected): Ditto.
            (webkit_accessible_selection_remove_selection): Ditto.
            (webkit_accessible_text_get_text): Makes sure stringValue() is
            considered to get the result substring when it was already
            considered when checking the maximum text length for the object.
            (getInterfaceMaskFromObject): Make sure the AtkSelection interface
            is implemented for the combo boxes, that the AtkText is
            implemented for the menu items and that the AtkAction interface is
            now implemented for every object (WebCore will decide what to do).
    
            Avoid a segfault crash when using this from unit tests.
    
            * platform/gtk/PopupMenuGtk.cpp:
            (WebCore::PopupMenuGtk::show): Make sure we got a valid GdkWindow
            before calling gdk_window_get_origin() over it.
    2010-11-21  Mario Sanchez Prada  <msanchez at igalia.com>
    
            Reviewed by Chris Fleizach.
    
            [GTK] Implement ROLE_COMBO_BOX
            https://bugs.webkit.org/show_bug.cgi?id=25678
    
            New test to check the implementation of the combo boxes.
    
            * tests/testatk.c:
            (testWebkitAtkComboBox): New test, checking that the roles and the
            implemented interfaces for a combo box and its descendants work.
            (main): Added the new unit test.
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@72499 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 68ce856..17486a7 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,72 @@
+2010-11-21  Mario Sanchez Prada  <msanchez at igalia.com>
+
+        Reviewed by Chris Fleizach.
+
+        [GTK] Implement ROLE_COMBO_BOX
+        https://bugs.webkit.org/show_bug.cgi?id=25678
+
+        Implement the remaining bits for combo boxes.
+
+        This patch finishes the implementation, from the point of view of
+        the Atk library, of those objects exposed to ATK as combo boxes,
+        and their related elements (menus and menu items). It therefore
+        implements the proper interfaces for each type of object related
+        to combo boxes (AtkSelection for the combo box, AtkText for every
+        menu item and AtkAction for the combo box, the menu and the menu
+        items), takes care of emitting the proper signals when focus or a
+        given a selection changes and adds a new unit test to check all
+        this new stuff.
+
+        Make possible to ask an AccessibleMenuListOption for a sensible
+        string representation, so far only available through the private
+        and MSAA related method nameForMSAA. Just moved the implementation
+        of that method to an overriden version of stringValue(), which is
+        platform independent, and called that from nameForMSAA().
+
+        * accessibility/AccessibilityMenuListOption.h:
+        * accessibility/AccessibilityMenuListOption.cpp:
+        (WebCore::AccessibilityMenuListOption::nameForMSAA): Just call to
+        stringValue(), which holds from now on that used to be here.
+        (WebCore::AccessibilityMenuListOption::stringValue): New, override
+        of AccessibilityObject::stringValue() to return a proper string.
+
+        Emit the missing signals when a selection is made.
+
+        * accessibility/gtk/AXObjectCacheAtk.cpp:
+        (WebCore::AXObjectCache::postPlatformNotification): Emit the usual
+        'focus' signals when a selection is made over the combo box.
+
+        * accessibility/gtk/AccessibilityObjectWrapperAtk.cpp:
+        (setAtkStateSetFromCoreObject): Ensure the EXPANDABLE and EXPANDED
+        Atk states are added to the state set when needed.
+        (listObjectForSelection): New, returns the proper list object (the
+        one holding the list of available options as its children) for an
+        specific AtkObject implementing AtkSelection. This is needed
+        because sometimes the selectable options are not directly children
+        of the AtkSelection object (i.e. a combo box has a 'menu' object
+        as its only child of it, holding the list of options as children).
+        (optionFromList): Use listObjectForSelection() to get the actual
+        object holding the list of children as the available options.
+        (optionFromSelection): Add support for combo boxes.
+        (webkit_accessible_selection_add_selection): Ditto.
+        (webkit_accessible_selection_clear_selection): Ditto.
+        (webkit_accessible_selection_get_selection_count): Ditto.
+        (webkit_accessible_selection_is_child_selected): Ditto.
+        (webkit_accessible_selection_remove_selection): Ditto.
+        (webkit_accessible_text_get_text): Makes sure stringValue() is
+        considered to get the result substring when it was already
+        considered when checking the maximum text length for the object.
+        (getInterfaceMaskFromObject): Make sure the AtkSelection interface
+        is implemented for the combo boxes, that the AtkText is
+        implemented for the menu items and that the AtkAction interface is
+        now implemented for every object (WebCore will decide what to do).
+
+        Avoid a segfault crash when using this from unit tests.
+
+        * platform/gtk/PopupMenuGtk.cpp:
+        (WebCore::PopupMenuGtk::show): Make sure we got a valid GdkWindow
+        before calling gdk_window_get_origin() over it.
+
 2010-11-21  Patrick Gansterer  <paroga at webkit.org>
 
         Reviewed by Csaba Osztrogonác.
diff --git a/WebCore/accessibility/AccessibilityMenuListOption.cpp b/WebCore/accessibility/AccessibilityMenuListOption.cpp
index d7473de..5bca580 100644
--- a/WebCore/accessibility/AccessibilityMenuListOption.cpp
+++ b/WebCore/accessibility/AccessibilityMenuListOption.cpp
@@ -91,7 +91,7 @@ void AccessibilityMenuListOption::setSelected(bool b)
 
 String AccessibilityMenuListOption::nameForMSAA() const
 {
-    return static_cast<HTMLOptionElement*>(m_element.get())->text();
+    return stringValue();
 }
 
 bool AccessibilityMenuListOption::canSetSelectedAttribute() const
@@ -110,4 +110,9 @@ IntRect AccessibilityMenuListOption::elementRect() const
     return grandparent->elementRect();
 }
 
+String AccessibilityMenuListOption::stringValue() const
+{
+    return static_cast<HTMLOptionElement*>(m_element.get())->text();
+}
+
 } // namespace WebCore
diff --git a/WebCore/accessibility/AccessibilityMenuListOption.h b/WebCore/accessibility/AccessibilityMenuListOption.h
index 7e27888..9393d56 100644
--- a/WebCore/accessibility/AccessibilityMenuListOption.h
+++ b/WebCore/accessibility/AccessibilityMenuListOption.h
@@ -59,6 +59,7 @@ private:
     virtual void setSelected(bool);
     virtual bool canSetSelectedAttribute() const;
     virtual IntRect elementRect() const;
+    virtual String stringValue() const;
 
     RefPtr<HTMLElement> m_element;
     AccessibilityMenuListPopup* m_popup;
diff --git a/WebCore/accessibility/gtk/AXObjectCacheAtk.cpp b/WebCore/accessibility/gtk/AXObjectCacheAtk.cpp
index 4216be4..c341a2d 100644
--- a/WebCore/accessibility/gtk/AXObjectCacheAtk.cpp
+++ b/WebCore/accessibility/gtk/AXObjectCacheAtk.cpp
@@ -95,10 +95,19 @@ static void notifyChildrenSelectionChange(AccessibilityObject* object)
 
 void AXObjectCache::postPlatformNotification(AccessibilityObject* coreObject, AXNotification notification)
 {
+    AtkObject* axObject = coreObject->wrapper();
+    if (!axObject)
+        return;
+
     if (notification == AXCheckedStateChanged) {
         if (!coreObject->isCheckboxOrRadio())
             return;
-        g_signal_emit_by_name(coreObject->wrapper(), "state-change", "checked", coreObject->isChecked());
+        g_signal_emit_by_name(axObject, "state-change", "checked", coreObject->isChecked());
+    } else if (notification == AXMenuListValueChanged) {
+        if (!coreObject->isMenuList())
+            return;
+        g_signal_emit_by_name(axObject, "focus-event", true);
+        g_signal_emit_by_name(axObject, "state-change", "focused", true);
     } else if (notification == AXSelectedChildrenChanged)
         notifyChildrenSelectionChange(coreObject);
 }
diff --git a/WebCore/accessibility/gtk/AccessibilityObjectWrapperAtk.cpp b/WebCore/accessibility/gtk/AccessibilityObjectWrapperAtk.cpp
index 3d4345a..ca0d80b 100644
--- a/WebCore/accessibility/gtk/AccessibilityObjectWrapperAtk.cpp
+++ b/WebCore/accessibility/gtk/AccessibilityObjectWrapperAtk.cpp
@@ -58,6 +58,7 @@
 #include "RenderListItem.h"
 #include "RenderListMarker.h"
 #include "RenderText.h"
+#include "SelectElement.h"
 #include "TextEncoding.h"
 #include "TextIterator.h"
 #include "WebKitAccessibleHyperlink.h"
@@ -500,6 +501,12 @@ static void setAtkStateSetFromCoreObject(AccessibilityObject* coreObject, AtkSta
         atk_state_set_add_state(stateSet, ATK_STATE_SENSITIVE);
     }
 
+    if (coreObject->canSetExpandedAttribute())
+        atk_state_set_add_state(stateSet, ATK_STATE_EXPANDABLE);
+
+    if (coreObject->isExpanded())
+        atk_state_set_add_state(stateSet, ATK_STATE_EXPANDED);
+
     if (coreObject->canSetFocusAttribute())
         atk_state_set_add_state(stateSet, ATK_STATE_FOCUSABLE);
 
@@ -694,13 +701,44 @@ static void atk_action_interface_init(AtkActionIface* iface)
 
 // Selection (for controls)
 
+static AccessibilityObject* listObjectForSelection(AtkSelection* selection)
+{
+    AccessibilityObject* coreSelection = core(selection);
+
+    // Only list boxes and menu lists supported so far.
+    if (!coreSelection->isListBox() && !coreSelection->isMenuList())
+        return 0;
+
+    // For list boxes the list object is just itself.
+    if (coreSelection->isListBox())
+        return coreSelection;
+
+    // For menu lists we need to return the first accessible child,
+    // with role MenuListPopupRole, since that's the one holding the list
+    // of items with role MenuListOptionRole.
+    AccessibilityObject::AccessibilityChildrenVector children = coreSelection->children();
+    if (!children.size())
+        return 0;
+
+    AccessibilityObject* listObject = children.at(0).get();
+    if (!listObject->isMenuListPopup())
+        return 0;
+
+    return listObject;
+}
+
 static AccessibilityObject* optionFromList(AtkSelection* selection, gint i)
 {
     AccessibilityObject* coreSelection = core(selection);
     if (!coreSelection || i < 0)
         return 0;
 
-    AccessibilityRenderObject::AccessibilityChildrenVector options = core(selection)->children();
+    // Need to select the proper list object depending on the type.
+    AccessibilityObject* listObject = listObjectForSelection(selection);
+    if (!listObject)
+        return 0;
+
+    AccessibilityRenderObject::AccessibilityChildrenVector options = listObject->children();
     if (i < static_cast<gint>(options.size()))
         return options.at(i).get();
 
@@ -712,14 +750,26 @@ static AccessibilityObject* optionFromSelection(AtkSelection* selection, gint i)
     // i is the ith selection as opposed to the ith child.
 
     AccessibilityObject* coreSelection = core(selection);
-    if (!coreSelection || i < 0)
+    if (!coreSelection || !coreSelection->isAccessibilityRenderObject() || i < 0)
         return 0;
 
     AccessibilityRenderObject::AccessibilityChildrenVector selectedItems;
     if (coreSelection->isListBox())
-        static_cast<AccessibilityListBox*>(coreSelection)->selectedChildren(selectedItems);
+        coreSelection->selectedChildren(selectedItems);
+    else if (coreSelection->isMenuList()) {
+        RenderObject* renderer = toAccessibilityRenderObject(coreSelection)->renderer();
+        if (!renderer)
+            return 0;
+
+        SelectElement* selectNode = toSelectElement(static_cast<Element*>(renderer->node()));
+        int selectedIndex = selectNode->selectedIndex();
+        const Vector<Element*> listItems = selectNode->listItems();
 
-    // TODO: Combo boxes
+        if (selectedIndex < 0 || selectedIndex >= static_cast<int>(listItems.size()))
+            return 0;
+
+        return optionFromList(selection, selectedIndex);
+    }
 
     if (i < static_cast<gint>(selectedItems.size()))
         return selectedItems.at(i).get();
@@ -729,11 +779,14 @@ static AccessibilityObject* optionFromSelection(AtkSelection* selection, gint i)
 
 static gboolean webkit_accessible_selection_add_selection(AtkSelection* selection, gint i)
 {
+    AccessibilityObject* coreSelection = core(selection);
+    if (!coreSelection)
+        return false;
+
     AccessibilityObject* option = optionFromList(selection, i);
-    if (option && core(selection)->isListBox()) {
-        AccessibilityListBoxOption* listBoxOption = static_cast<AccessibilityListBoxOption*>(option);
-        listBoxOption->setSelected(true);
-        return listBoxOption->isSelected();
+    if (option && (coreSelection->isListBox() || coreSelection->isMenuList())) {
+        option->setSelected(true);
+        return option->isSelected();
     }
 
     return false;
@@ -746,7 +799,7 @@ static gboolean webkit_accessible_selection_clear_selection(AtkSelection* select
         return false;
 
     AccessibilityRenderObject::AccessibilityChildrenVector selectedItems;
-    if (coreSelection->isListBox()) {
+    if (coreSelection->isListBox() || coreSelection->isMenuList()) {
         // Set the list of selected items to an empty list; then verify that it worked.
         AccessibilityListBox* listBox = static_cast<AccessibilityListBox*>(coreSelection);
         listBox->setSelectedChildren(selectedItems);
@@ -771,32 +824,54 @@ static AtkObject* webkit_accessible_selection_ref_selection(AtkSelection* select
 static gint webkit_accessible_selection_get_selection_count(AtkSelection* selection)
 {
     AccessibilityObject* coreSelection = core(selection);
-    if (coreSelection && coreSelection->isListBox()) {
+    if (!coreSelection || !coreSelection->isAccessibilityRenderObject())
+        return 0;
+
+    if (coreSelection->isListBox()) {
         AccessibilityRenderObject::AccessibilityChildrenVector selectedItems;
-        static_cast<AccessibilityListBox*>(coreSelection)->selectedChildren(selectedItems);
+        coreSelection->selectedChildren(selectedItems);
         return static_cast<gint>(selectedItems.size());
     }
 
+    if (coreSelection->isMenuList()) {
+        RenderObject* renderer = toAccessibilityRenderObject(coreSelection)->renderer();
+        if (!renderer)
+            return 0;
+
+        SelectElement* selectNode = toSelectElement(static_cast<Element*>(renderer->node()));
+        int selectedIndex = selectNode->selectedIndex();
+        const Vector<Element*> listItems = selectNode->listItems();
+
+        return selectedIndex >= 0 && selectedIndex < static_cast<int>(listItems.size());
+    }
+
     return 0;
 }
 
 static gboolean webkit_accessible_selection_is_child_selected(AtkSelection* selection, gint i)
 {
+    AccessibilityObject* coreSelection = core(selection);
+    if (!coreSelection)
+        return 0;
+
     AccessibilityObject* option = optionFromList(selection, i);
-    if (option && core(selection)->isListBox())
-        return static_cast<AccessibilityListBoxOption*>(option)->isSelected();
+    if (option && (coreSelection->isListBox() || coreSelection->isMenuList()))
+        return option->isSelected();
 
     return false;
 }
 
 static gboolean webkit_accessible_selection_remove_selection(AtkSelection* selection, gint i)
 {
+    AccessibilityObject* coreSelection = core(selection);
+    if (!coreSelection)
+        return 0;
+
     // TODO: This is only getting called if i == 0. What is preventing the rest?
     AccessibilityObject* option = optionFromSelection(selection, i);
-    if (option && core(selection)->isListBox()) {
-        AccessibilityListBoxOption* listBoxOption = static_cast<AccessibilityListBoxOption*>(option);
-        listBoxOption->setSelected(false);
-        return !listBoxOption->isSelected();
+    if (option && (coreSelection->isListBox() || coreSelection->isMenuList())) {
+        option->setSelected(false);
+        return !option->isSelected();
     }
 
     return false;
@@ -969,8 +1044,11 @@ static gchar* webkit_accessible_text_get_text(AtkText* text, gint startOffset, g
 
     if (coreObject->isTextControl())
         ret = coreObject->doAXStringForRange(PlainTextRange(start, length));
-    else
-        ret = coreObject->textUnderElement().substring(start, length);
+    else {
+        ret = coreObject->stringValue().substring(start, length);
+        if (!ret)
+            ret = coreObject->textUnderElement().substring(start, length);
+    }
 
     if (!ret.length()) {
         // This can happen at least with anonymous RenderBlocks (e.g. body text amongst paragraphs)
@@ -2177,19 +2255,23 @@ static guint16 getInterfaceMaskFromObject(AccessibilityObject* coreObject)
     AccessibilityRole role = coreObject->roleValue();
 
     // Action
-    if (!coreObject->actionVerb().isEmpty()) {
-        interfaceMask |= 1 << WAI_ACTION;
+    // As the implementation of the AtkAction interface is a very
+    // basic one (just relays in executing the default action for each
+    // object, and only supports having one action per object), it is
+    // better just to implement this interface for every instance of
+    // the WebKitAccessible class and let WebCore decide what to do.
+    interfaceMask |= 1 << WAI_ACTION;
 
-        if (!coreObject->accessibilityIsIgnored() && coreObject->isLink())
-            interfaceMask |= 1 << WAI_HYPERLINK;
-    }
+    // Hyperlink
+    if (coreObject->isLink())
+        interfaceMask |= 1 << WAI_HYPERLINK;
 
     // Selection
-    if (coreObject->isListBox())
+    if (coreObject->isListBox() || coreObject->isMenuList())
         interfaceMask |= 1 << WAI_SELECTION;
 
     // Text & Editable Text
-    if (role == StaticTextRole)
+    if (role == StaticTextRole || coreObject->isMenuListOption())
         interfaceMask |= 1 << WAI_TEXT;
     else if (coreObject->isAccessibilityRenderObject()) {
         if (coreObject->isTextControl()) {
diff --git a/WebCore/platform/gtk/PopupMenuGtk.cpp b/WebCore/platform/gtk/PopupMenuGtk.cpp
index e7ff78e..07ca912 100644
--- a/WebCore/platform/gtk/PopupMenuGtk.cpp
+++ b/WebCore/platform/gtk/PopupMenuGtk.cpp
@@ -58,8 +58,11 @@ void PopupMenuGtk::show(const IntRect& rect, FrameView* view, int index)
     } else
         gtk_container_foreach(GTK_CONTAINER(m_popup.get()), reinterpret_cast<GtkCallback>(menuRemoveItem), this);
 
-    int x, y;
-    gdk_window_get_origin(gtk_widget_get_window(GTK_WIDGET(view->hostWindow()->platformPageClient())), &x, &y);
+    int x = 0;
+    int y = 0;
+    GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(view->hostWindow()->platformPageClient()));
+    if (window)
+        gdk_window_get_origin(window, &x, &y);
     m_menuPosition = view->contentsToWindow(rect.location());
     m_menuPosition = IntPoint(m_menuPosition.x() + x, m_menuPosition.y() + y + rect.height());
     m_indexMap.clear();
diff --git a/WebKit/gtk/ChangeLog b/WebKit/gtk/ChangeLog
index 6728af5..3305bcb 100644
--- a/WebKit/gtk/ChangeLog
+++ b/WebKit/gtk/ChangeLog
@@ -1,3 +1,17 @@
+2010-11-21  Mario Sanchez Prada  <msanchez at igalia.com>
+
+        Reviewed by Chris Fleizach.
+
+        [GTK] Implement ROLE_COMBO_BOX
+        https://bugs.webkit.org/show_bug.cgi?id=25678
+
+        New test to check the implementation of the combo boxes.
+
+        * tests/testatk.c:
+        (testWebkitAtkComboBox): New test, checking that the roles and the
+        implemented interfaces for a combo box and its descendants work.
+        (main): Added the new unit test.
+
 2010-11-20  Xan Lopez  <xlopez at igalia.com>
 
         Reviewed by Martin Robinson.
diff --git a/WebKit/gtk/tests/testatk.c b/WebKit/gtk/tests/testatk.c
index f098f62..abd6091 100644
--- a/WebKit/gtk/tests/testatk.c
+++ b/WebKit/gtk/tests/testatk.c
@@ -44,6 +44,8 @@ static const char* contentsInTable = "<html><body><table><tr><td>foo</td><td>bar
 
 static const char* contentsInTableWithHeaders = "<html><body><table><tr><th>foo</th><th>bar</th><th colspan='2'>baz</th></tr><tr><th>qux</th><td>1</td><td>2</td><td>3</td></tr><tr><th rowspan='2'>quux</th><td>4</td><td>5</td><td>6</td></tr><tr><td>6</td><td>7</td><td>8</td></tr><tr><th>corge</th><td>9</td><td>10</td><td>11</td></tr></table><table><tr><td>1</td><td>2</td></tr><tr><td>3</td><td>4</td></tr></table></body></html>";
 
+static const char* comboBoxSelector = "<html><body><select><option selected value='foo'>foo</option><option value='bar'>bar</option></select></body></html>";
+
 static const char* formWithTextInputs = "<html><body><form><input type='text' name='entry' /></form></body></html>";
 
 static const char* hypertextAndHyperlinks = "<html><body><p>A paragraph with no links at all</p><p><a href='http://foo.bar.baz/'>A line</a> with <a href='http://bar.baz.foo/'>a link in the middle</a> as well as at the beginning and <a href='http://baz.foo.bar/'>at the end</a></p></body></html>";
@@ -221,6 +223,107 @@ static void runGetTextTests(AtkText* textObject)
                         0, "This is a test. This is the second sentence. And this the third.", 0, 64);
 }
 
+static void testWebkitAtkComboBox()
+{
+    WebKitWebView* webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
+    g_object_ref_sink(webView);
+    GtkAllocation allocation = { 0, 0, 800, 600 };
+    gtk_widget_size_allocate(GTK_WIDGET(webView), &allocation);
+    webkit_web_view_load_string(webView, comboBoxSelector, 0, 0, 0);
+
+    /* Wait for the accessible objects to be created. */
+    waitForAccessibleObjects();
+
+    AtkObject* object = gtk_widget_get_accessible(GTK_WIDGET(webView));
+    g_assert(object);
+
+    AtkObject* formObject = atk_object_ref_accessible_child(object, 0);
+    g_assert(formObject);
+
+    AtkObject* comboBox = atk_object_ref_accessible_child(formObject, 0);
+    g_assert(ATK_IS_OBJECT(comboBox));
+
+    AtkObject* menuPopup = atk_object_ref_accessible_child(comboBox, 0);
+    g_assert(ATK_IS_OBJECT(menuPopup));
+
+    AtkObject* item1 = atk_object_ref_accessible_child(menuPopup, 0);
+    g_assert(ATK_IS_OBJECT(item1));
+
+    AtkObject* item2 = atk_object_ref_accessible_child(menuPopup, 1);
+    g_assert(ATK_IS_OBJECT(item2));
+
+    /* Check roles. */
+    g_assert(atk_object_get_role(comboBox) == ATK_ROLE_COMBO_BOX);
+    g_assert(atk_object_get_role(menuPopup) == ATK_ROLE_MENU);
+    g_assert(atk_object_get_role(item1) == ATK_ROLE_MENU_ITEM);
+    g_assert(atk_object_get_role(item2) == ATK_ROLE_MENU_ITEM);
+
+    /* Check the implementation of the AtkSelection interface. */
+    g_assert(ATK_IS_SELECTION(comboBox));
+    AtkSelection* atkSelection = ATK_SELECTION(comboBox);
+    g_assert_cmpint(atk_selection_get_selection_count(atkSelection), ==, 1);
+    g_assert(atk_selection_is_child_selected(atkSelection, 0));
+    g_assert(!atk_selection_is_child_selected(atkSelection, 1));
+    AtkObject* selectedItem = atk_selection_ref_selection(atkSelection, 0);
+    g_assert(selectedItem == item1);
+    g_object_unref(selectedItem);
+
+    /* Check the implementations of the AtkAction interface. */
+    g_assert(ATK_IS_ACTION(comboBox));
+    AtkAction* atkAction = ATK_ACTION(comboBox);
+    g_assert_cmpint(atk_action_get_n_actions(atkAction), ==, 1);
+    g_assert(atk_action_do_action(atkAction, 0));
+
+    g_assert(ATK_IS_ACTION(menuPopup));
+    atkAction = ATK_ACTION(menuPopup);
+    g_assert_cmpint(atk_action_get_n_actions(atkAction), ==, 1);
+    g_assert(atk_action_do_action(atkAction, 0));
+
+    g_assert(ATK_IS_ACTION(item1));
+    atkAction = ATK_ACTION(item1);
+    g_assert_cmpint(atk_action_get_n_actions(atkAction), ==, 1);
+    g_assert(atk_action_do_action(atkAction, 0));
+
+    g_assert(ATK_IS_ACTION(item2));
+    atkAction = ATK_ACTION(item2);
+    g_assert_cmpint(atk_action_get_n_actions(atkAction), ==, 1);
+    g_assert(atk_action_do_action(atkAction, 0));
+
+    /* After selecting the second item, selection should have changed. */
+    g_assert_cmpint(atk_selection_get_selection_count(atkSelection), ==, 1);
+    g_assert(!atk_selection_is_child_selected(atkSelection, 0));
+    g_assert(atk_selection_is_child_selected(atkSelection, 1));
+    selectedItem = atk_selection_ref_selection(atkSelection, 0);
+    g_assert(selectedItem == item2);
+    g_object_unref(selectedItem);
+
+    /* Check the implementation of the AtkText interface. */
+    g_assert(ATK_IS_TEXT(item1));
+    AtkText* atkText = ATK_TEXT(item1);
+    char *text = atk_text_get_text(atkText, 0, -1);
+    g_assert_cmpstr(text, ==, "foo");
+    g_free(text);
+    text = atk_text_get_text(atkText, 0, 2);
+    g_assert_cmpstr(text, ==, "fo");
+    g_free(text);
+
+    g_assert(ATK_IS_TEXT(item2));
+    atkText = ATK_TEXT(item2);
+    text = atk_text_get_text(atkText, 0, -1);
+    g_assert_cmpstr(text, ==, "bar");
+    g_free(text);
+    text = atk_text_get_text(atkText, 1, 3);
+    g_assert_cmpstr(text, ==, "ar");
+    g_free(text);
+
+    g_object_unref(formObject);
+    g_object_unref(comboBox);
+    g_object_unref(menuPopup);
+    g_object_unref(item1);
+    g_object_unref(item2);
+    g_object_unref(webView);
+}
+
 static void testWebkitAtkGetTextAtOffsetForms()
 {
     WebKitWebView* webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
@@ -1211,6 +1314,7 @@ int main(int argc, char** argv)
     gtk_test_init(&argc, &argv, 0);
 
     g_test_bug_base("https://bugs.webkit.org/");
+    g_test_add_func("/webkit/atk/comboBox", testWebkitAtkComboBox);
     g_test_add_func("/webkit/atk/getTextAtOffset", testWebkitAtkGetTextAtOffset);
     g_test_add_func("/webkit/atk/getTextAtOffsetForms", testWebkitAtkGetTextAtOffsetForms);
     g_test_add_func("/webkit/atk/getTextAtOffsetNewlines", testWebkitAtkGetTextAtOffsetNewlines);

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list