Changeset 72958 in webkit
- Timestamp:
- Nov 30, 2010 1:16:14 PM (13 years ago)
- Location:
- trunk
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/WebCore/ChangeLog
r72956 r72958 1 2010-11-30 Mario Sanchez Prada <msanchez@igalia.com> 2 3 Reviewed by Chris Fleizach. 4 5 [GTK] Implement ROLE_COMBO_BOX 6 https://bugs.webkit.org/show_bug.cgi?id=25678 7 8 Implement the remaining bits for combo boxes. 9 10 This patch finishes the implementation, from the point of view of 11 the Atk library, of those objects exposed to ATK as combo boxes, 12 and their related elements (menus and menu items). It therefore 13 implements the proper interfaces for each type of object related 14 to combo boxes (AtkSelection for the combo box, AtkText for every 15 menu item and AtkAction for the combo box, the menu and the menu 16 items), takes care of emitting the proper signals when focus or a 17 given a selection changes and adds a new unit test to check all 18 this new stuff. 19 20 Make possible to ask an AccessibleMenuListOption for a sensible 21 string representation, so far only available through the private 22 and MSAA related method nameForMSAA. Just moved the implementation 23 of that method to an overriden version of stringValue(), which is 24 platform independent, and called that from nameForMSAA(). 25 26 * accessibility/AccessibilityMenuListOption.h: 27 * accessibility/AccessibilityMenuListOption.cpp: 28 (WebCore::AccessibilityMenuListOption::nameForMSAA): Just call to 29 stringValue(), which holds from now on that used to be here. 30 (WebCore::AccessibilityMenuListOption::stringValue): New, override 31 of AccessibilityObject::stringValue() to return a proper string. 32 33 Emit the missing signals when a selection is made. 34 35 * accessibility/gtk/AXObjectCacheAtk.cpp: 36 (WebCore::AXObjectCache::postPlatformNotification): Emit the usual 37 'focus' signals when a selection is made over the combo box. 38 39 * accessibility/gtk/AccessibilityObjectWrapperAtk.cpp: 40 (setAtkStateSetFromCoreObject): Ensure the EXPANDABLE and EXPANDED 41 Atk states are added to the state set when needed. 42 (listObjectForSelection): New, returns the proper list object (the 43 one holding the list of available options as its children) for an 44 specific AtkObject implementing AtkSelection. This is needed 45 because sometimes the selectable options are not directly children 46 of the AtkSelection object (i.e. a combo box has a 'menu' object 47 as its only child of it, holding the list of options as children). 48 (optionFromList): Use listObjectForSelection() to get the actual 49 object holding the list of children as the available options. 50 (optionFromSelection): Add support for combo boxes. 51 (webkit_accessible_selection_add_selection): Ditto. 52 (webkit_accessible_selection_clear_selection): Ditto. 53 (webkit_accessible_selection_get_selection_count): Ditto. 54 (webkit_accessible_selection_is_child_selected): Ditto. 55 (webkit_accessible_selection_remove_selection): Ditto. 56 (webkit_accessible_text_get_text): Makes sure stringValue() is 57 considered to get the result substring when it was already 58 considered when checking the maximum text length for the object. 59 (getInterfaceMaskFromObject): Make sure the AtkSelection interface 60 is implemented for the combo boxes, that the AtkText is 61 implemented for the menu items and that the AtkAction interface is 62 now implemented for every object (WebCore will decide what to do). 63 64 Avoid a segfault crash when using this from unit tests. 65 66 * platform/gtk/PopupMenuGtk.cpp: 67 (WebCore::PopupMenuGtk::show): Make sure we got a valid GdkWindow 68 before calling gdk_window_get_origin() over it. 69 1 70 2010-11-30 Andreas Kling <kling@webkit.org> 2 71 -
trunk/WebCore/accessibility/AccessibilityMenuListOption.cpp
r72673 r72958 92 92 String AccessibilityMenuListOption::nameForMSAA() const 93 93 { 94 return st atic_cast<HTMLOptionElement*>(m_element.get())->text();94 return stringValue(); 95 95 } 96 96 … … 111 111 } 112 112 113 String AccessibilityMenuListOption::stringValue() const 114 { 115 return static_cast<HTMLOptionElement*>(m_element.get())->text(); 116 } 117 113 118 } // namespace WebCore -
trunk/WebCore/accessibility/AccessibilityMenuListOption.h
r72673 r72958 60 60 virtual bool canSetSelectedAttribute() const; 61 61 virtual IntRect elementRect() const; 62 virtual String stringValue() const; 62 63 63 64 RefPtr<HTMLElement> m_element; -
trunk/WebCore/accessibility/gtk/AXObjectCacheAtk.cpp
r72673 r72958 96 96 void AXObjectCache::postPlatformNotification(AccessibilityObject* coreObject, AXNotification notification) 97 97 { 98 AtkObject* axObject = coreObject->wrapper(); 99 if (!axObject) 100 return; 101 98 102 if (notification == AXCheckedStateChanged) { 99 103 if (!coreObject->isCheckboxOrRadio()) 100 104 return; 101 g_signal_emit_by_name(coreObject->wrapper(), "state-change", "checked", coreObject->isChecked()); 105 g_signal_emit_by_name(axObject, "state-change", "checked", coreObject->isChecked()); 106 } else if (notification == AXMenuListValueChanged) { 107 if (!coreObject->isMenuList()) 108 return; 109 g_signal_emit_by_name(axObject, "focus-event", true); 110 g_signal_emit_by_name(axObject, "state-change", "focused", true); 102 111 } else if (notification == AXSelectedChildrenChanged) 103 112 notifyChildrenSelectionChange(coreObject); -
trunk/WebCore/accessibility/gtk/AccessibilityObjectWrapperAtk.cpp
r72904 r72958 59 59 #include "RenderListMarker.h" 60 60 #include "RenderText.h" 61 #include "SelectElement.h" 61 62 #include "TextEncoding.h" 62 63 #include "TextIterator.h" … … 501 502 } 502 503 504 if (coreObject->canSetExpandedAttribute()) 505 atk_state_set_add_state(stateSet, ATK_STATE_EXPANDABLE); 506 507 if (coreObject->isExpanded()) 508 atk_state_set_add_state(stateSet, ATK_STATE_EXPANDED); 509 503 510 if (coreObject->canSetFocusAttribute()) 504 511 atk_state_set_add_state(stateSet, ATK_STATE_FOCUSABLE); … … 695 702 // Selection (for controls) 696 703 704 static AccessibilityObject* listObjectForSelection(AtkSelection* selection) 705 { 706 AccessibilityObject* coreSelection = core(selection); 707 708 // Only list boxes and menu lists supported so far. 709 if (!coreSelection->isListBox() && !coreSelection->isMenuList()) 710 return 0; 711 712 // For list boxes the list object is just itself. 713 if (coreSelection->isListBox()) 714 return coreSelection; 715 716 // For menu lists we need to return the first accessible child, 717 // with role MenuListPopupRole, since that's the one holding the list 718 // of items with role MenuListOptionRole. 719 AccessibilityObject::AccessibilityChildrenVector children = coreSelection->children(); 720 if (!children.size()) 721 return 0; 722 723 AccessibilityObject* listObject = children.at(0).get(); 724 if (!listObject->isMenuListPopup()) 725 return 0; 726 727 return listObject; 728 } 729 697 730 static AccessibilityObject* optionFromList(AtkSelection* selection, gint i) 698 731 { … … 701 734 return 0; 702 735 703 AccessibilityRenderObject::AccessibilityChildrenVector options = core(selection)->children(); 736 // Need to select the proper list object depending on the type. 737 AccessibilityObject* listObject = listObjectForSelection(selection); 738 if (!listObject) 739 return 0; 740 741 AccessibilityRenderObject::AccessibilityChildrenVector options = listObject->children(); 704 742 if (i < static_cast<gint>(options.size())) 705 743 return options.at(i).get(); … … 713 751 714 752 AccessibilityObject* coreSelection = core(selection); 715 if (!coreSelection || i < 0)753 if (!coreSelection || !coreSelection->isAccessibilityRenderObject() || i < 0) 716 754 return 0; 717 755 718 756 AccessibilityRenderObject::AccessibilityChildrenVector selectedItems; 719 757 if (coreSelection->isListBox()) 720 static_cast<AccessibilityListBox*>(coreSelection)->selectedChildren(selectedItems); 721 722 // TODO: Combo boxes 758 coreSelection->selectedChildren(selectedItems); 759 else if (coreSelection->isMenuList()) { 760 RenderObject* renderer = toAccessibilityRenderObject(coreSelection)->renderer(); 761 if (!renderer) 762 return 0; 763 764 SelectElement* selectNode = toSelectElement(static_cast<Element*>(renderer->node())); 765 int selectedIndex = selectNode->selectedIndex(); 766 const Vector<Element*> listItems = selectNode->listItems(); 767 768 if (selectedIndex < 0 || selectedIndex >= static_cast<int>(listItems.size())) 769 return 0; 770 771 return optionFromList(selection, selectedIndex); 772 } 723 773 724 774 if (i < static_cast<gint>(selectedItems.size())) … … 729 779 730 780 static gboolean webkit_accessible_selection_add_selection(AtkSelection* selection, gint i) 731 {732 AccessibilityObject* option = optionFromList(selection, i);733 if (option && core(selection)->isListBox()) {734 AccessibilityListBoxOption* listBoxOption = static_cast<AccessibilityListBoxOption*>(option);735 listBoxOption->setSelected(true);736 return listBoxOption->isSelected();737 }738 739 return false;740 }741 742 static gboolean webkit_accessible_selection_clear_selection(AtkSelection* selection)743 781 { 744 782 AccessibilityObject* coreSelection = core(selection); … … 746 784 return false; 747 785 786 AccessibilityObject* option = optionFromList(selection, i); 787 if (option && (coreSelection->isListBox() || coreSelection->isMenuList())) { 788 option->setSelected(true); 789 return option->isSelected(); 790 } 791 792 return false; 793 } 794 795 static gboolean webkit_accessible_selection_clear_selection(AtkSelection* selection) 796 { 797 AccessibilityObject* coreSelection = core(selection); 798 if (!coreSelection) 799 return false; 800 748 801 AccessibilityRenderObject::AccessibilityChildrenVector selectedItems; 749 if (coreSelection->isListBox() ) {802 if (coreSelection->isListBox() || coreSelection->isMenuList()) { 750 803 // Set the list of selected items to an empty list; then verify that it worked. 751 804 AccessibilityListBox* listBox = static_cast<AccessibilityListBox*>(coreSelection); … … 772 825 { 773 826 AccessibilityObject* coreSelection = core(selection); 774 if (coreSelection && coreSelection->isListBox()) { 827 if (!coreSelection || !coreSelection->isAccessibilityRenderObject()) 828 return 0; 829 830 if (coreSelection->isListBox()) { 775 831 AccessibilityRenderObject::AccessibilityChildrenVector selectedItems; 776 static_cast<AccessibilityListBox*>(coreSelection)->selectedChildren(selectedItems);832 coreSelection->selectedChildren(selectedItems); 777 833 return static_cast<gint>(selectedItems.size()); 778 834 } 779 835 836 if (coreSelection->isMenuList()) { 837 RenderObject* renderer = toAccessibilityRenderObject(coreSelection)->renderer(); 838 if (!renderer) 839 return 0; 840 841 SelectElement* selectNode = toSelectElement(static_cast<Element*>(renderer->node())); 842 int selectedIndex = selectNode->selectedIndex(); 843 const Vector<Element*> listItems = selectNode->listItems(); 844 845 return selectedIndex >= 0 && selectedIndex < static_cast<int>(listItems.size()); 846 } 847 780 848 return 0; 781 849 } … … 783 851 static gboolean webkit_accessible_selection_is_child_selected(AtkSelection* selection, gint i) 784 852 { 853 AccessibilityObject* coreSelection = core(selection); 854 if (!coreSelection) 855 return 0; 856 785 857 AccessibilityObject* option = optionFromList(selection, i); 786 if (option && core(selection)->isListBox())787 return static_cast<AccessibilityListBoxOption*>(option)->isSelected();858 if (option && (coreSelection->isListBox() || coreSelection->isMenuList())) 859 return option->isSelected(); 788 860 789 861 return false; … … 792 864 static gboolean webkit_accessible_selection_remove_selection(AtkSelection* selection, gint i) 793 865 { 866 AccessibilityObject* coreSelection = core(selection); 867 if (!coreSelection) 868 return 0; 869 794 870 // TODO: This is only getting called if i == 0. What is preventing the rest? 795 871 AccessibilityObject* option = optionFromSelection(selection, i); 796 if (option && core(selection)->isListBox()) { 797 AccessibilityListBoxOption* listBoxOption = static_cast<AccessibilityListBoxOption*>(option); 798 listBoxOption->setSelected(false); 799 return !listBoxOption->isSelected(); 872 if (option && (coreSelection->isListBox() || coreSelection->isMenuList())) { 873 option->setSelected(false); 874 return !option->isSelected(); 800 875 } 801 876 … … 970 1045 if (coreObject->isTextControl()) 971 1046 ret = coreObject->doAXStringForRange(PlainTextRange(start, length)); 972 else 973 ret = coreObject->textUnderElement().substring(start, length); 1047 else { 1048 ret = coreObject->stringValue().substring(start, length); 1049 if (!ret) 1050 ret = coreObject->textUnderElement().substring(start, length); 1051 } 974 1052 975 1053 if (!ret.length()) { … … 2178 2256 2179 2257 // Action 2180 if (!coreObject->actionVerb().isEmpty()) { 2181 interfaceMask |= 1 << WAI_ACTION; 2182 2183 if (!coreObject->accessibilityIsIgnored() && coreObject->isLink()) 2184 interfaceMask |= 1 << WAI_HYPERLINK; 2185 } 2258 // As the implementation of the AtkAction interface is a very 2259 // basic one (just relays in executing the default action for each 2260 // object, and only supports having one action per object), it is 2261 // better just to implement this interface for every instance of 2262 // the WebKitAccessible class and let WebCore decide what to do. 2263 interfaceMask |= 1 << WAI_ACTION; 2264 2265 // Hyperlink 2266 if (coreObject->isLink()) 2267 interfaceMask |= 1 << WAI_HYPERLINK; 2186 2268 2187 2269 // Selection 2188 if (coreObject->isListBox() )2270 if (coreObject->isListBox() || coreObject->isMenuList()) 2189 2271 interfaceMask |= 1 << WAI_SELECTION; 2190 2272 2191 2273 // Text & Editable Text 2192 if (role == StaticTextRole )2274 if (role == StaticTextRole || coreObject->isMenuListOption()) 2193 2275 interfaceMask |= 1 << WAI_TEXT; 2194 2276 else if (coreObject->isAccessibilityRenderObject()) { -
trunk/WebCore/platform/gtk/PopupMenuGtk.cpp
r72673 r72958 59 59 gtk_container_foreach(GTK_CONTAINER(m_popup.get()), reinterpret_cast<GtkCallback>(menuRemoveItem), this); 60 60 61 int x, y; 62 gdk_window_get_origin(gtk_widget_get_window(GTK_WIDGET(view->hostWindow()->platformPageClient())), &x, &y); 61 int x = 0; 62 int y = 0; 63 GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(view->hostWindow()->platformPageClient())); 64 if (window) 65 gdk_window_get_origin(window, &x, &y); 63 66 m_menuPosition = view->contentsToWindow(rect.location()); 64 67 m_menuPosition = IntPoint(m_menuPosition.x() + x, m_menuPosition.y() + y + rect.height()); -
trunk/WebKit/gtk/ChangeLog
r72909 r72958 1 2010-11-30 Mario Sanchez Prada <msanchez@igalia.com> 2 3 Reviewed by Chris Fleizach. 4 5 [GTK] Implement ROLE_COMBO_BOX 6 https://bugs.webkit.org/show_bug.cgi?id=25678 7 8 New test to check the implementation of the combo boxes. 9 10 * tests/testatk.c: 11 (testWebkitAtkComboBox): New test, checking that the roles and the 12 implemented interfaces for a combo box and its descendants work. 13 (main): Added the new unit test. 14 1 15 2010-11-30 Carlos Garcia Campos <cgarcia@igalia.com> 2 16 -
trunk/WebKit/gtk/tests/testatk.c
r72904 r72958 45 45 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>"; 46 46 47 static const char* comboBoxSelector = "<html><body><select><option selected value='foo'>foo</option><option value='bar'>bar</option></select></body></html>"; 48 47 49 static const char* formWithTextInputs = "<html><body><form><input type='text' name='entry' /></form></body></html>"; 48 50 … … 220 222 testGetTextFunction(textObject, atk_text_get_text_at_offset, ATK_TEXT_BOUNDARY_LINE_END, 221 223 0, "This is a test. This is the second sentence. And this the third.", 0, 64); 224 } 225 226 static void testWebkitAtkComboBox() 227 { 228 WebKitWebView* webView = WEBKIT_WEB_VIEW(webkit_web_view_new()); 229 g_object_ref_sink(webView); 230 GtkAllocation allocation = { 0, 0, 800, 600 }; 231 gtk_widget_size_allocate(GTK_WIDGET(webView), &allocation); 232 webkit_web_view_load_string(webView, comboBoxSelector, 0, 0, 0); 233 234 /* Wait for the accessible objects to be created. */ 235 waitForAccessibleObjects(); 236 237 AtkObject* object = gtk_widget_get_accessible(GTK_WIDGET(webView)); 238 g_assert(object); 239 240 AtkObject* formObject = atk_object_ref_accessible_child(object, 0); 241 g_assert(formObject); 242 243 AtkObject* comboBox = atk_object_ref_accessible_child(formObject, 0); 244 g_assert(ATK_IS_OBJECT(comboBox)); 245 246 AtkObject* menuPopup = atk_object_ref_accessible_child(comboBox, 0); 247 g_assert(ATK_IS_OBJECT(menuPopup)); 248 249 AtkObject* item1 = atk_object_ref_accessible_child(menuPopup, 0); 250 g_assert(ATK_IS_OBJECT(item1)); 251 252 AtkObject* item2 = atk_object_ref_accessible_child(menuPopup, 1); 253 g_assert(ATK_IS_OBJECT(item2)); 254 255 /* Check roles. */ 256 g_assert(atk_object_get_role(comboBox) == ATK_ROLE_COMBO_BOX); 257 g_assert(atk_object_get_role(menuPopup) == ATK_ROLE_MENU); 258 g_assert(atk_object_get_role(item1) == ATK_ROLE_MENU_ITEM); 259 g_assert(atk_object_get_role(item2) == ATK_ROLE_MENU_ITEM); 260 261 /* Check the implementation of the AtkSelection interface. */ 262 g_assert(ATK_IS_SELECTION(comboBox)); 263 AtkSelection* atkSelection = ATK_SELECTION(comboBox); 264 g_assert_cmpint(atk_selection_get_selection_count(atkSelection), ==, 1); 265 g_assert(atk_selection_is_child_selected(atkSelection, 0)); 266 g_assert(!atk_selection_is_child_selected(atkSelection, 1)); 267 AtkObject* selectedItem = atk_selection_ref_selection(atkSelection, 0); 268 g_assert(selectedItem == item1); 269 g_object_unref(selectedItem); 270 271 /* Check the implementations of the AtkAction interface. */ 272 g_assert(ATK_IS_ACTION(comboBox)); 273 AtkAction* atkAction = ATK_ACTION(comboBox); 274 g_assert_cmpint(atk_action_get_n_actions(atkAction), ==, 1); 275 g_assert(atk_action_do_action(atkAction, 0)); 276 277 g_assert(ATK_IS_ACTION(menuPopup)); 278 atkAction = ATK_ACTION(menuPopup); 279 g_assert_cmpint(atk_action_get_n_actions(atkAction), ==, 1); 280 g_assert(atk_action_do_action(atkAction, 0)); 281 282 g_assert(ATK_IS_ACTION(item1)); 283 atkAction = ATK_ACTION(item1); 284 g_assert_cmpint(atk_action_get_n_actions(atkAction), ==, 1); 285 g_assert(atk_action_do_action(atkAction, 0)); 286 287 g_assert(ATK_IS_ACTION(item2)); 288 atkAction = ATK_ACTION(item2); 289 g_assert_cmpint(atk_action_get_n_actions(atkAction), ==, 1); 290 g_assert(atk_action_do_action(atkAction, 0)); 291 292 /* After selecting the second item, selection should have changed. */ 293 g_assert_cmpint(atk_selection_get_selection_count(atkSelection), ==, 1); 294 g_assert(!atk_selection_is_child_selected(atkSelection, 0)); 295 g_assert(atk_selection_is_child_selected(atkSelection, 1)); 296 selectedItem = atk_selection_ref_selection(atkSelection, 0); 297 g_assert(selectedItem == item2); 298 g_object_unref(selectedItem); 299 300 /* Check the implementation of the AtkText interface. */ 301 g_assert(ATK_IS_TEXT(item1)); 302 AtkText* atkText = ATK_TEXT(item1); 303 char *text = atk_text_get_text(atkText, 0, -1); 304 g_assert_cmpstr(text, ==, "foo"); 305 g_free(text); 306 text = atk_text_get_text(atkText, 0, 2); 307 g_assert_cmpstr(text, ==, "fo"); 308 g_free(text); 309 310 g_assert(ATK_IS_TEXT(item2)); 311 atkText = ATK_TEXT(item2); 312 text = atk_text_get_text(atkText, 0, -1); 313 g_assert_cmpstr(text, ==, "bar"); 314 g_free(text); 315 text = atk_text_get_text(atkText, 1, 3); 316 g_assert_cmpstr(text, ==, "ar"); 317 g_free(text); 318 319 g_object_unref(formObject); 320 g_object_unref(comboBox); 321 g_object_unref(menuPopup); 322 g_object_unref(item1); 323 g_object_unref(item2); 324 g_object_unref(webView); 222 325 } 223 326 … … 1212 1315 1213 1316 g_test_bug_base("https://bugs.webkit.org/"); 1317 g_test_add_func("/webkit/atk/comboBox", testWebkitAtkComboBox); 1214 1318 g_test_add_func("/webkit/atk/getTextAtOffset", testWebkitAtkGetTextAtOffset); 1215 1319 g_test_add_func("/webkit/atk/getTextAtOffsetForms", testWebkitAtkGetTextAtOffsetForms);
Note: See TracChangeset
for help on using the changeset viewer.